View.java revision 99b254be5cc8ac800206480113dc09e4e19b6eb1
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    /**
2114     * The view's tag.
2115     * {@hide}
2116     *
2117     * @see #setTag(Object)
2118     * @see #getTag()
2119     */
2120    protected Object mTag = null;
2121
2122    // for mPrivateFlags:
2123    /** {@hide} */
2124    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2125    /** {@hide} */
2126    static final int PFLAG_FOCUSED                     = 0x00000002;
2127    /** {@hide} */
2128    static final int PFLAG_SELECTED                    = 0x00000004;
2129    /** {@hide} */
2130    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2131    /** {@hide} */
2132    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2133    /** {@hide} */
2134    static final int PFLAG_DRAWN                       = 0x00000020;
2135    /**
2136     * When this flag is set, this view is running an animation on behalf of its
2137     * children and should therefore not cancel invalidate requests, even if they
2138     * lie outside of this view's bounds.
2139     *
2140     * {@hide}
2141     */
2142    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2143    /** {@hide} */
2144    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2145    /** {@hide} */
2146    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2147    /** {@hide} */
2148    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2149    /** {@hide} */
2150    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2151    /** {@hide} */
2152    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2153    /** {@hide} */
2154    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2155
2156    private static final int PFLAG_PRESSED             = 0x00004000;
2157
2158    /** {@hide} */
2159    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2160    /**
2161     * Flag used to indicate that this view should be drawn once more (and only once
2162     * more) after its animation has completed.
2163     * {@hide}
2164     */
2165    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2166
2167    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2168
2169    /**
2170     * Indicates that the View returned true when onSetAlpha() was called and that
2171     * the alpha must be restored.
2172     * {@hide}
2173     */
2174    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2175
2176    /**
2177     * Set by {@link #setScrollContainer(boolean)}.
2178     */
2179    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2180
2181    /**
2182     * Set by {@link #setScrollContainer(boolean)}.
2183     */
2184    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2185
2186    /**
2187     * View flag indicating whether this view was invalidated (fully or partially.)
2188     *
2189     * @hide
2190     */
2191    static final int PFLAG_DIRTY                       = 0x00200000;
2192
2193    /**
2194     * View flag indicating whether this view was invalidated by an opaque
2195     * invalidate request.
2196     *
2197     * @hide
2198     */
2199    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2200
2201    /**
2202     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2203     *
2204     * @hide
2205     */
2206    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2207
2208    /**
2209     * Indicates whether the background is opaque.
2210     *
2211     * @hide
2212     */
2213    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2214
2215    /**
2216     * Indicates whether the scrollbars are opaque.
2217     *
2218     * @hide
2219     */
2220    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2221
2222    /**
2223     * Indicates whether the view is opaque.
2224     *
2225     * @hide
2226     */
2227    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2228
2229    /**
2230     * Indicates a prepressed state;
2231     * the short time between ACTION_DOWN and recognizing
2232     * a 'real' press. Prepressed is used to recognize quick taps
2233     * even when they are shorter than ViewConfiguration.getTapTimeout().
2234     *
2235     * @hide
2236     */
2237    private static final int PFLAG_PREPRESSED          = 0x02000000;
2238
2239    /**
2240     * Indicates whether the view is temporarily detached.
2241     *
2242     * @hide
2243     */
2244    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2245
2246    /**
2247     * Indicates that we should awaken scroll bars once attached
2248     *
2249     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2250     * during window attachment and it is no longer needed. Feel free to repurpose it.
2251     *
2252     * @hide
2253     */
2254    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2255
2256    /**
2257     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2258     * @hide
2259     */
2260    private static final int PFLAG_HOVERED             = 0x10000000;
2261
2262    /**
2263     * no longer needed, should be reused
2264     */
2265    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2266
2267    /** {@hide} */
2268    static final int PFLAG_ACTIVATED                   = 0x40000000;
2269
2270    /**
2271     * Indicates that this view was specifically invalidated, not just dirtied because some
2272     * child view was invalidated. The flag is used to determine when we need to recreate
2273     * a view's display list (as opposed to just returning a reference to its existing
2274     * display list).
2275     *
2276     * @hide
2277     */
2278    static final int PFLAG_INVALIDATED                 = 0x80000000;
2279
2280    /**
2281     * Masks for mPrivateFlags2, as generated by dumpFlags():
2282     *
2283     * |-------|-------|-------|-------|
2284     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2285     *                                1  PFLAG2_DRAG_HOVERED
2286     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2287     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2288     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2289     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2290     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2291     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2292     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2293     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2294     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2295     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2296     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2297     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2298     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2299     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2300     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2301     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2302     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2303     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2304     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2305     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2306     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2307     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2308     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2309     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2310     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2311     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2312     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2313     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2314     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2315     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2316     *    1                              PFLAG2_PADDING_RESOLVED
2317     *   1                               PFLAG2_DRAWABLE_RESOLVED
2318     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2319     * |-------|-------|-------|-------|
2320     */
2321
2322    /**
2323     * Indicates that this view has reported that it can accept the current drag's content.
2324     * Cleared when the drag operation concludes.
2325     * @hide
2326     */
2327    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2328
2329    /**
2330     * Indicates that this view is currently directly under the drag location in a
2331     * drag-and-drop operation involving content that it can accept.  Cleared when
2332     * the drag exits the view, or when the drag operation concludes.
2333     * @hide
2334     */
2335    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2336
2337    /** @hide */
2338    @IntDef({
2339        LAYOUT_DIRECTION_LTR,
2340        LAYOUT_DIRECTION_RTL,
2341        LAYOUT_DIRECTION_INHERIT,
2342        LAYOUT_DIRECTION_LOCALE
2343    })
2344    @Retention(RetentionPolicy.SOURCE)
2345    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2346    public @interface LayoutDir {}
2347
2348    /** @hide */
2349    @IntDef({
2350        LAYOUT_DIRECTION_LTR,
2351        LAYOUT_DIRECTION_RTL
2352    })
2353    @Retention(RetentionPolicy.SOURCE)
2354    public @interface ResolvedLayoutDir {}
2355
2356    /**
2357     * A flag to indicate that the layout direction of this view has not been defined yet.
2358     * @hide
2359     */
2360    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2361
2362    /**
2363     * Horizontal layout direction of this view is from Left to Right.
2364     * Use with {@link #setLayoutDirection}.
2365     */
2366    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2367
2368    /**
2369     * Horizontal layout direction of this view is from Right to Left.
2370     * Use with {@link #setLayoutDirection}.
2371     */
2372    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2373
2374    /**
2375     * Horizontal layout direction of this view is inherited from its parent.
2376     * Use with {@link #setLayoutDirection}.
2377     */
2378    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2379
2380    /**
2381     * Horizontal layout direction of this view is from deduced from the default language
2382     * script for the locale. Use with {@link #setLayoutDirection}.
2383     */
2384    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2385
2386    /**
2387     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2388     * @hide
2389     */
2390    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2391
2392    /**
2393     * Mask for use with private flags indicating bits used for horizontal layout direction.
2394     * @hide
2395     */
2396    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2397
2398    /**
2399     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2400     * right-to-left direction.
2401     * @hide
2402     */
2403    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2404
2405    /**
2406     * Indicates whether the view horizontal layout direction has been resolved.
2407     * @hide
2408     */
2409    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2410
2411    /**
2412     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2413     * @hide
2414     */
2415    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2416            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2417
2418    /*
2419     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2420     * flag value.
2421     * @hide
2422     */
2423    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2424            LAYOUT_DIRECTION_LTR,
2425            LAYOUT_DIRECTION_RTL,
2426            LAYOUT_DIRECTION_INHERIT,
2427            LAYOUT_DIRECTION_LOCALE
2428    };
2429
2430    /**
2431     * Default horizontal layout direction.
2432     */
2433    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2434
2435    /**
2436     * Default horizontal layout direction.
2437     * @hide
2438     */
2439    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2440
2441    /**
2442     * Text direction is inherited through {@link ViewGroup}
2443     */
2444    public static final int TEXT_DIRECTION_INHERIT = 0;
2445
2446    /**
2447     * Text direction is using "first strong algorithm". The first strong directional character
2448     * determines the paragraph direction. If there is no strong directional character, the
2449     * paragraph direction is the view's resolved layout direction.
2450     */
2451    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2452
2453    /**
2454     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2455     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2456     * If there are neither, the paragraph direction is the view's resolved layout direction.
2457     */
2458    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2459
2460    /**
2461     * Text direction is forced to LTR.
2462     */
2463    public static final int TEXT_DIRECTION_LTR = 3;
2464
2465    /**
2466     * Text direction is forced to RTL.
2467     */
2468    public static final int TEXT_DIRECTION_RTL = 4;
2469
2470    /**
2471     * Text direction is coming from the system Locale.
2472     */
2473    public static final int TEXT_DIRECTION_LOCALE = 5;
2474
2475    /**
2476     * Text direction is using "first strong algorithm". The first strong directional character
2477     * determines the paragraph direction. If there is no strong directional character, the
2478     * paragraph direction is LTR.
2479     */
2480    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2481
2482    /**
2483     * Text direction is using "first strong algorithm". The first strong directional character
2484     * determines the paragraph direction. If there is no strong directional character, the
2485     * paragraph direction is RTL.
2486     */
2487    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2488
2489    /**
2490     * Default text direction is inherited
2491     */
2492    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2493
2494    /**
2495     * Default resolved text direction
2496     * @hide
2497     */
2498    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2499
2500    /**
2501     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2502     * @hide
2503     */
2504    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2505
2506    /**
2507     * Mask for use with private flags indicating bits used for text direction.
2508     * @hide
2509     */
2510    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2511            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2512
2513    /**
2514     * Array of text direction flags for mapping attribute "textDirection" to correct
2515     * flag value.
2516     * @hide
2517     */
2518    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2519            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2520            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2521            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2522            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2523            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2524            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2525            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2526            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2527    };
2528
2529    /**
2530     * Indicates whether the view text direction has been resolved.
2531     * @hide
2532     */
2533    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2534            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2535
2536    /**
2537     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2538     * @hide
2539     */
2540    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2541
2542    /**
2543     * Mask for use with private flags indicating bits used for resolved text direction.
2544     * @hide
2545     */
2546    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2547            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2548
2549    /**
2550     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2551     * @hide
2552     */
2553    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2554            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2555
2556    /** @hide */
2557    @IntDef({
2558        TEXT_ALIGNMENT_INHERIT,
2559        TEXT_ALIGNMENT_GRAVITY,
2560        TEXT_ALIGNMENT_CENTER,
2561        TEXT_ALIGNMENT_TEXT_START,
2562        TEXT_ALIGNMENT_TEXT_END,
2563        TEXT_ALIGNMENT_VIEW_START,
2564        TEXT_ALIGNMENT_VIEW_END
2565    })
2566    @Retention(RetentionPolicy.SOURCE)
2567    public @interface TextAlignment {}
2568
2569    /**
2570     * Default text alignment. The text alignment of this View is inherited from its parent.
2571     * Use with {@link #setTextAlignment(int)}
2572     */
2573    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2574
2575    /**
2576     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2577     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2578     *
2579     * Use with {@link #setTextAlignment(int)}
2580     */
2581    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2582
2583    /**
2584     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2585     *
2586     * Use with {@link #setTextAlignment(int)}
2587     */
2588    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2589
2590    /**
2591     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2592     *
2593     * Use with {@link #setTextAlignment(int)}
2594     */
2595    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2596
2597    /**
2598     * Center the paragraph, e.g. ALIGN_CENTER.
2599     *
2600     * Use with {@link #setTextAlignment(int)}
2601     */
2602    public static final int TEXT_ALIGNMENT_CENTER = 4;
2603
2604    /**
2605     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2606     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2607     *
2608     * Use with {@link #setTextAlignment(int)}
2609     */
2610    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2611
2612    /**
2613     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2614     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2615     *
2616     * Use with {@link #setTextAlignment(int)}
2617     */
2618    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2619
2620    /**
2621     * Default text alignment is inherited
2622     */
2623    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2624
2625    /**
2626     * Default resolved text alignment
2627     * @hide
2628     */
2629    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2630
2631    /**
2632      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2633      * @hide
2634      */
2635    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2636
2637    /**
2638      * Mask for use with private flags indicating bits used for text alignment.
2639      * @hide
2640      */
2641    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2642
2643    /**
2644     * Array of text direction flags for mapping attribute "textAlignment" to correct
2645     * flag value.
2646     * @hide
2647     */
2648    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2649            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2650            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2651            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2652            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2653            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2654            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2655            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2656    };
2657
2658    /**
2659     * Indicates whether the view text alignment has been resolved.
2660     * @hide
2661     */
2662    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2663
2664    /**
2665     * Bit shift to get the resolved text alignment.
2666     * @hide
2667     */
2668    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2669
2670    /**
2671     * Mask for use with private flags indicating bits used for text alignment.
2672     * @hide
2673     */
2674    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2675            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2676
2677    /**
2678     * Indicates whether if the view text alignment has been resolved to gravity
2679     */
2680    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2681            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2682
2683    // Accessiblity constants for mPrivateFlags2
2684
2685    /**
2686     * Shift for the bits in {@link #mPrivateFlags2} related to the
2687     * "importantForAccessibility" attribute.
2688     */
2689    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2690
2691    /**
2692     * Automatically determine whether a view is important for accessibility.
2693     */
2694    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2695
2696    /**
2697     * The view is important for accessibility.
2698     */
2699    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2700
2701    /**
2702     * The view is not important for accessibility.
2703     */
2704    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2705
2706    /**
2707     * The view is not important for accessibility, nor are any of its
2708     * descendant views.
2709     */
2710    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2711
2712    /**
2713     * The default whether the view is important for accessibility.
2714     */
2715    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2716
2717    /**
2718     * Mask for obtaining the bits which specify how to determine
2719     * whether a view is important for accessibility.
2720     */
2721    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2722        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2723        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2724        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2725
2726    /**
2727     * Shift for the bits in {@link #mPrivateFlags2} related to the
2728     * "accessibilityLiveRegion" attribute.
2729     */
2730    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2731
2732    /**
2733     * Live region mode specifying that accessibility services should not
2734     * automatically announce changes to this view. This is the default live
2735     * region mode for most views.
2736     * <p>
2737     * Use with {@link #setAccessibilityLiveRegion(int)}.
2738     */
2739    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2740
2741    /**
2742     * Live region mode specifying that accessibility services should announce
2743     * changes to this view.
2744     * <p>
2745     * Use with {@link #setAccessibilityLiveRegion(int)}.
2746     */
2747    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2748
2749    /**
2750     * Live region mode specifying that accessibility services should interrupt
2751     * ongoing speech to immediately announce changes to this view.
2752     * <p>
2753     * Use with {@link #setAccessibilityLiveRegion(int)}.
2754     */
2755    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2756
2757    /**
2758     * The default whether the view is important for accessibility.
2759     */
2760    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2761
2762    /**
2763     * Mask for obtaining the bits which specify a view's accessibility live
2764     * region mode.
2765     */
2766    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2767            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2768            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2769
2770    /**
2771     * Flag indicating whether a view has accessibility focus.
2772     */
2773    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2774
2775    /**
2776     * Flag whether the accessibility state of the subtree rooted at this view changed.
2777     */
2778    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2779
2780    /**
2781     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2782     * is used to check whether later changes to the view's transform should invalidate the
2783     * view to force the quickReject test to run again.
2784     */
2785    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2786
2787    /**
2788     * Flag indicating that start/end padding has been resolved into left/right padding
2789     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2790     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2791     * during measurement. In some special cases this is required such as when an adapter-based
2792     * view measures prospective children without attaching them to a window.
2793     */
2794    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2795
2796    /**
2797     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2798     */
2799    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2800
2801    /**
2802     * Indicates that the view is tracking some sort of transient state
2803     * that the app should not need to be aware of, but that the framework
2804     * should take special care to preserve.
2805     */
2806    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2807
2808    /**
2809     * Group of bits indicating that RTL properties resolution is done.
2810     */
2811    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2812            PFLAG2_TEXT_DIRECTION_RESOLVED |
2813            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2814            PFLAG2_PADDING_RESOLVED |
2815            PFLAG2_DRAWABLE_RESOLVED;
2816
2817    // There are a couple of flags left in mPrivateFlags2
2818
2819    /* End of masks for mPrivateFlags2 */
2820
2821    /**
2822     * Masks for mPrivateFlags3, as generated by dumpFlags():
2823     *
2824     * |-------|-------|-------|-------|
2825     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2826     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2827     *                               1   PFLAG3_IS_LAID_OUT
2828     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2829     *                             1     PFLAG3_CALLED_SUPER
2830     *                            1      PFLAG3_APPLYING_INSETS
2831     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2832     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2833     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2834     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2835     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2836     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2837     *                     1             PFLAG3_SCROLL_INDICATOR_START
2838     *                    1              PFLAG3_SCROLL_INDICATOR_END
2839     *                   1               PFLAG3_ASSIST_BLOCKED
2840     *                  1                PFLAG3_CLUSTER
2841     *                 1                 PFLAG3_IS_AUTOFILLED
2842     *                1                  PFLAG3_FINGER_DOWN
2843     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2844     *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2845     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2846     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2847     *        1                          PFLAG3_TEMPORARY_DETACH
2848     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2849     *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2850     * |-------|-------|-------|-------|
2851     */
2852
2853    /**
2854     * Flag indicating that view has a transform animation set on it. This is used to track whether
2855     * an animation is cleared between successive frames, in order to tell the associated
2856     * DisplayList to clear its animation matrix.
2857     */
2858    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2859
2860    /**
2861     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2862     * animation is cleared between successive frames, in order to tell the associated
2863     * DisplayList to restore its alpha value.
2864     */
2865    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2866
2867    /**
2868     * Flag indicating that the view has been through at least one layout since it
2869     * was last attached to a window.
2870     */
2871    static final int PFLAG3_IS_LAID_OUT = 0x4;
2872
2873    /**
2874     * Flag indicating that a call to measure() was skipped and should be done
2875     * instead when layout() is invoked.
2876     */
2877    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2878
2879    /**
2880     * Flag indicating that an overridden method correctly called down to
2881     * the superclass implementation as required by the API spec.
2882     */
2883    static final int PFLAG3_CALLED_SUPER = 0x10;
2884
2885    /**
2886     * Flag indicating that we're in the process of applying window insets.
2887     */
2888    static final int PFLAG3_APPLYING_INSETS = 0x20;
2889
2890    /**
2891     * Flag indicating that we're in the process of fitting system windows using the old method.
2892     */
2893    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2894
2895    /**
2896     * Flag indicating that nested scrolling is enabled for this view.
2897     * The view will optionally cooperate with views up its parent chain to allow for
2898     * integrated nested scrolling along the same axis.
2899     */
2900    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2901
2902    /**
2903     * Flag indicating that the bottom scroll indicator should be displayed
2904     * when this view can scroll up.
2905     */
2906    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2907
2908    /**
2909     * Flag indicating that the bottom scroll indicator should be displayed
2910     * when this view can scroll down.
2911     */
2912    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2913
2914    /**
2915     * Flag indicating that the left scroll indicator should be displayed
2916     * when this view can scroll left.
2917     */
2918    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2919
2920    /**
2921     * Flag indicating that the right scroll indicator should be displayed
2922     * when this view can scroll right.
2923     */
2924    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2925
2926    /**
2927     * Flag indicating that the start scroll indicator should be displayed
2928     * when this view can scroll in the start direction.
2929     */
2930    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2931
2932    /**
2933     * Flag indicating that the end scroll indicator should be displayed
2934     * when this view can scroll in the end direction.
2935     */
2936    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2937
2938    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2939
2940    static final int SCROLL_INDICATORS_NONE = 0x0000;
2941
2942    /**
2943     * Mask for use with setFlags indicating bits used for indicating which
2944     * scroll indicators are enabled.
2945     */
2946    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2947            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2948            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2949            | PFLAG3_SCROLL_INDICATOR_END;
2950
2951    /**
2952     * Left-shift required to translate between public scroll indicator flags
2953     * and internal PFLAGS3 flags. When used as a right-shift, translates
2954     * PFLAGS3 flags to public flags.
2955     */
2956    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2957
2958    /** @hide */
2959    @Retention(RetentionPolicy.SOURCE)
2960    @IntDef(flag = true,
2961            value = {
2962                    SCROLL_INDICATOR_TOP,
2963                    SCROLL_INDICATOR_BOTTOM,
2964                    SCROLL_INDICATOR_LEFT,
2965                    SCROLL_INDICATOR_RIGHT,
2966                    SCROLL_INDICATOR_START,
2967                    SCROLL_INDICATOR_END,
2968            })
2969    public @interface ScrollIndicators {}
2970
2971    /**
2972     * Scroll indicator direction for the top edge of the view.
2973     *
2974     * @see #setScrollIndicators(int)
2975     * @see #setScrollIndicators(int, int)
2976     * @see #getScrollIndicators()
2977     */
2978    public static final int SCROLL_INDICATOR_TOP =
2979            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2980
2981    /**
2982     * Scroll indicator direction for the bottom edge of the view.
2983     *
2984     * @see #setScrollIndicators(int)
2985     * @see #setScrollIndicators(int, int)
2986     * @see #getScrollIndicators()
2987     */
2988    public static final int SCROLL_INDICATOR_BOTTOM =
2989            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2990
2991    /**
2992     * Scroll indicator direction for the left edge of the view.
2993     *
2994     * @see #setScrollIndicators(int)
2995     * @see #setScrollIndicators(int, int)
2996     * @see #getScrollIndicators()
2997     */
2998    public static final int SCROLL_INDICATOR_LEFT =
2999            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3000
3001    /**
3002     * Scroll indicator direction for the right edge of the view.
3003     *
3004     * @see #setScrollIndicators(int)
3005     * @see #setScrollIndicators(int, int)
3006     * @see #getScrollIndicators()
3007     */
3008    public static final int SCROLL_INDICATOR_RIGHT =
3009            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3010
3011    /**
3012     * Scroll indicator direction for the starting edge of the view.
3013     * <p>
3014     * Resolved according to the view's layout direction, see
3015     * {@link #getLayoutDirection()} for more information.
3016     *
3017     * @see #setScrollIndicators(int)
3018     * @see #setScrollIndicators(int, int)
3019     * @see #getScrollIndicators()
3020     */
3021    public static final int SCROLL_INDICATOR_START =
3022            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3023
3024    /**
3025     * Scroll indicator direction for the ending edge of the view.
3026     * <p>
3027     * Resolved according to the view's layout direction, see
3028     * {@link #getLayoutDirection()} for more information.
3029     *
3030     * @see #setScrollIndicators(int)
3031     * @see #setScrollIndicators(int, int)
3032     * @see #getScrollIndicators()
3033     */
3034    public static final int SCROLL_INDICATOR_END =
3035            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3036
3037    /**
3038     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3039     * into this view.<p>
3040     */
3041    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3042
3043    /**
3044     * Flag indicating that the view is a root of a keyboard navigation cluster.
3045     *
3046     * @see #isKeyboardNavigationCluster()
3047     * @see #setKeyboardNavigationCluster(boolean)
3048     */
3049    private static final int PFLAG3_CLUSTER = 0x8000;
3050
3051    /**
3052     * Flag indicating that the view is autofilled
3053     *
3054     * @see #isAutofilled()
3055     * @see #setAutofilled(boolean)
3056     */
3057    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3058
3059    /**
3060     * Indicates that the user is currently touching the screen.
3061     * Currently used for the tooltip positioning only.
3062     */
3063    private static final int PFLAG3_FINGER_DOWN = 0x20000;
3064
3065    /**
3066     * Flag indicating that this view is the default-focus view.
3067     *
3068     * @see #isFocusedByDefault()
3069     * @see #setFocusedByDefault(boolean)
3070     */
3071    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3072
3073    /**
3074     * Shift for the bits in {@link #mPrivateFlags3} related to the
3075     * "importantForAutofill" attribute.
3076     */
3077    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3078
3079    /**
3080     * Mask for obtaining the bits which specify how to determine
3081     * whether a view is important for autofill.
3082     */
3083    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3084            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3085            | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3086            | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3087            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3088
3089    /**
3090     * Whether this view has rendered elements that overlap (see {@link
3091     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3092     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3093     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3094     * determined by whatever {@link #hasOverlappingRendering()} returns.
3095     */
3096    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3097
3098    /**
3099     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3100     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3101     */
3102    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3103
3104    /**
3105     * Flag indicating that the view is temporarily detached from the parent view.
3106     *
3107     * @see #onStartTemporaryDetach()
3108     * @see #onFinishTemporaryDetach()
3109     */
3110    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3111
3112    /**
3113     * Flag indicating that the view does not wish to be revealed within its parent
3114     * hierarchy when it gains focus. Expressed in the negative since the historical
3115     * default behavior is to reveal on focus; this flag suppresses that behavior.
3116     *
3117     * @see #setRevealOnFocusHint(boolean)
3118     * @see #getRevealOnFocusHint()
3119     */
3120    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3121
3122    /**
3123     * Flag indicating that when layout is completed we should notify
3124     * that the view was entered for autofill purposes. To minimize
3125     * showing autofill for views not visible to the user we evaluate
3126     * user visibility which cannot be done until the view is laid out.
3127     */
3128    static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3129
3130    /* End of masks for mPrivateFlags3 */
3131
3132    /**
3133     * Always allow a user to over-scroll this view, provided it is a
3134     * view that can scroll.
3135     *
3136     * @see #getOverScrollMode()
3137     * @see #setOverScrollMode(int)
3138     */
3139    public static final int OVER_SCROLL_ALWAYS = 0;
3140
3141    /**
3142     * Allow a user to over-scroll this view only if the content is large
3143     * enough to meaningfully scroll, provided it is a view that can scroll.
3144     *
3145     * @see #getOverScrollMode()
3146     * @see #setOverScrollMode(int)
3147     */
3148    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3149
3150    /**
3151     * Never allow a user to over-scroll this view.
3152     *
3153     * @see #getOverScrollMode()
3154     * @see #setOverScrollMode(int)
3155     */
3156    public static final int OVER_SCROLL_NEVER = 2;
3157
3158    /**
3159     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3160     * requested the system UI (status bar) to be visible (the default).
3161     *
3162     * @see #setSystemUiVisibility(int)
3163     */
3164    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3165
3166    /**
3167     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3168     * system UI to enter an unobtrusive "low profile" mode.
3169     *
3170     * <p>This is for use in games, book readers, video players, or any other
3171     * "immersive" application where the usual system chrome is deemed too distracting.
3172     *
3173     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3174     *
3175     * @see #setSystemUiVisibility(int)
3176     */
3177    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3178
3179    /**
3180     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3181     * system navigation be temporarily hidden.
3182     *
3183     * <p>This is an even less obtrusive state than that called for by
3184     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3185     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3186     * those to disappear. This is useful (in conjunction with the
3187     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3188     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3189     * window flags) for displaying content using every last pixel on the display.
3190     *
3191     * <p>There is a limitation: because navigation controls are so important, the least user
3192     * interaction will cause them to reappear immediately.  When this happens, both
3193     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3194     * so that both elements reappear at the same time.
3195     *
3196     * @see #setSystemUiVisibility(int)
3197     */
3198    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3199
3200    /**
3201     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3202     * into the normal fullscreen mode so that its content can take over the screen
3203     * while still allowing the user to interact with the application.
3204     *
3205     * <p>This has the same visual effect as
3206     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3207     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3208     * meaning that non-critical screen decorations (such as the status bar) will be
3209     * hidden while the user is in the View's window, focusing the experience on
3210     * that content.  Unlike the window flag, if you are using ActionBar in
3211     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3212     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3213     * hide the action bar.
3214     *
3215     * <p>This approach to going fullscreen is best used over the window flag when
3216     * it is a transient state -- that is, the application does this at certain
3217     * points in its user interaction where it wants to allow the user to focus
3218     * on content, but not as a continuous state.  For situations where the application
3219     * would like to simply stay full screen the entire time (such as a game that
3220     * wants to take over the screen), the
3221     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3222     * is usually a better approach.  The state set here will be removed by the system
3223     * in various situations (such as the user moving to another application) like
3224     * the other system UI states.
3225     *
3226     * <p>When using this flag, the application should provide some easy facility
3227     * for the user to go out of it.  A common example would be in an e-book
3228     * reader, where tapping on the screen brings back whatever screen and UI
3229     * decorations that had been hidden while the user was immersed in reading
3230     * the book.
3231     *
3232     * @see #setSystemUiVisibility(int)
3233     */
3234    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3235
3236    /**
3237     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3238     * flags, we would like a stable view of the content insets given to
3239     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3240     * will always represent the worst case that the application can expect
3241     * as a continuous state.  In the stock Android UI this is the space for
3242     * the system bar, nav bar, and status bar, but not more transient elements
3243     * such as an input method.
3244     *
3245     * The stable layout your UI sees is based on the system UI modes you can
3246     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3247     * then you will get a stable layout for changes of the
3248     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3249     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3250     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3251     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3252     * with a stable layout.  (Note that you should avoid using
3253     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3254     *
3255     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3256     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3257     * then a hidden status bar will be considered a "stable" state for purposes
3258     * here.  This allows your UI to continually hide the status bar, while still
3259     * using the system UI flags to hide the action bar while still retaining
3260     * a stable layout.  Note that changing the window fullscreen flag will never
3261     * provide a stable layout for a clean transition.
3262     *
3263     * <p>If you are using ActionBar in
3264     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3265     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3266     * insets it adds to those given to the application.
3267     */
3268    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3269
3270    /**
3271     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3272     * to be laid out as if it has requested
3273     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3274     * allows it to avoid artifacts when switching in and out of that mode, at
3275     * the expense that some of its user interface may be covered by screen
3276     * decorations when they are shown.  You can perform layout of your inner
3277     * UI elements to account for the navigation system UI through the
3278     * {@link #fitSystemWindows(Rect)} method.
3279     */
3280    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3281
3282    /**
3283     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3284     * to be laid out as if it has requested
3285     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3286     * allows it to avoid artifacts when switching in and out of that mode, at
3287     * the expense that some of its user interface may be covered by screen
3288     * decorations when they are shown.  You can perform layout of your inner
3289     * UI elements to account for non-fullscreen system UI through the
3290     * {@link #fitSystemWindows(Rect)} method.
3291     */
3292    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3293
3294    /**
3295     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3296     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3297     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3298     * user interaction.
3299     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3300     * has an effect when used in combination with that flag.</p>
3301     */
3302    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3303
3304    /**
3305     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3306     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3307     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3308     * experience while also hiding the system bars.  If this flag is not set,
3309     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3310     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3311     * if the user swipes from the top of the screen.
3312     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3313     * system gestures, such as swiping from the top of the screen.  These transient system bars
3314     * will overlay app’s content, may have some degree of transparency, and will automatically
3315     * hide after a short timeout.
3316     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3317     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3318     * with one or both of those flags.</p>
3319     */
3320    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3321
3322    /**
3323     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3324     * is compatible with light status bar backgrounds.
3325     *
3326     * <p>For this to take effect, the window must request
3327     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3328     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3329     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3330     *         FLAG_TRANSLUCENT_STATUS}.
3331     *
3332     * @see android.R.attr#windowLightStatusBar
3333     */
3334    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3335
3336    /**
3337     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3338     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3339     */
3340    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3341
3342    /**
3343     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3344     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3345     */
3346    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3347
3348    /**
3349     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3350     * that is compatible with light navigation bar backgrounds.
3351     *
3352     * <p>For this to take effect, the window must request
3353     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3354     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3355     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3356     *         FLAG_TRANSLUCENT_NAVIGATION}.
3357     */
3358    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3359
3360    /**
3361     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3362     */
3363    @Deprecated
3364    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3365
3366    /**
3367     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3368     */
3369    @Deprecated
3370    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3371
3372    /**
3373     * @hide
3374     *
3375     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3376     * out of the public fields to keep the undefined bits out of the developer's way.
3377     *
3378     * Flag to make the status bar not expandable.  Unless you also
3379     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3380     */
3381    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3382
3383    /**
3384     * @hide
3385     *
3386     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3387     * out of the public fields to keep the undefined bits out of the developer's way.
3388     *
3389     * Flag to hide notification icons and scrolling ticker text.
3390     */
3391    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3392
3393    /**
3394     * @hide
3395     *
3396     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3397     * out of the public fields to keep the undefined bits out of the developer's way.
3398     *
3399     * Flag to disable incoming notification alerts.  This will not block
3400     * icons, but it will block sound, vibrating and other visual or aural notifications.
3401     */
3402    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3403
3404    /**
3405     * @hide
3406     *
3407     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3408     * out of the public fields to keep the undefined bits out of the developer's way.
3409     *
3410     * Flag to hide only the scrolling ticker.  Note that
3411     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3412     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3413     */
3414    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3415
3416    /**
3417     * @hide
3418     *
3419     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3420     * out of the public fields to keep the undefined bits out of the developer's way.
3421     *
3422     * Flag to hide the center system info area.
3423     */
3424    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3425
3426    /**
3427     * @hide
3428     *
3429     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3430     * out of the public fields to keep the undefined bits out of the developer's way.
3431     *
3432     * Flag to hide only the home button.  Don't use this
3433     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3434     */
3435    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3436
3437    /**
3438     * @hide
3439     *
3440     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3441     * out of the public fields to keep the undefined bits out of the developer's way.
3442     *
3443     * Flag to hide only the back button. Don't use this
3444     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3445     */
3446    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3447
3448    /**
3449     * @hide
3450     *
3451     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3452     * out of the public fields to keep the undefined bits out of the developer's way.
3453     *
3454     * Flag to hide only the clock.  You might use this if your activity has
3455     * its own clock making the status bar's clock redundant.
3456     */
3457    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3458
3459    /**
3460     * @hide
3461     *
3462     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3463     * out of the public fields to keep the undefined bits out of the developer's way.
3464     *
3465     * Flag to hide only the recent apps button. Don't use this
3466     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3467     */
3468    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3469
3470    /**
3471     * @hide
3472     *
3473     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3474     * out of the public fields to keep the undefined bits out of the developer's way.
3475     *
3476     * Flag to disable the global search gesture. Don't use this
3477     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3478     */
3479    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3480
3481    /**
3482     * @hide
3483     *
3484     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3485     * out of the public fields to keep the undefined bits out of the developer's way.
3486     *
3487     * Flag to specify that the status bar is displayed in transient mode.
3488     */
3489    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3490
3491    /**
3492     * @hide
3493     *
3494     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3495     * out of the public fields to keep the undefined bits out of the developer's way.
3496     *
3497     * Flag to specify that the navigation bar is displayed in transient mode.
3498     */
3499    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3500
3501    /**
3502     * @hide
3503     *
3504     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3505     * out of the public fields to keep the undefined bits out of the developer's way.
3506     *
3507     * Flag to specify that the hidden status bar would like to be shown.
3508     */
3509    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3510
3511    /**
3512     * @hide
3513     *
3514     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3515     * out of the public fields to keep the undefined bits out of the developer's way.
3516     *
3517     * Flag to specify that the hidden navigation bar would like to be shown.
3518     */
3519    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3520
3521    /**
3522     * @hide
3523     *
3524     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3525     * out of the public fields to keep the undefined bits out of the developer's way.
3526     *
3527     * Flag to specify that the status bar is displayed in translucent mode.
3528     */
3529    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3530
3531    /**
3532     * @hide
3533     *
3534     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3535     * out of the public fields to keep the undefined bits out of the developer's way.
3536     *
3537     * Flag to specify that the navigation bar is displayed in translucent mode.
3538     */
3539    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3540
3541    /**
3542     * @hide
3543     *
3544     * Makes navigation bar transparent (but not the status bar).
3545     */
3546    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3547
3548    /**
3549     * @hide
3550     *
3551     * Makes status bar transparent (but not the navigation bar).
3552     */
3553    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3554
3555    /**
3556     * @hide
3557     *
3558     * Makes both status bar and navigation bar transparent.
3559     */
3560    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3561            | STATUS_BAR_TRANSPARENT;
3562
3563    /**
3564     * @hide
3565     */
3566    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3567
3568    /**
3569     * These are the system UI flags that can be cleared by events outside
3570     * of an application.  Currently this is just the ability to tap on the
3571     * screen while hiding the navigation bar to have it return.
3572     * @hide
3573     */
3574    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3575            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3576            | SYSTEM_UI_FLAG_FULLSCREEN;
3577
3578    /**
3579     * Flags that can impact the layout in relation to system UI.
3580     */
3581    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3582            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3583            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3584
3585    /** @hide */
3586    @IntDef(flag = true,
3587            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3588    @Retention(RetentionPolicy.SOURCE)
3589    public @interface FindViewFlags {}
3590
3591    /**
3592     * Find views that render the specified text.
3593     *
3594     * @see #findViewsWithText(ArrayList, CharSequence, int)
3595     */
3596    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3597
3598    /**
3599     * Find find views that contain the specified content description.
3600     *
3601     * @see #findViewsWithText(ArrayList, CharSequence, int)
3602     */
3603    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3604
3605    /**
3606     * Find views that contain {@link AccessibilityNodeProvider}. Such
3607     * a View is a root of virtual view hierarchy and may contain the searched
3608     * text. If this flag is set Views with providers are automatically
3609     * added and it is a responsibility of the client to call the APIs of
3610     * the provider to determine whether the virtual tree rooted at this View
3611     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3612     * representing the virtual views with this text.
3613     *
3614     * @see #findViewsWithText(ArrayList, CharSequence, int)
3615     *
3616     * @hide
3617     */
3618    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3619
3620    /**
3621     * The undefined cursor position.
3622     *
3623     * @hide
3624     */
3625    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3626
3627    /**
3628     * Indicates that the screen has changed state and is now off.
3629     *
3630     * @see #onScreenStateChanged(int)
3631     */
3632    public static final int SCREEN_STATE_OFF = 0x0;
3633
3634    /**
3635     * Indicates that the screen has changed state and is now on.
3636     *
3637     * @see #onScreenStateChanged(int)
3638     */
3639    public static final int SCREEN_STATE_ON = 0x1;
3640
3641    /**
3642     * Indicates no axis of view scrolling.
3643     */
3644    public static final int SCROLL_AXIS_NONE = 0;
3645
3646    /**
3647     * Indicates scrolling along the horizontal axis.
3648     */
3649    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3650
3651    /**
3652     * Indicates scrolling along the vertical axis.
3653     */
3654    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3655
3656    /**
3657     * Controls the over-scroll mode for this view.
3658     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3659     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3660     * and {@link #OVER_SCROLL_NEVER}.
3661     */
3662    private int mOverScrollMode;
3663
3664    /**
3665     * The parent this view is attached to.
3666     * {@hide}
3667     *
3668     * @see #getParent()
3669     */
3670    protected ViewParent mParent;
3671
3672    /**
3673     * {@hide}
3674     */
3675    AttachInfo mAttachInfo;
3676
3677    /**
3678     * {@hide}
3679     */
3680    @ViewDebug.ExportedProperty(flagMapping = {
3681        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3682                name = "FORCE_LAYOUT"),
3683        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3684                name = "LAYOUT_REQUIRED"),
3685        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3686            name = "DRAWING_CACHE_INVALID", outputIf = false),
3687        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3688        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3689        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3690        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3691    }, formatToHexString = true)
3692
3693    /* @hide */
3694    public int mPrivateFlags;
3695    int mPrivateFlags2;
3696    int mPrivateFlags3;
3697
3698    /**
3699     * This view's request for the visibility of the status bar.
3700     * @hide
3701     */
3702    @ViewDebug.ExportedProperty(flagMapping = {
3703        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3704                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3705                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3706        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3707                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3708                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3709        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3710                                equals = SYSTEM_UI_FLAG_VISIBLE,
3711                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3712    }, formatToHexString = true)
3713    int mSystemUiVisibility;
3714
3715    /**
3716     * Reference count for transient state.
3717     * @see #setHasTransientState(boolean)
3718     */
3719    int mTransientStateCount = 0;
3720
3721    /**
3722     * Count of how many windows this view has been attached to.
3723     */
3724    int mWindowAttachCount;
3725
3726    /**
3727     * The layout parameters associated with this view and used by the parent
3728     * {@link android.view.ViewGroup} to determine how this view should be
3729     * laid out.
3730     * {@hide}
3731     */
3732    protected ViewGroup.LayoutParams mLayoutParams;
3733
3734    /**
3735     * The view flags hold various views states.
3736     * {@hide}
3737     */
3738    @ViewDebug.ExportedProperty(formatToHexString = true)
3739    int mViewFlags;
3740
3741    static class TransformationInfo {
3742        /**
3743         * The transform matrix for the View. This transform is calculated internally
3744         * based on the translation, rotation, and scale properties.
3745         *
3746         * Do *not* use this variable directly; instead call getMatrix(), which will
3747         * load the value from the View's RenderNode.
3748         */
3749        private final Matrix mMatrix = new Matrix();
3750
3751        /**
3752         * The inverse transform matrix for the View. This transform is calculated
3753         * internally based on the translation, rotation, and scale properties.
3754         *
3755         * Do *not* use this variable directly; instead call getInverseMatrix(),
3756         * which will load the value from the View's RenderNode.
3757         */
3758        private Matrix mInverseMatrix;
3759
3760        /**
3761         * The opacity of the View. This is a value from 0 to 1, where 0 means
3762         * completely transparent and 1 means completely opaque.
3763         */
3764        @ViewDebug.ExportedProperty
3765        float mAlpha = 1f;
3766
3767        /**
3768         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3769         * property only used by transitions, which is composited with the other alpha
3770         * values to calculate the final visual alpha value.
3771         */
3772        float mTransitionAlpha = 1f;
3773    }
3774
3775    /** @hide */
3776    public TransformationInfo mTransformationInfo;
3777
3778    /**
3779     * Current clip bounds. to which all drawing of this view are constrained.
3780     */
3781    Rect mClipBounds = null;
3782
3783    private boolean mLastIsOpaque;
3784
3785    /**
3786     * The distance in pixels from the left edge of this view's parent
3787     * to the left edge of this view.
3788     * {@hide}
3789     */
3790    @ViewDebug.ExportedProperty(category = "layout")
3791    protected int mLeft;
3792    /**
3793     * The distance in pixels from the left edge of this view's parent
3794     * to the right edge of this view.
3795     * {@hide}
3796     */
3797    @ViewDebug.ExportedProperty(category = "layout")
3798    protected int mRight;
3799    /**
3800     * The distance in pixels from the top edge of this view's parent
3801     * to the top edge of this view.
3802     * {@hide}
3803     */
3804    @ViewDebug.ExportedProperty(category = "layout")
3805    protected int mTop;
3806    /**
3807     * The distance in pixels from the top edge of this view's parent
3808     * to the bottom edge of this view.
3809     * {@hide}
3810     */
3811    @ViewDebug.ExportedProperty(category = "layout")
3812    protected int mBottom;
3813
3814    /**
3815     * The offset, in pixels, by which the content of this view is scrolled
3816     * horizontally.
3817     * {@hide}
3818     */
3819    @ViewDebug.ExportedProperty(category = "scrolling")
3820    protected int mScrollX;
3821    /**
3822     * The offset, in pixels, by which the content of this view is scrolled
3823     * vertically.
3824     * {@hide}
3825     */
3826    @ViewDebug.ExportedProperty(category = "scrolling")
3827    protected int mScrollY;
3828
3829    /**
3830     * The left padding in pixels, that is the distance in pixels between the
3831     * left edge of this view and the left edge of its content.
3832     * {@hide}
3833     */
3834    @ViewDebug.ExportedProperty(category = "padding")
3835    protected int mPaddingLeft = 0;
3836    /**
3837     * The right padding in pixels, that is the distance in pixels between the
3838     * right edge of this view and the right edge of its content.
3839     * {@hide}
3840     */
3841    @ViewDebug.ExportedProperty(category = "padding")
3842    protected int mPaddingRight = 0;
3843    /**
3844     * The top padding in pixels, that is the distance in pixels between the
3845     * top edge of this view and the top edge of its content.
3846     * {@hide}
3847     */
3848    @ViewDebug.ExportedProperty(category = "padding")
3849    protected int mPaddingTop;
3850    /**
3851     * The bottom padding in pixels, that is the distance in pixels between the
3852     * bottom edge of this view and the bottom edge of its content.
3853     * {@hide}
3854     */
3855    @ViewDebug.ExportedProperty(category = "padding")
3856    protected int mPaddingBottom;
3857
3858    /**
3859     * The layout insets in pixels, that is the distance in pixels between the
3860     * visible edges of this view its bounds.
3861     */
3862    private Insets mLayoutInsets;
3863
3864    /**
3865     * Briefly describes the view and is primarily used for accessibility support.
3866     */
3867    private CharSequence mContentDescription;
3868
3869    /**
3870     * Specifies the id of a view for which this view serves as a label for
3871     * accessibility purposes.
3872     */
3873    private int mLabelForId = View.NO_ID;
3874
3875    /**
3876     * Predicate for matching labeled view id with its label for
3877     * accessibility purposes.
3878     */
3879    private MatchLabelForPredicate mMatchLabelForPredicate;
3880
3881    /**
3882     * Specifies a view before which this one is visited in accessibility traversal.
3883     */
3884    private int mAccessibilityTraversalBeforeId = NO_ID;
3885
3886    /**
3887     * Specifies a view after which this one is visited in accessibility traversal.
3888     */
3889    private int mAccessibilityTraversalAfterId = NO_ID;
3890
3891    /**
3892     * Predicate for matching a view by its id.
3893     */
3894    private MatchIdPredicate mMatchIdPredicate;
3895
3896    /**
3897     * Cache the paddingRight set by the user to append to the scrollbar's size.
3898     *
3899     * @hide
3900     */
3901    @ViewDebug.ExportedProperty(category = "padding")
3902    protected int mUserPaddingRight;
3903
3904    /**
3905     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3906     *
3907     * @hide
3908     */
3909    @ViewDebug.ExportedProperty(category = "padding")
3910    protected int mUserPaddingBottom;
3911
3912    /**
3913     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3914     *
3915     * @hide
3916     */
3917    @ViewDebug.ExportedProperty(category = "padding")
3918    protected int mUserPaddingLeft;
3919
3920    /**
3921     * Cache the paddingStart set by the user to append to the scrollbar's size.
3922     *
3923     */
3924    @ViewDebug.ExportedProperty(category = "padding")
3925    int mUserPaddingStart;
3926
3927    /**
3928     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3929     *
3930     */
3931    @ViewDebug.ExportedProperty(category = "padding")
3932    int mUserPaddingEnd;
3933
3934    /**
3935     * Cache initial left padding.
3936     *
3937     * @hide
3938     */
3939    int mUserPaddingLeftInitial;
3940
3941    /**
3942     * Cache initial right padding.
3943     *
3944     * @hide
3945     */
3946    int mUserPaddingRightInitial;
3947
3948    /**
3949     * Default undefined padding
3950     */
3951    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3952
3953    /**
3954     * Cache if a left padding has been defined
3955     */
3956    private boolean mLeftPaddingDefined = false;
3957
3958    /**
3959     * Cache if a right padding has been defined
3960     */
3961    private boolean mRightPaddingDefined = false;
3962
3963    /**
3964     * @hide
3965     */
3966    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3967    /**
3968     * @hide
3969     */
3970    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3971
3972    private LongSparseLongArray mMeasureCache;
3973
3974    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3975    private Drawable mBackground;
3976    private TintInfo mBackgroundTint;
3977
3978    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3979    private ForegroundInfo mForegroundInfo;
3980
3981    private Drawable mScrollIndicatorDrawable;
3982
3983    /**
3984     * RenderNode used for backgrounds.
3985     * <p>
3986     * When non-null and valid, this is expected to contain an up-to-date copy
3987     * of the background drawable. It is cleared on temporary detach, and reset
3988     * on cleanup.
3989     */
3990    private RenderNode mBackgroundRenderNode;
3991
3992    private int mBackgroundResource;
3993    private boolean mBackgroundSizeChanged;
3994
3995    /** The default focus highlight.
3996     * @see #mDefaultFocusHighlightEnabled
3997     * @see Drawable#hasFocusStateSpecified()
3998     */
3999    private Drawable mDefaultFocusHighlight;
4000    private Drawable mDefaultFocusHighlightCache;
4001    private boolean mDefaultFocusHighlightSizeChanged;
4002    /**
4003     * True if the default focus highlight is needed on the target device.
4004     */
4005    private static boolean sUseDefaultFocusHighlight;
4006
4007    private String mTransitionName;
4008
4009    static class TintInfo {
4010        ColorStateList mTintList;
4011        PorterDuff.Mode mTintMode;
4012        boolean mHasTintMode;
4013        boolean mHasTintList;
4014    }
4015
4016    private static class ForegroundInfo {
4017        private Drawable mDrawable;
4018        private TintInfo mTintInfo;
4019        private int mGravity = Gravity.FILL;
4020        private boolean mInsidePadding = true;
4021        private boolean mBoundsChanged = true;
4022        private final Rect mSelfBounds = new Rect();
4023        private final Rect mOverlayBounds = new Rect();
4024    }
4025
4026    static class ListenerInfo {
4027        /**
4028         * Listener used to dispatch focus change events.
4029         * This field should be made private, so it is hidden from the SDK.
4030         * {@hide}
4031         */
4032        protected OnFocusChangeListener mOnFocusChangeListener;
4033
4034        /**
4035         * Listeners for layout change events.
4036         */
4037        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4038
4039        protected OnScrollChangeListener mOnScrollChangeListener;
4040
4041        /**
4042         * Listeners for attach events.
4043         */
4044        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4045
4046        /**
4047         * Listener used to dispatch click events.
4048         * This field should be made private, so it is hidden from the SDK.
4049         * {@hide}
4050         */
4051        public OnClickListener mOnClickListener;
4052
4053        /**
4054         * Listener used to dispatch long click events.
4055         * This field should be made private, so it is hidden from the SDK.
4056         * {@hide}
4057         */
4058        protected OnLongClickListener mOnLongClickListener;
4059
4060        /**
4061         * Listener used to dispatch context click events. This field should be made private, so it
4062         * is hidden from the SDK.
4063         * {@hide}
4064         */
4065        protected OnContextClickListener mOnContextClickListener;
4066
4067        /**
4068         * Listener used to build the context menu.
4069         * This field should be made private, so it is hidden from the SDK.
4070         * {@hide}
4071         */
4072        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4073
4074        private OnKeyListener mOnKeyListener;
4075
4076        private OnTouchListener mOnTouchListener;
4077
4078        private OnHoverListener mOnHoverListener;
4079
4080        private OnGenericMotionListener mOnGenericMotionListener;
4081
4082        private OnDragListener mOnDragListener;
4083
4084        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4085
4086        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4087
4088        OnCapturedPointerListener mOnCapturedPointerListener;
4089    }
4090
4091    ListenerInfo mListenerInfo;
4092
4093    private static class TooltipInfo {
4094        /**
4095         * Text to be displayed in a tooltip popup.
4096         */
4097        @Nullable
4098        CharSequence mTooltipText;
4099
4100        /**
4101         * View-relative position of the tooltip anchor point.
4102         */
4103        int mAnchorX;
4104        int mAnchorY;
4105
4106        /**
4107         * The tooltip popup.
4108         */
4109        @Nullable
4110        TooltipPopup mTooltipPopup;
4111
4112        /**
4113         * Set to true if the tooltip was shown as a result of a long click.
4114         */
4115        boolean mTooltipFromLongClick;
4116
4117        /**
4118         * Keep these Runnables so that they can be used to reschedule.
4119         */
4120        Runnable mShowTooltipRunnable;
4121        Runnable mHideTooltipRunnable;
4122    }
4123
4124    TooltipInfo mTooltipInfo;
4125
4126    // Temporary values used to hold (x,y) coordinates when delegating from the
4127    // two-arg performLongClick() method to the legacy no-arg version.
4128    private float mLongClickX = Float.NaN;
4129    private float mLongClickY = Float.NaN;
4130
4131    /**
4132     * The application environment this view lives in.
4133     * This field should be made private, so it is hidden from the SDK.
4134     * {@hide}
4135     */
4136    @ViewDebug.ExportedProperty(deepExport = true)
4137    protected Context mContext;
4138
4139    private final Resources mResources;
4140
4141    private ScrollabilityCache mScrollCache;
4142
4143    private int[] mDrawableState = null;
4144
4145    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4146
4147    /**
4148     * Animator that automatically runs based on state changes.
4149     */
4150    private StateListAnimator mStateListAnimator;
4151
4152    /**
4153     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4154     * the user may specify which view to go to next.
4155     */
4156    private int mNextFocusLeftId = View.NO_ID;
4157
4158    /**
4159     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4160     * the user may specify which view to go to next.
4161     */
4162    private int mNextFocusRightId = View.NO_ID;
4163
4164    /**
4165     * When this view has focus and the next focus is {@link #FOCUS_UP},
4166     * the user may specify which view to go to next.
4167     */
4168    private int mNextFocusUpId = View.NO_ID;
4169
4170    /**
4171     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4172     * the user may specify which view to go to next.
4173     */
4174    private int mNextFocusDownId = View.NO_ID;
4175
4176    /**
4177     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4178     * the user may specify which view to go to next.
4179     */
4180    int mNextFocusForwardId = View.NO_ID;
4181
4182    /**
4183     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4184     *
4185     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4186     */
4187    int mNextClusterForwardId = View.NO_ID;
4188
4189    /**
4190     * Whether this View should use a default focus highlight when it gets focused but doesn't
4191     * have {@link android.R.attr#state_focused} defined in its background.
4192     */
4193    boolean mDefaultFocusHighlightEnabled = true;
4194
4195    private CheckForLongPress mPendingCheckForLongPress;
4196    private CheckForTap mPendingCheckForTap = null;
4197    private PerformClick mPerformClick;
4198    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4199
4200    private UnsetPressedState mUnsetPressedState;
4201
4202    /**
4203     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4204     * up event while a long press is invoked as soon as the long press duration is reached, so
4205     * a long press could be performed before the tap is checked, in which case the tap's action
4206     * should not be invoked.
4207     */
4208    private boolean mHasPerformedLongPress;
4209
4210    /**
4211     * Whether a context click button is currently pressed down. This is true when the stylus is
4212     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4213     * pressed. This is false once the button is released or if the stylus has been lifted.
4214     */
4215    private boolean mInContextButtonPress;
4216
4217    /**
4218     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4219     * true after a stylus button press has occured, when the next up event should not be recognized
4220     * as a tap.
4221     */
4222    private boolean mIgnoreNextUpEvent;
4223
4224    /**
4225     * The minimum height of the view. We'll try our best to have the height
4226     * of this view to at least this amount.
4227     */
4228    @ViewDebug.ExportedProperty(category = "measurement")
4229    private int mMinHeight;
4230
4231    /**
4232     * The minimum width of the view. We'll try our best to have the width
4233     * of this view to at least this amount.
4234     */
4235    @ViewDebug.ExportedProperty(category = "measurement")
4236    private int mMinWidth;
4237
4238    /**
4239     * The delegate to handle touch events that are physically in this view
4240     * but should be handled by another view.
4241     */
4242    private TouchDelegate mTouchDelegate = null;
4243
4244    /**
4245     * Solid color to use as a background when creating the drawing cache. Enables
4246     * the cache to use 16 bit bitmaps instead of 32 bit.
4247     */
4248    private int mDrawingCacheBackgroundColor = 0;
4249
4250    /**
4251     * Special tree observer used when mAttachInfo is null.
4252     */
4253    private ViewTreeObserver mFloatingTreeObserver;
4254
4255    /**
4256     * Cache the touch slop from the context that created the view.
4257     */
4258    private int mTouchSlop;
4259
4260    /**
4261     * Object that handles automatic animation of view properties.
4262     */
4263    private ViewPropertyAnimator mAnimator = null;
4264
4265    /**
4266     * List of registered FrameMetricsObservers.
4267     */
4268    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4269
4270    /**
4271     * Flag indicating that a drag can cross window boundaries.  When
4272     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4273     * with this flag set, all visible applications with targetSdkVersion >=
4274     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4275     * in the drag operation and receive the dragged content.
4276     *
4277     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4278     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4279     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4280     */
4281    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4282
4283    /**
4284     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4285     * request read access to the content URI(s) contained in the {@link ClipData} object.
4286     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4287     */
4288    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4289
4290    /**
4291     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4292     * request write access to the content URI(s) contained in the {@link ClipData} object.
4293     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4294     */
4295    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4296
4297    /**
4298     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4299     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4300     * reboots until explicitly revoked with
4301     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4302     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4303     */
4304    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4305            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4306
4307    /**
4308     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4309     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4310     * match against the original granted URI.
4311     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4312     */
4313    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4314            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4315
4316    /**
4317     * Flag indicating that the drag shadow will be opaque.  When
4318     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4319     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4320     */
4321    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4322
4323    /**
4324     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4325     */
4326    private float mVerticalScrollFactor;
4327
4328    /**
4329     * Position of the vertical scroll bar.
4330     */
4331    private int mVerticalScrollbarPosition;
4332
4333    /**
4334     * Position the scroll bar at the default position as determined by the system.
4335     */
4336    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4337
4338    /**
4339     * Position the scroll bar along the left edge.
4340     */
4341    public static final int SCROLLBAR_POSITION_LEFT = 1;
4342
4343    /**
4344     * Position the scroll bar along the right edge.
4345     */
4346    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4347
4348    /**
4349     * Indicates that the view does not have a layer.
4350     *
4351     * @see #getLayerType()
4352     * @see #setLayerType(int, android.graphics.Paint)
4353     * @see #LAYER_TYPE_SOFTWARE
4354     * @see #LAYER_TYPE_HARDWARE
4355     */
4356    public static final int LAYER_TYPE_NONE = 0;
4357
4358    /**
4359     * <p>Indicates that the view has a software layer. A software layer is backed
4360     * by a bitmap and causes the view to be rendered using Android's software
4361     * rendering pipeline, even if hardware acceleration is enabled.</p>
4362     *
4363     * <p>Software layers have various usages:</p>
4364     * <p>When the application is not using hardware acceleration, a software layer
4365     * is useful to apply a specific color filter and/or blending mode and/or
4366     * translucency to a view and all its children.</p>
4367     * <p>When the application is using hardware acceleration, a software layer
4368     * is useful to render drawing primitives not supported by the hardware
4369     * accelerated pipeline. It can also be used to cache a complex view tree
4370     * into a texture and reduce the complexity of drawing operations. For instance,
4371     * when animating a complex view tree with a translation, a software layer can
4372     * be used to render the view tree only once.</p>
4373     * <p>Software layers should be avoided when the affected view tree updates
4374     * often. Every update will require to re-render the software layer, which can
4375     * potentially be slow (particularly when hardware acceleration is turned on
4376     * since the layer will have to be uploaded into a hardware texture after every
4377     * update.)</p>
4378     *
4379     * @see #getLayerType()
4380     * @see #setLayerType(int, android.graphics.Paint)
4381     * @see #LAYER_TYPE_NONE
4382     * @see #LAYER_TYPE_HARDWARE
4383     */
4384    public static final int LAYER_TYPE_SOFTWARE = 1;
4385
4386    /**
4387     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4388     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4389     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4390     * rendering pipeline, but only if hardware acceleration is turned on for the
4391     * view hierarchy. When hardware acceleration is turned off, hardware layers
4392     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4393     *
4394     * <p>A hardware layer is useful to apply a specific color filter and/or
4395     * blending mode and/or translucency to a view and all its children.</p>
4396     * <p>A hardware layer can be used to cache a complex view tree into a
4397     * texture and reduce the complexity of drawing operations. For instance,
4398     * when animating a complex view tree with a translation, a hardware layer can
4399     * be used to render the view tree only once.</p>
4400     * <p>A hardware layer can also be used to increase the rendering quality when
4401     * rotation transformations are applied on a view. It can also be used to
4402     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4403     *
4404     * @see #getLayerType()
4405     * @see #setLayerType(int, android.graphics.Paint)
4406     * @see #LAYER_TYPE_NONE
4407     * @see #LAYER_TYPE_SOFTWARE
4408     */
4409    public static final int LAYER_TYPE_HARDWARE = 2;
4410
4411    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4412            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4413            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4414            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4415    })
4416    int mLayerType = LAYER_TYPE_NONE;
4417    Paint mLayerPaint;
4418
4419    /**
4420     * Set to true when drawing cache is enabled and cannot be created.
4421     *
4422     * @hide
4423     */
4424    public boolean mCachingFailed;
4425    private Bitmap mDrawingCache;
4426    private Bitmap mUnscaledDrawingCache;
4427
4428    /**
4429     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4430     * <p>
4431     * When non-null and valid, this is expected to contain an up-to-date copy
4432     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4433     * cleanup.
4434     */
4435    final RenderNode mRenderNode;
4436
4437    /**
4438     * Set to true when the view is sending hover accessibility events because it
4439     * is the innermost hovered view.
4440     */
4441    private boolean mSendingHoverAccessibilityEvents;
4442
4443    /**
4444     * Delegate for injecting accessibility functionality.
4445     */
4446    AccessibilityDelegate mAccessibilityDelegate;
4447
4448    /**
4449     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4450     * and add/remove objects to/from the overlay directly through the Overlay methods.
4451     */
4452    ViewOverlay mOverlay;
4453
4454    /**
4455     * The currently active parent view for receiving delegated nested scrolling events.
4456     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4457     * by {@link #stopNestedScroll()} at the same point where we clear
4458     * requestDisallowInterceptTouchEvent.
4459     */
4460    private ViewParent mNestedScrollingParent;
4461
4462    /**
4463     * Consistency verifier for debugging purposes.
4464     * @hide
4465     */
4466    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4467            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4468                    new InputEventConsistencyVerifier(this, 0) : null;
4469
4470    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4471
4472    private int[] mTempNestedScrollConsumed;
4473
4474    /**
4475     * An overlay is going to draw this View instead of being drawn as part of this
4476     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4477     * when this view is invalidated.
4478     */
4479    GhostView mGhostView;
4480
4481    /**
4482     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4483     * @hide
4484     */
4485    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4486    public String[] mAttributes;
4487
4488    /**
4489     * Maps a Resource id to its name.
4490     */
4491    private static SparseArray<String> mAttributeMap;
4492
4493    /**
4494     * Queue of pending runnables. Used to postpone calls to post() until this
4495     * view is attached and has a handler.
4496     */
4497    private HandlerActionQueue mRunQueue;
4498
4499    /**
4500     * The pointer icon when the mouse hovers on this view. The default is null.
4501     */
4502    private PointerIcon mPointerIcon;
4503
4504    /**
4505     * @hide
4506     */
4507    String mStartActivityRequestWho;
4508
4509    @Nullable
4510    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4511
4512    /** Used to delay visibility updates sent to the autofill manager */
4513    private Handler mVisibilityChangeForAutofillHandler;
4514
4515    /**
4516     * Simple constructor to use when creating a view from code.
4517     *
4518     * @param context The Context the view is running in, through which it can
4519     *        access the current theme, resources, etc.
4520     */
4521    public View(Context context) {
4522        mContext = context;
4523        mResources = context != null ? context.getResources() : null;
4524        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4525        // Set some flags defaults
4526        mPrivateFlags2 =
4527                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4528                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4529                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4530                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4531                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4532                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4533        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4534        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4535        mUserPaddingStart = UNDEFINED_PADDING;
4536        mUserPaddingEnd = UNDEFINED_PADDING;
4537        mRenderNode = RenderNode.create(getClass().getName(), this);
4538
4539        if (!sCompatibilityDone && context != null) {
4540            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4541
4542            // Older apps may need this compatibility hack for measurement.
4543            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4544
4545            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4546            // of whether a layout was requested on that View.
4547            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4548
4549            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4550            Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4551
4552            // In M and newer, our widgets can pass a "hint" value in the size
4553            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4554            // know what the expected parent size is going to be, so e.g. list items can size
4555            // themselves at 1/3 the size of their container. It breaks older apps though,
4556            // specifically apps that use some popular open source libraries.
4557            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4558
4559            // Old versions of the platform would give different results from
4560            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4561            // modes, so we always need to run an additional EXACTLY pass.
4562            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4563
4564            // Prior to N, layout params could change without requiring a
4565            // subsequent call to setLayoutParams() and they would usually
4566            // work. Partial layout breaks this assumption.
4567            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4568
4569            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4570            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4571            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4572
4573            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4574            // in apps so we target check it to avoid breaking existing apps.
4575            sPreserveMarginParamsInLayoutParamConversion =
4576                    targetSdkVersion >= Build.VERSION_CODES.N;
4577
4578            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4579
4580            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4581
4582            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4583
4584            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4585                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4586
4587            sCompatibilityDone = true;
4588        }
4589    }
4590
4591    /**
4592     * Constructor that is called when inflating a view from XML. This is called
4593     * when a view is being constructed from an XML file, supplying attributes
4594     * that were specified in the XML file. This version uses a default style of
4595     * 0, so the only attribute values applied are those in the Context's Theme
4596     * and the given AttributeSet.
4597     *
4598     * <p>
4599     * The method onFinishInflate() will be called after all children have been
4600     * added.
4601     *
4602     * @param context The Context the view is running in, through which it can
4603     *        access the current theme, resources, etc.
4604     * @param attrs The attributes of the XML tag that is inflating the view.
4605     * @see #View(Context, AttributeSet, int)
4606     */
4607    public View(Context context, @Nullable AttributeSet attrs) {
4608        this(context, attrs, 0);
4609    }
4610
4611    /**
4612     * Perform inflation from XML and apply a class-specific base style from a
4613     * theme attribute. This constructor of View allows subclasses to use their
4614     * own base style when they are inflating. For example, a Button class's
4615     * constructor would call this version of the super class constructor and
4616     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4617     * allows the theme's button style to modify all of the base view attributes
4618     * (in particular its background) as well as the Button class's attributes.
4619     *
4620     * @param context The Context the view is running in, through which it can
4621     *        access the current theme, resources, etc.
4622     * @param attrs The attributes of the XML tag that is inflating the view.
4623     * @param defStyleAttr An attribute in the current theme that contains a
4624     *        reference to a style resource that supplies default values for
4625     *        the view. Can be 0 to not look for defaults.
4626     * @see #View(Context, AttributeSet)
4627     */
4628    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4629        this(context, attrs, defStyleAttr, 0);
4630    }
4631
4632    /**
4633     * Perform inflation from XML and apply a class-specific base style from a
4634     * theme attribute or style resource. This constructor of View allows
4635     * subclasses to use their own base style when they are inflating.
4636     * <p>
4637     * When determining the final value of a particular attribute, there are
4638     * four inputs that come into play:
4639     * <ol>
4640     * <li>Any attribute values in the given AttributeSet.
4641     * <li>The style resource specified in the AttributeSet (named "style").
4642     * <li>The default style specified by <var>defStyleAttr</var>.
4643     * <li>The default style specified by <var>defStyleRes</var>.
4644     * <li>The base values in this theme.
4645     * </ol>
4646     * <p>
4647     * Each of these inputs is considered in-order, with the first listed taking
4648     * precedence over the following ones. In other words, if in the
4649     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4650     * , then the button's text will <em>always</em> be black, regardless of
4651     * what is specified in any of the styles.
4652     *
4653     * @param context The Context the view is running in, through which it can
4654     *        access the current theme, resources, etc.
4655     * @param attrs The attributes of the XML tag that is inflating the view.
4656     * @param defStyleAttr An attribute in the current theme that contains a
4657     *        reference to a style resource that supplies default values for
4658     *        the view. Can be 0 to not look for defaults.
4659     * @param defStyleRes A resource identifier of a style resource that
4660     *        supplies default values for the view, used only if
4661     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4662     *        to not look for defaults.
4663     * @see #View(Context, AttributeSet, int)
4664     */
4665    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4666        this(context);
4667
4668        final TypedArray a = context.obtainStyledAttributes(
4669                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4670
4671        if (mDebugViewAttributes) {
4672            saveAttributeData(attrs, a);
4673        }
4674
4675        Drawable background = null;
4676
4677        int leftPadding = -1;
4678        int topPadding = -1;
4679        int rightPadding = -1;
4680        int bottomPadding = -1;
4681        int startPadding = UNDEFINED_PADDING;
4682        int endPadding = UNDEFINED_PADDING;
4683
4684        int padding = -1;
4685        int paddingHorizontal = -1;
4686        int paddingVertical = -1;
4687
4688        int viewFlagValues = 0;
4689        int viewFlagMasks = 0;
4690
4691        boolean setScrollContainer = false;
4692
4693        int x = 0;
4694        int y = 0;
4695
4696        float tx = 0;
4697        float ty = 0;
4698        float tz = 0;
4699        float elevation = 0;
4700        float rotation = 0;
4701        float rotationX = 0;
4702        float rotationY = 0;
4703        float sx = 1f;
4704        float sy = 1f;
4705        boolean transformSet = false;
4706
4707        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4708        int overScrollMode = mOverScrollMode;
4709        boolean initializeScrollbars = false;
4710        boolean initializeScrollIndicators = false;
4711
4712        boolean startPaddingDefined = false;
4713        boolean endPaddingDefined = false;
4714        boolean leftPaddingDefined = false;
4715        boolean rightPaddingDefined = false;
4716
4717        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4718
4719        // Set default values.
4720        viewFlagValues |= FOCUSABLE_AUTO;
4721        viewFlagMasks |= FOCUSABLE_AUTO;
4722
4723        final int N = a.getIndexCount();
4724        for (int i = 0; i < N; i++) {
4725            int attr = a.getIndex(i);
4726            switch (attr) {
4727                case com.android.internal.R.styleable.View_background:
4728                    background = a.getDrawable(attr);
4729                    break;
4730                case com.android.internal.R.styleable.View_padding:
4731                    padding = a.getDimensionPixelSize(attr, -1);
4732                    mUserPaddingLeftInitial = padding;
4733                    mUserPaddingRightInitial = padding;
4734                    leftPaddingDefined = true;
4735                    rightPaddingDefined = true;
4736                    break;
4737                case com.android.internal.R.styleable.View_paddingHorizontal:
4738                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4739                    mUserPaddingLeftInitial = paddingHorizontal;
4740                    mUserPaddingRightInitial = paddingHorizontal;
4741                    leftPaddingDefined = true;
4742                    rightPaddingDefined = true;
4743                    break;
4744                case com.android.internal.R.styleable.View_paddingVertical:
4745                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4746                    break;
4747                 case com.android.internal.R.styleable.View_paddingLeft:
4748                    leftPadding = a.getDimensionPixelSize(attr, -1);
4749                    mUserPaddingLeftInitial = leftPadding;
4750                    leftPaddingDefined = true;
4751                    break;
4752                case com.android.internal.R.styleable.View_paddingTop:
4753                    topPadding = a.getDimensionPixelSize(attr, -1);
4754                    break;
4755                case com.android.internal.R.styleable.View_paddingRight:
4756                    rightPadding = a.getDimensionPixelSize(attr, -1);
4757                    mUserPaddingRightInitial = rightPadding;
4758                    rightPaddingDefined = true;
4759                    break;
4760                case com.android.internal.R.styleable.View_paddingBottom:
4761                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4762                    break;
4763                case com.android.internal.R.styleable.View_paddingStart:
4764                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4765                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4766                    break;
4767                case com.android.internal.R.styleable.View_paddingEnd:
4768                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4769                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4770                    break;
4771                case com.android.internal.R.styleable.View_scrollX:
4772                    x = a.getDimensionPixelOffset(attr, 0);
4773                    break;
4774                case com.android.internal.R.styleable.View_scrollY:
4775                    y = a.getDimensionPixelOffset(attr, 0);
4776                    break;
4777                case com.android.internal.R.styleable.View_alpha:
4778                    setAlpha(a.getFloat(attr, 1f));
4779                    break;
4780                case com.android.internal.R.styleable.View_transformPivotX:
4781                    setPivotX(a.getDimension(attr, 0));
4782                    break;
4783                case com.android.internal.R.styleable.View_transformPivotY:
4784                    setPivotY(a.getDimension(attr, 0));
4785                    break;
4786                case com.android.internal.R.styleable.View_translationX:
4787                    tx = a.getDimension(attr, 0);
4788                    transformSet = true;
4789                    break;
4790                case com.android.internal.R.styleable.View_translationY:
4791                    ty = a.getDimension(attr, 0);
4792                    transformSet = true;
4793                    break;
4794                case com.android.internal.R.styleable.View_translationZ:
4795                    tz = a.getDimension(attr, 0);
4796                    transformSet = true;
4797                    break;
4798                case com.android.internal.R.styleable.View_elevation:
4799                    elevation = a.getDimension(attr, 0);
4800                    transformSet = true;
4801                    break;
4802                case com.android.internal.R.styleable.View_rotation:
4803                    rotation = a.getFloat(attr, 0);
4804                    transformSet = true;
4805                    break;
4806                case com.android.internal.R.styleable.View_rotationX:
4807                    rotationX = a.getFloat(attr, 0);
4808                    transformSet = true;
4809                    break;
4810                case com.android.internal.R.styleable.View_rotationY:
4811                    rotationY = a.getFloat(attr, 0);
4812                    transformSet = true;
4813                    break;
4814                case com.android.internal.R.styleable.View_scaleX:
4815                    sx = a.getFloat(attr, 1f);
4816                    transformSet = true;
4817                    break;
4818                case com.android.internal.R.styleable.View_scaleY:
4819                    sy = a.getFloat(attr, 1f);
4820                    transformSet = true;
4821                    break;
4822                case com.android.internal.R.styleable.View_id:
4823                    mID = a.getResourceId(attr, NO_ID);
4824                    break;
4825                case com.android.internal.R.styleable.View_tag:
4826                    mTag = a.getText(attr);
4827                    break;
4828                case com.android.internal.R.styleable.View_fitsSystemWindows:
4829                    if (a.getBoolean(attr, false)) {
4830                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4831                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4832                    }
4833                    break;
4834                case com.android.internal.R.styleable.View_focusable:
4835                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4836                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4837                        viewFlagMasks |= FOCUSABLE_MASK;
4838                    }
4839                    break;
4840                case com.android.internal.R.styleable.View_focusableInTouchMode:
4841                    if (a.getBoolean(attr, false)) {
4842                        // unset auto focus since focusableInTouchMode implies explicit focusable
4843                        viewFlagValues &= ~FOCUSABLE_AUTO;
4844                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4845                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4846                    }
4847                    break;
4848                case com.android.internal.R.styleable.View_clickable:
4849                    if (a.getBoolean(attr, false)) {
4850                        viewFlagValues |= CLICKABLE;
4851                        viewFlagMasks |= CLICKABLE;
4852                    }
4853                    break;
4854                case com.android.internal.R.styleable.View_longClickable:
4855                    if (a.getBoolean(attr, false)) {
4856                        viewFlagValues |= LONG_CLICKABLE;
4857                        viewFlagMasks |= LONG_CLICKABLE;
4858                    }
4859                    break;
4860                case com.android.internal.R.styleable.View_contextClickable:
4861                    if (a.getBoolean(attr, false)) {
4862                        viewFlagValues |= CONTEXT_CLICKABLE;
4863                        viewFlagMasks |= CONTEXT_CLICKABLE;
4864                    }
4865                    break;
4866                case com.android.internal.R.styleable.View_saveEnabled:
4867                    if (!a.getBoolean(attr, true)) {
4868                        viewFlagValues |= SAVE_DISABLED;
4869                        viewFlagMasks |= SAVE_DISABLED_MASK;
4870                    }
4871                    break;
4872                case com.android.internal.R.styleable.View_duplicateParentState:
4873                    if (a.getBoolean(attr, false)) {
4874                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4875                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4876                    }
4877                    break;
4878                case com.android.internal.R.styleable.View_visibility:
4879                    final int visibility = a.getInt(attr, 0);
4880                    if (visibility != 0) {
4881                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4882                        viewFlagMasks |= VISIBILITY_MASK;
4883                    }
4884                    break;
4885                case com.android.internal.R.styleable.View_layoutDirection:
4886                    // Clear any layout direction flags (included resolved bits) already set
4887                    mPrivateFlags2 &=
4888                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4889                    // Set the layout direction flags depending on the value of the attribute
4890                    final int layoutDirection = a.getInt(attr, -1);
4891                    final int value = (layoutDirection != -1) ?
4892                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4893                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4894                    break;
4895                case com.android.internal.R.styleable.View_drawingCacheQuality:
4896                    final int cacheQuality = a.getInt(attr, 0);
4897                    if (cacheQuality != 0) {
4898                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4899                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4900                    }
4901                    break;
4902                case com.android.internal.R.styleable.View_contentDescription:
4903                    setContentDescription(a.getString(attr));
4904                    break;
4905                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4906                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4907                    break;
4908                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4909                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4910                    break;
4911                case com.android.internal.R.styleable.View_labelFor:
4912                    setLabelFor(a.getResourceId(attr, NO_ID));
4913                    break;
4914                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4915                    if (!a.getBoolean(attr, true)) {
4916                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4917                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4918                    }
4919                    break;
4920                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4921                    if (!a.getBoolean(attr, true)) {
4922                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4923                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4924                    }
4925                    break;
4926                case R.styleable.View_scrollbars:
4927                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4928                    if (scrollbars != SCROLLBARS_NONE) {
4929                        viewFlagValues |= scrollbars;
4930                        viewFlagMasks |= SCROLLBARS_MASK;
4931                        initializeScrollbars = true;
4932                    }
4933                    break;
4934                //noinspection deprecation
4935                case R.styleable.View_fadingEdge:
4936                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4937                        // Ignore the attribute starting with ICS
4938                        break;
4939                    }
4940                    // With builds < ICS, fall through and apply fading edges
4941                case R.styleable.View_requiresFadingEdge:
4942                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4943                    if (fadingEdge != FADING_EDGE_NONE) {
4944                        viewFlagValues |= fadingEdge;
4945                        viewFlagMasks |= FADING_EDGE_MASK;
4946                        initializeFadingEdgeInternal(a);
4947                    }
4948                    break;
4949                case R.styleable.View_scrollbarStyle:
4950                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4951                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4952                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4953                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4954                    }
4955                    break;
4956                case R.styleable.View_isScrollContainer:
4957                    setScrollContainer = true;
4958                    if (a.getBoolean(attr, false)) {
4959                        setScrollContainer(true);
4960                    }
4961                    break;
4962                case com.android.internal.R.styleable.View_keepScreenOn:
4963                    if (a.getBoolean(attr, false)) {
4964                        viewFlagValues |= KEEP_SCREEN_ON;
4965                        viewFlagMasks |= KEEP_SCREEN_ON;
4966                    }
4967                    break;
4968                case R.styleable.View_filterTouchesWhenObscured:
4969                    if (a.getBoolean(attr, false)) {
4970                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4971                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4972                    }
4973                    break;
4974                case R.styleable.View_nextFocusLeft:
4975                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4976                    break;
4977                case R.styleable.View_nextFocusRight:
4978                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4979                    break;
4980                case R.styleable.View_nextFocusUp:
4981                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4982                    break;
4983                case R.styleable.View_nextFocusDown:
4984                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4985                    break;
4986                case R.styleable.View_nextFocusForward:
4987                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4988                    break;
4989                case R.styleable.View_nextClusterForward:
4990                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4991                    break;
4992                case R.styleable.View_minWidth:
4993                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4994                    break;
4995                case R.styleable.View_minHeight:
4996                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4997                    break;
4998                case R.styleable.View_onClick:
4999                    if (context.isRestricted()) {
5000                        throw new IllegalStateException("The android:onClick attribute cannot "
5001                                + "be used within a restricted context");
5002                    }
5003
5004                    final String handlerName = a.getString(attr);
5005                    if (handlerName != null) {
5006                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5007                    }
5008                    break;
5009                case R.styleable.View_overScrollMode:
5010                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5011                    break;
5012                case R.styleable.View_verticalScrollbarPosition:
5013                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5014                    break;
5015                case R.styleable.View_layerType:
5016                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5017                    break;
5018                case R.styleable.View_textDirection:
5019                    // Clear any text direction flag already set
5020                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5021                    // Set the text direction flags depending on the value of the attribute
5022                    final int textDirection = a.getInt(attr, -1);
5023                    if (textDirection != -1) {
5024                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5025                    }
5026                    break;
5027                case R.styleable.View_textAlignment:
5028                    // Clear any text alignment flag already set
5029                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5030                    // Set the text alignment flag depending on the value of the attribute
5031                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5032                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5033                    break;
5034                case R.styleable.View_importantForAccessibility:
5035                    setImportantForAccessibility(a.getInt(attr,
5036                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5037                    break;
5038                case R.styleable.View_accessibilityLiveRegion:
5039                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5040                    break;
5041                case R.styleable.View_transitionName:
5042                    setTransitionName(a.getString(attr));
5043                    break;
5044                case R.styleable.View_nestedScrollingEnabled:
5045                    setNestedScrollingEnabled(a.getBoolean(attr, false));
5046                    break;
5047                case R.styleable.View_stateListAnimator:
5048                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5049                            a.getResourceId(attr, 0)));
5050                    break;
5051                case R.styleable.View_backgroundTint:
5052                    // This will get applied later during setBackground().
5053                    if (mBackgroundTint == null) {
5054                        mBackgroundTint = new TintInfo();
5055                    }
5056                    mBackgroundTint.mTintList = a.getColorStateList(
5057                            R.styleable.View_backgroundTint);
5058                    mBackgroundTint.mHasTintList = true;
5059                    break;
5060                case R.styleable.View_backgroundTintMode:
5061                    // This will get applied later during setBackground().
5062                    if (mBackgroundTint == null) {
5063                        mBackgroundTint = new TintInfo();
5064                    }
5065                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5066                            R.styleable.View_backgroundTintMode, -1), null);
5067                    mBackgroundTint.mHasTintMode = true;
5068                    break;
5069                case R.styleable.View_outlineProvider:
5070                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5071                            PROVIDER_BACKGROUND));
5072                    break;
5073                case R.styleable.View_foreground:
5074                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5075                        setForeground(a.getDrawable(attr));
5076                    }
5077                    break;
5078                case R.styleable.View_foregroundGravity:
5079                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5080                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5081                    }
5082                    break;
5083                case R.styleable.View_foregroundTintMode:
5084                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5085                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5086                    }
5087                    break;
5088                case R.styleable.View_foregroundTint:
5089                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5090                        setForegroundTintList(a.getColorStateList(attr));
5091                    }
5092                    break;
5093                case R.styleable.View_foregroundInsidePadding:
5094                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5095                        if (mForegroundInfo == null) {
5096                            mForegroundInfo = new ForegroundInfo();
5097                        }
5098                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5099                                mForegroundInfo.mInsidePadding);
5100                    }
5101                    break;
5102                case R.styleable.View_scrollIndicators:
5103                    final int scrollIndicators =
5104                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5105                                    & SCROLL_INDICATORS_PFLAG3_MASK;
5106                    if (scrollIndicators != 0) {
5107                        mPrivateFlags3 |= scrollIndicators;
5108                        initializeScrollIndicators = true;
5109                    }
5110                    break;
5111                case R.styleable.View_pointerIcon:
5112                    final int resourceId = a.getResourceId(attr, 0);
5113                    if (resourceId != 0) {
5114                        setPointerIcon(PointerIcon.load(
5115                                context.getResources(), resourceId));
5116                    } else {
5117                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5118                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5119                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5120                        }
5121                    }
5122                    break;
5123                case R.styleable.View_forceHasOverlappingRendering:
5124                    if (a.peekValue(attr) != null) {
5125                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5126                    }
5127                    break;
5128                case R.styleable.View_tooltipText:
5129                    setTooltipText(a.getText(attr));
5130                    break;
5131                case R.styleable.View_keyboardNavigationCluster:
5132                    if (a.peekValue(attr) != null) {
5133                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5134                    }
5135                    break;
5136                case R.styleable.View_focusedByDefault:
5137                    if (a.peekValue(attr) != null) {
5138                        setFocusedByDefault(a.getBoolean(attr, true));
5139                    }
5140                    break;
5141                case R.styleable.View_autofillHints:
5142                    if (a.peekValue(attr) != null) {
5143                        CharSequence[] rawHints = null;
5144                        String rawString = null;
5145
5146                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5147                            int resId = a.getResourceId(attr, 0);
5148
5149                            try {
5150                                rawHints = a.getTextArray(attr);
5151                            } catch (Resources.NotFoundException e) {
5152                                rawString = getResources().getString(resId);
5153                            }
5154                        } else {
5155                            rawString = a.getString(attr);
5156                        }
5157
5158                        if (rawHints == null) {
5159                            if (rawString == null) {
5160                                throw new IllegalArgumentException(
5161                                        "Could not resolve autofillHints");
5162                            } else {
5163                                rawHints = rawString.split(",");
5164                            }
5165                        }
5166
5167                        String[] hints = new String[rawHints.length];
5168
5169                        int numHints = rawHints.length;
5170                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5171                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5172                        }
5173                        setAutofillHints(hints);
5174                    }
5175                    break;
5176                case R.styleable.View_importantForAutofill:
5177                    if (a.peekValue(attr) != null) {
5178                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5179                    }
5180                    break;
5181                case R.styleable.View_defaultFocusHighlightEnabled:
5182                    if (a.peekValue(attr) != null) {
5183                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5184                    }
5185                    break;
5186            }
5187        }
5188
5189        setOverScrollMode(overScrollMode);
5190
5191        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5192        // the resolved layout direction). Those cached values will be used later during padding
5193        // resolution.
5194        mUserPaddingStart = startPadding;
5195        mUserPaddingEnd = endPadding;
5196
5197        if (background != null) {
5198            setBackground(background);
5199        }
5200
5201        // setBackground above will record that padding is currently provided by the background.
5202        // If we have padding specified via xml, record that here instead and use it.
5203        mLeftPaddingDefined = leftPaddingDefined;
5204        mRightPaddingDefined = rightPaddingDefined;
5205
5206        if (padding >= 0) {
5207            leftPadding = padding;
5208            topPadding = padding;
5209            rightPadding = padding;
5210            bottomPadding = padding;
5211            mUserPaddingLeftInitial = padding;
5212            mUserPaddingRightInitial = padding;
5213        } else {
5214            if (paddingHorizontal >= 0) {
5215                leftPadding = paddingHorizontal;
5216                rightPadding = paddingHorizontal;
5217                mUserPaddingLeftInitial = paddingHorizontal;
5218                mUserPaddingRightInitial = paddingHorizontal;
5219            }
5220            if (paddingVertical >= 0) {
5221                topPadding = paddingVertical;
5222                bottomPadding = paddingVertical;
5223            }
5224        }
5225
5226        if (isRtlCompatibilityMode()) {
5227            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5228            // left / right padding are used if defined (meaning here nothing to do). If they are not
5229            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5230            // start / end and resolve them as left / right (layout direction is not taken into account).
5231            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5232            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5233            // defined.
5234            if (!mLeftPaddingDefined && startPaddingDefined) {
5235                leftPadding = startPadding;
5236            }
5237            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5238            if (!mRightPaddingDefined && endPaddingDefined) {
5239                rightPadding = endPadding;
5240            }
5241            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5242        } else {
5243            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5244            // values defined. Otherwise, left /right values are used.
5245            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5246            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5247            // defined.
5248            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5249
5250            if (mLeftPaddingDefined && !hasRelativePadding) {
5251                mUserPaddingLeftInitial = leftPadding;
5252            }
5253            if (mRightPaddingDefined && !hasRelativePadding) {
5254                mUserPaddingRightInitial = rightPadding;
5255            }
5256        }
5257
5258        internalSetPadding(
5259                mUserPaddingLeftInitial,
5260                topPadding >= 0 ? topPadding : mPaddingTop,
5261                mUserPaddingRightInitial,
5262                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5263
5264        if (viewFlagMasks != 0) {
5265            setFlags(viewFlagValues, viewFlagMasks);
5266        }
5267
5268        if (initializeScrollbars) {
5269            initializeScrollbarsInternal(a);
5270        }
5271
5272        if (initializeScrollIndicators) {
5273            initializeScrollIndicatorsInternal();
5274        }
5275
5276        a.recycle();
5277
5278        // Needs to be called after mViewFlags is set
5279        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5280            recomputePadding();
5281        }
5282
5283        if (x != 0 || y != 0) {
5284            scrollTo(x, y);
5285        }
5286
5287        if (transformSet) {
5288            setTranslationX(tx);
5289            setTranslationY(ty);
5290            setTranslationZ(tz);
5291            setElevation(elevation);
5292            setRotation(rotation);
5293            setRotationX(rotationX);
5294            setRotationY(rotationY);
5295            setScaleX(sx);
5296            setScaleY(sy);
5297        }
5298
5299        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5300            setScrollContainer(true);
5301        }
5302
5303        computeOpaqueFlags();
5304    }
5305
5306    /**
5307     * An implementation of OnClickListener that attempts to lazily load a
5308     * named click handling method from a parent or ancestor context.
5309     */
5310    private static class DeclaredOnClickListener implements OnClickListener {
5311        private final View mHostView;
5312        private final String mMethodName;
5313
5314        private Method mResolvedMethod;
5315        private Context mResolvedContext;
5316
5317        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5318            mHostView = hostView;
5319            mMethodName = methodName;
5320        }
5321
5322        @Override
5323        public void onClick(@NonNull View v) {
5324            if (mResolvedMethod == null) {
5325                resolveMethod(mHostView.getContext(), mMethodName);
5326            }
5327
5328            try {
5329                mResolvedMethod.invoke(mResolvedContext, v);
5330            } catch (IllegalAccessException e) {
5331                throw new IllegalStateException(
5332                        "Could not execute non-public method for android:onClick", e);
5333            } catch (InvocationTargetException e) {
5334                throw new IllegalStateException(
5335                        "Could not execute method for android:onClick", e);
5336            }
5337        }
5338
5339        @NonNull
5340        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5341            while (context != null) {
5342                try {
5343                    if (!context.isRestricted()) {
5344                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5345                        if (method != null) {
5346                            mResolvedMethod = method;
5347                            mResolvedContext = context;
5348                            return;
5349                        }
5350                    }
5351                } catch (NoSuchMethodException e) {
5352                    // Failed to find method, keep searching up the hierarchy.
5353                }
5354
5355                if (context instanceof ContextWrapper) {
5356                    context = ((ContextWrapper) context).getBaseContext();
5357                } else {
5358                    // Can't search up the hierarchy, null out and fail.
5359                    context = null;
5360                }
5361            }
5362
5363            final int id = mHostView.getId();
5364            final String idText = id == NO_ID ? "" : " with id '"
5365                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5366            throw new IllegalStateException("Could not find method " + mMethodName
5367                    + "(View) in a parent or ancestor Context for android:onClick "
5368                    + "attribute defined on view " + mHostView.getClass() + idText);
5369        }
5370    }
5371
5372    /**
5373     * Non-public constructor for use in testing
5374     */
5375    View() {
5376        mResources = null;
5377        mRenderNode = RenderNode.create(getClass().getName(), this);
5378    }
5379
5380    final boolean debugDraw() {
5381        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5382    }
5383
5384    private static SparseArray<String> getAttributeMap() {
5385        if (mAttributeMap == null) {
5386            mAttributeMap = new SparseArray<>();
5387        }
5388        return mAttributeMap;
5389    }
5390
5391    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5392        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5393        final int indexCount = t.getIndexCount();
5394        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5395
5396        int i = 0;
5397
5398        // Store raw XML attributes.
5399        for (int j = 0; j < attrsCount; ++j) {
5400            attributes[i] = attrs.getAttributeName(j);
5401            attributes[i + 1] = attrs.getAttributeValue(j);
5402            i += 2;
5403        }
5404
5405        // Store resolved styleable attributes.
5406        final Resources res = t.getResources();
5407        final SparseArray<String> attributeMap = getAttributeMap();
5408        for (int j = 0; j < indexCount; ++j) {
5409            final int index = t.getIndex(j);
5410            if (!t.hasValueOrEmpty(index)) {
5411                // Value is undefined. Skip it.
5412                continue;
5413            }
5414
5415            final int resourceId = t.getResourceId(index, 0);
5416            if (resourceId == 0) {
5417                // Value is not a reference. Skip it.
5418                continue;
5419            }
5420
5421            String resourceName = attributeMap.get(resourceId);
5422            if (resourceName == null) {
5423                try {
5424                    resourceName = res.getResourceName(resourceId);
5425                } catch (Resources.NotFoundException e) {
5426                    resourceName = "0x" + Integer.toHexString(resourceId);
5427                }
5428                attributeMap.put(resourceId, resourceName);
5429            }
5430
5431            attributes[i] = resourceName;
5432            attributes[i + 1] = t.getString(index);
5433            i += 2;
5434        }
5435
5436        // Trim to fit contents.
5437        final String[] trimmed = new String[i];
5438        System.arraycopy(attributes, 0, trimmed, 0, i);
5439        mAttributes = trimmed;
5440    }
5441
5442    public String toString() {
5443        StringBuilder out = new StringBuilder(128);
5444        out.append(getClass().getName());
5445        out.append('{');
5446        out.append(Integer.toHexString(System.identityHashCode(this)));
5447        out.append(' ');
5448        switch (mViewFlags&VISIBILITY_MASK) {
5449            case VISIBLE: out.append('V'); break;
5450            case INVISIBLE: out.append('I'); break;
5451            case GONE: out.append('G'); break;
5452            default: out.append('.'); break;
5453        }
5454        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5455        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5456        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5457        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5458        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5459        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5460        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5461        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5462        out.append(' ');
5463        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5464        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5465        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5466        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5467            out.append('p');
5468        } else {
5469            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5470        }
5471        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5472        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5473        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5474        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5475        out.append(' ');
5476        out.append(mLeft);
5477        out.append(',');
5478        out.append(mTop);
5479        out.append('-');
5480        out.append(mRight);
5481        out.append(',');
5482        out.append(mBottom);
5483        final int id = getId();
5484        if (id != NO_ID) {
5485            out.append(" #");
5486            out.append(Integer.toHexString(id));
5487            final Resources r = mResources;
5488            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5489                try {
5490                    String pkgname;
5491                    switch (id&0xff000000) {
5492                        case 0x7f000000:
5493                            pkgname="app";
5494                            break;
5495                        case 0x01000000:
5496                            pkgname="android";
5497                            break;
5498                        default:
5499                            pkgname = r.getResourcePackageName(id);
5500                            break;
5501                    }
5502                    String typename = r.getResourceTypeName(id);
5503                    String entryname = r.getResourceEntryName(id);
5504                    out.append(" ");
5505                    out.append(pkgname);
5506                    out.append(":");
5507                    out.append(typename);
5508                    out.append("/");
5509                    out.append(entryname);
5510                } catch (Resources.NotFoundException e) {
5511                }
5512            }
5513        }
5514        out.append("}");
5515        return out.toString();
5516    }
5517
5518    /**
5519     * <p>
5520     * Initializes the fading edges from a given set of styled attributes. This
5521     * method should be called by subclasses that need fading edges and when an
5522     * instance of these subclasses is created programmatically rather than
5523     * being inflated from XML. This method is automatically called when the XML
5524     * is inflated.
5525     * </p>
5526     *
5527     * @param a the styled attributes set to initialize the fading edges from
5528     *
5529     * @removed
5530     */
5531    protected void initializeFadingEdge(TypedArray a) {
5532        // This method probably shouldn't have been included in the SDK to begin with.
5533        // It relies on 'a' having been initialized using an attribute filter array that is
5534        // not publicly available to the SDK. The old method has been renamed
5535        // to initializeFadingEdgeInternal and hidden for framework use only;
5536        // this one initializes using defaults to make it safe to call for apps.
5537
5538        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5539
5540        initializeFadingEdgeInternal(arr);
5541
5542        arr.recycle();
5543    }
5544
5545    /**
5546     * <p>
5547     * Initializes the fading edges from a given set of styled attributes. This
5548     * method should be called by subclasses that need fading edges and when an
5549     * instance of these subclasses is created programmatically rather than
5550     * being inflated from XML. This method is automatically called when the XML
5551     * is inflated.
5552     * </p>
5553     *
5554     * @param a the styled attributes set to initialize the fading edges from
5555     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5556     */
5557    protected void initializeFadingEdgeInternal(TypedArray a) {
5558        initScrollCache();
5559
5560        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5561                R.styleable.View_fadingEdgeLength,
5562                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5563    }
5564
5565    /**
5566     * Returns the size of the vertical faded edges used to indicate that more
5567     * content in this view is visible.
5568     *
5569     * @return The size in pixels of the vertical faded edge or 0 if vertical
5570     *         faded edges are not enabled for this view.
5571     * @attr ref android.R.styleable#View_fadingEdgeLength
5572     */
5573    public int getVerticalFadingEdgeLength() {
5574        if (isVerticalFadingEdgeEnabled()) {
5575            ScrollabilityCache cache = mScrollCache;
5576            if (cache != null) {
5577                return cache.fadingEdgeLength;
5578            }
5579        }
5580        return 0;
5581    }
5582
5583    /**
5584     * Set the size of the faded edge used to indicate that more content in this
5585     * view is available.  Will not change whether the fading edge is enabled; use
5586     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5587     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5588     * for the vertical or horizontal fading edges.
5589     *
5590     * @param length The size in pixels of the faded edge used to indicate that more
5591     *        content in this view is visible.
5592     */
5593    public void setFadingEdgeLength(int length) {
5594        initScrollCache();
5595        mScrollCache.fadingEdgeLength = length;
5596    }
5597
5598    /**
5599     * Returns the size of the horizontal faded edges used to indicate that more
5600     * content in this view is visible.
5601     *
5602     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5603     *         faded edges are not enabled for this view.
5604     * @attr ref android.R.styleable#View_fadingEdgeLength
5605     */
5606    public int getHorizontalFadingEdgeLength() {
5607        if (isHorizontalFadingEdgeEnabled()) {
5608            ScrollabilityCache cache = mScrollCache;
5609            if (cache != null) {
5610                return cache.fadingEdgeLength;
5611            }
5612        }
5613        return 0;
5614    }
5615
5616    /**
5617     * Returns the width of the vertical scrollbar.
5618     *
5619     * @return The width in pixels of the vertical scrollbar or 0 if there
5620     *         is no vertical scrollbar.
5621     */
5622    public int getVerticalScrollbarWidth() {
5623        ScrollabilityCache cache = mScrollCache;
5624        if (cache != null) {
5625            ScrollBarDrawable scrollBar = cache.scrollBar;
5626            if (scrollBar != null) {
5627                int size = scrollBar.getSize(true);
5628                if (size <= 0) {
5629                    size = cache.scrollBarSize;
5630                }
5631                return size;
5632            }
5633            return 0;
5634        }
5635        return 0;
5636    }
5637
5638    /**
5639     * Returns the height of the horizontal scrollbar.
5640     *
5641     * @return The height in pixels of the horizontal scrollbar or 0 if
5642     *         there is no horizontal scrollbar.
5643     */
5644    protected int getHorizontalScrollbarHeight() {
5645        ScrollabilityCache cache = mScrollCache;
5646        if (cache != null) {
5647            ScrollBarDrawable scrollBar = cache.scrollBar;
5648            if (scrollBar != null) {
5649                int size = scrollBar.getSize(false);
5650                if (size <= 0) {
5651                    size = cache.scrollBarSize;
5652                }
5653                return size;
5654            }
5655            return 0;
5656        }
5657        return 0;
5658    }
5659
5660    /**
5661     * <p>
5662     * Initializes the scrollbars from a given set of styled attributes. This
5663     * method should be called by subclasses that need scrollbars and when an
5664     * instance of these subclasses is created programmatically rather than
5665     * being inflated from XML. This method is automatically called when the XML
5666     * is inflated.
5667     * </p>
5668     *
5669     * @param a the styled attributes set to initialize the scrollbars from
5670     *
5671     * @removed
5672     */
5673    protected void initializeScrollbars(TypedArray a) {
5674        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5675        // using the View filter array which is not available to the SDK. As such, internal
5676        // framework usage now uses initializeScrollbarsInternal and we grab a default
5677        // TypedArray with the right filter instead here.
5678        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5679
5680        initializeScrollbarsInternal(arr);
5681
5682        // We ignored the method parameter. Recycle the one we actually did use.
5683        arr.recycle();
5684    }
5685
5686    /**
5687     * <p>
5688     * Initializes the scrollbars from a given set of styled attributes. This
5689     * method should be called by subclasses that need scrollbars and when an
5690     * instance of these subclasses is created programmatically rather than
5691     * being inflated from XML. This method is automatically called when the XML
5692     * is inflated.
5693     * </p>
5694     *
5695     * @param a the styled attributes set to initialize the scrollbars from
5696     * @hide
5697     */
5698    protected void initializeScrollbarsInternal(TypedArray a) {
5699        initScrollCache();
5700
5701        final ScrollabilityCache scrollabilityCache = mScrollCache;
5702
5703        if (scrollabilityCache.scrollBar == null) {
5704            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5705            scrollabilityCache.scrollBar.setState(getDrawableState());
5706            scrollabilityCache.scrollBar.setCallback(this);
5707        }
5708
5709        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5710
5711        if (!fadeScrollbars) {
5712            scrollabilityCache.state = ScrollabilityCache.ON;
5713        }
5714        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5715
5716
5717        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5718                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5719                        .getScrollBarFadeDuration());
5720        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5721                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5722                ViewConfiguration.getScrollDefaultDelay());
5723
5724
5725        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5726                com.android.internal.R.styleable.View_scrollbarSize,
5727                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5728
5729        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5730        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5731
5732        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5733        if (thumb != null) {
5734            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5735        }
5736
5737        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5738                false);
5739        if (alwaysDraw) {
5740            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5741        }
5742
5743        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5744        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5745
5746        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5747        if (thumb != null) {
5748            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5749        }
5750
5751        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5752                false);
5753        if (alwaysDraw) {
5754            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5755        }
5756
5757        // Apply layout direction to the new Drawables if needed
5758        final int layoutDirection = getLayoutDirection();
5759        if (track != null) {
5760            track.setLayoutDirection(layoutDirection);
5761        }
5762        if (thumb != null) {
5763            thumb.setLayoutDirection(layoutDirection);
5764        }
5765
5766        // Re-apply user/background padding so that scrollbar(s) get added
5767        resolvePadding();
5768    }
5769
5770    private void initializeScrollIndicatorsInternal() {
5771        // Some day maybe we'll break this into top/left/start/etc. and let the
5772        // client control it. Until then, you can have any scroll indicator you
5773        // want as long as it's a 1dp foreground-colored rectangle.
5774        if (mScrollIndicatorDrawable == null) {
5775            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5776        }
5777    }
5778
5779    /**
5780     * <p>
5781     * Initalizes the scrollability cache if necessary.
5782     * </p>
5783     */
5784    private void initScrollCache() {
5785        if (mScrollCache == null) {
5786            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5787        }
5788    }
5789
5790    private ScrollabilityCache getScrollCache() {
5791        initScrollCache();
5792        return mScrollCache;
5793    }
5794
5795    /**
5796     * Set the position of the vertical scroll bar. Should be one of
5797     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5798     * {@link #SCROLLBAR_POSITION_RIGHT}.
5799     *
5800     * @param position Where the vertical scroll bar should be positioned.
5801     */
5802    public void setVerticalScrollbarPosition(int position) {
5803        if (mVerticalScrollbarPosition != position) {
5804            mVerticalScrollbarPosition = position;
5805            computeOpaqueFlags();
5806            resolvePadding();
5807        }
5808    }
5809
5810    /**
5811     * @return The position where the vertical scroll bar will show, if applicable.
5812     * @see #setVerticalScrollbarPosition(int)
5813     */
5814    public int getVerticalScrollbarPosition() {
5815        return mVerticalScrollbarPosition;
5816    }
5817
5818    boolean isOnScrollbar(float x, float y) {
5819        if (mScrollCache == null) {
5820            return false;
5821        }
5822        x += getScrollX();
5823        y += getScrollY();
5824        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5825            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5826            getVerticalScrollBarBounds(null, touchBounds);
5827            if (touchBounds.contains((int) x, (int) y)) {
5828                return true;
5829            }
5830        }
5831        if (isHorizontalScrollBarEnabled()) {
5832            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5833            getHorizontalScrollBarBounds(null, touchBounds);
5834            if (touchBounds.contains((int) x, (int) y)) {
5835                return true;
5836            }
5837        }
5838        return false;
5839    }
5840
5841    boolean isOnScrollbarThumb(float x, float y) {
5842        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5843    }
5844
5845    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5846        if (mScrollCache == null) {
5847            return false;
5848        }
5849        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5850            x += getScrollX();
5851            y += getScrollY();
5852            final Rect bounds = mScrollCache.mScrollBarBounds;
5853            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5854            getVerticalScrollBarBounds(bounds, touchBounds);
5855            final int range = computeVerticalScrollRange();
5856            final int offset = computeVerticalScrollOffset();
5857            final int extent = computeVerticalScrollExtent();
5858            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5859                    extent, range);
5860            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5861                    extent, range, offset);
5862            final int thumbTop = bounds.top + thumbOffset;
5863            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5864            if (x >= touchBounds.left && x <= touchBounds.right
5865                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5866                return true;
5867            }
5868        }
5869        return false;
5870    }
5871
5872    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5873        if (mScrollCache == null) {
5874            return false;
5875        }
5876        if (isHorizontalScrollBarEnabled()) {
5877            x += getScrollX();
5878            y += getScrollY();
5879            final Rect bounds = mScrollCache.mScrollBarBounds;
5880            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5881            getHorizontalScrollBarBounds(bounds, touchBounds);
5882            final int range = computeHorizontalScrollRange();
5883            final int offset = computeHorizontalScrollOffset();
5884            final int extent = computeHorizontalScrollExtent();
5885            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5886                    extent, range);
5887            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5888                    extent, range, offset);
5889            final int thumbLeft = bounds.left + thumbOffset;
5890            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5891            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5892                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5893                return true;
5894            }
5895        }
5896        return false;
5897    }
5898
5899    boolean isDraggingScrollBar() {
5900        return mScrollCache != null
5901                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5902    }
5903
5904    /**
5905     * Sets the state of all scroll indicators.
5906     * <p>
5907     * See {@link #setScrollIndicators(int, int)} for usage information.
5908     *
5909     * @param indicators a bitmask of indicators that should be enabled, or
5910     *                   {@code 0} to disable all indicators
5911     * @see #setScrollIndicators(int, int)
5912     * @see #getScrollIndicators()
5913     * @attr ref android.R.styleable#View_scrollIndicators
5914     */
5915    public void setScrollIndicators(@ScrollIndicators int indicators) {
5916        setScrollIndicators(indicators,
5917                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5918    }
5919
5920    /**
5921     * Sets the state of the scroll indicators specified by the mask. To change
5922     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5923     * <p>
5924     * When a scroll indicator is enabled, it will be displayed if the view
5925     * can scroll in the direction of the indicator.
5926     * <p>
5927     * Multiple indicator types may be enabled or disabled by passing the
5928     * logical OR of the desired types. If multiple types are specified, they
5929     * will all be set to the same enabled state.
5930     * <p>
5931     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5932     *
5933     * @param indicators the indicator direction, or the logical OR of multiple
5934     *             indicator directions. One or more of:
5935     *             <ul>
5936     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5937     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5938     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5939     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5940     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5941     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5942     *             </ul>
5943     * @see #setScrollIndicators(int)
5944     * @see #getScrollIndicators()
5945     * @attr ref android.R.styleable#View_scrollIndicators
5946     */
5947    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5948        // Shift and sanitize mask.
5949        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5950        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5951
5952        // Shift and mask indicators.
5953        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5954        indicators &= mask;
5955
5956        // Merge with non-masked flags.
5957        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5958
5959        if (mPrivateFlags3 != updatedFlags) {
5960            mPrivateFlags3 = updatedFlags;
5961
5962            if (indicators != 0) {
5963                initializeScrollIndicatorsInternal();
5964            }
5965            invalidate();
5966        }
5967    }
5968
5969    /**
5970     * Returns a bitmask representing the enabled scroll indicators.
5971     * <p>
5972     * For example, if the top and left scroll indicators are enabled and all
5973     * other indicators are disabled, the return value will be
5974     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5975     * <p>
5976     * To check whether the bottom scroll indicator is enabled, use the value
5977     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5978     *
5979     * @return a bitmask representing the enabled scroll indicators
5980     */
5981    @ScrollIndicators
5982    public int getScrollIndicators() {
5983        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5984                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5985    }
5986
5987    ListenerInfo getListenerInfo() {
5988        if (mListenerInfo != null) {
5989            return mListenerInfo;
5990        }
5991        mListenerInfo = new ListenerInfo();
5992        return mListenerInfo;
5993    }
5994
5995    /**
5996     * Register a callback to be invoked when the scroll X or Y positions of
5997     * this view change.
5998     * <p>
5999     * <b>Note:</b> Some views handle scrolling independently from View and may
6000     * have their own separate listeners for scroll-type events. For example,
6001     * {@link android.widget.ListView ListView} allows clients to register an
6002     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6003     * to listen for changes in list scroll position.
6004     *
6005     * @param l The listener to notify when the scroll X or Y position changes.
6006     * @see android.view.View#getScrollX()
6007     * @see android.view.View#getScrollY()
6008     */
6009    public void setOnScrollChangeListener(OnScrollChangeListener l) {
6010        getListenerInfo().mOnScrollChangeListener = l;
6011    }
6012
6013    /**
6014     * Register a callback to be invoked when focus of this view changed.
6015     *
6016     * @param l The callback that will run.
6017     */
6018    public void setOnFocusChangeListener(OnFocusChangeListener l) {
6019        getListenerInfo().mOnFocusChangeListener = l;
6020    }
6021
6022    /**
6023     * Add a listener that will be called when the bounds of the view change due to
6024     * layout processing.
6025     *
6026     * @param listener The listener that will be called when layout bounds change.
6027     */
6028    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6029        ListenerInfo li = getListenerInfo();
6030        if (li.mOnLayoutChangeListeners == null) {
6031            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6032        }
6033        if (!li.mOnLayoutChangeListeners.contains(listener)) {
6034            li.mOnLayoutChangeListeners.add(listener);
6035        }
6036    }
6037
6038    /**
6039     * Remove a listener for layout changes.
6040     *
6041     * @param listener The listener for layout bounds change.
6042     */
6043    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6044        ListenerInfo li = mListenerInfo;
6045        if (li == null || li.mOnLayoutChangeListeners == null) {
6046            return;
6047        }
6048        li.mOnLayoutChangeListeners.remove(listener);
6049    }
6050
6051    /**
6052     * Add a listener for attach state changes.
6053     *
6054     * This listener will be called whenever this view is attached or detached
6055     * from a window. Remove the listener using
6056     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6057     *
6058     * @param listener Listener to attach
6059     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6060     */
6061    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6062        ListenerInfo li = getListenerInfo();
6063        if (li.mOnAttachStateChangeListeners == null) {
6064            li.mOnAttachStateChangeListeners
6065                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6066        }
6067        li.mOnAttachStateChangeListeners.add(listener);
6068    }
6069
6070    /**
6071     * Remove a listener for attach state changes. The listener will receive no further
6072     * notification of window attach/detach events.
6073     *
6074     * @param listener Listener to remove
6075     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6076     */
6077    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6078        ListenerInfo li = mListenerInfo;
6079        if (li == null || li.mOnAttachStateChangeListeners == null) {
6080            return;
6081        }
6082        li.mOnAttachStateChangeListeners.remove(listener);
6083    }
6084
6085    /**
6086     * Returns the focus-change callback registered for this view.
6087     *
6088     * @return The callback, or null if one is not registered.
6089     */
6090    public OnFocusChangeListener getOnFocusChangeListener() {
6091        ListenerInfo li = mListenerInfo;
6092        return li != null ? li.mOnFocusChangeListener : null;
6093    }
6094
6095    /**
6096     * Register a callback to be invoked when this view is clicked. If this view is not
6097     * clickable, it becomes clickable.
6098     *
6099     * @param l The callback that will run
6100     *
6101     * @see #setClickable(boolean)
6102     */
6103    public void setOnClickListener(@Nullable OnClickListener l) {
6104        if (!isClickable()) {
6105            setClickable(true);
6106        }
6107        getListenerInfo().mOnClickListener = l;
6108    }
6109
6110    /**
6111     * Return whether this view has an attached OnClickListener.  Returns
6112     * true if there is a listener, false if there is none.
6113     */
6114    public boolean hasOnClickListeners() {
6115        ListenerInfo li = mListenerInfo;
6116        return (li != null && li.mOnClickListener != null);
6117    }
6118
6119    /**
6120     * Register a callback to be invoked when this view is clicked and held. If this view is not
6121     * long clickable, it becomes long clickable.
6122     *
6123     * @param l The callback that will run
6124     *
6125     * @see #setLongClickable(boolean)
6126     */
6127    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6128        if (!isLongClickable()) {
6129            setLongClickable(true);
6130        }
6131        getListenerInfo().mOnLongClickListener = l;
6132    }
6133
6134    /**
6135     * Register a callback to be invoked when this view is context clicked. If the view is not
6136     * context clickable, it becomes context clickable.
6137     *
6138     * @param l The callback that will run
6139     * @see #setContextClickable(boolean)
6140     */
6141    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6142        if (!isContextClickable()) {
6143            setContextClickable(true);
6144        }
6145        getListenerInfo().mOnContextClickListener = l;
6146    }
6147
6148    /**
6149     * Register a callback to be invoked when the context menu for this view is
6150     * being built. If this view is not long clickable, it becomes long clickable.
6151     *
6152     * @param l The callback that will run
6153     *
6154     */
6155    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6156        if (!isLongClickable()) {
6157            setLongClickable(true);
6158        }
6159        getListenerInfo().mOnCreateContextMenuListener = l;
6160    }
6161
6162    /**
6163     * Set an observer to collect stats for each frame rendered for this view.
6164     *
6165     * @hide
6166     */
6167    public void addFrameMetricsListener(Window window,
6168            Window.OnFrameMetricsAvailableListener listener,
6169            Handler handler) {
6170        if (mAttachInfo != null) {
6171            if (mAttachInfo.mThreadedRenderer != null) {
6172                if (mFrameMetricsObservers == null) {
6173                    mFrameMetricsObservers = new ArrayList<>();
6174                }
6175
6176                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6177                        handler.getLooper(), listener);
6178                mFrameMetricsObservers.add(fmo);
6179                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6180            } else {
6181                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6182            }
6183        } else {
6184            if (mFrameMetricsObservers == null) {
6185                mFrameMetricsObservers = new ArrayList<>();
6186            }
6187
6188            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6189                    handler.getLooper(), listener);
6190            mFrameMetricsObservers.add(fmo);
6191        }
6192    }
6193
6194    /**
6195     * Remove observer configured to collect frame stats for this view.
6196     *
6197     * @hide
6198     */
6199    public void removeFrameMetricsListener(
6200            Window.OnFrameMetricsAvailableListener listener) {
6201        ThreadedRenderer renderer = getThreadedRenderer();
6202        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6203        if (fmo == null) {
6204            throw new IllegalArgumentException(
6205                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6206        }
6207
6208        if (mFrameMetricsObservers != null) {
6209            mFrameMetricsObservers.remove(fmo);
6210            if (renderer != null) {
6211                renderer.removeFrameMetricsObserver(fmo);
6212            }
6213        }
6214    }
6215
6216    private void registerPendingFrameMetricsObservers() {
6217        if (mFrameMetricsObservers != null) {
6218            ThreadedRenderer renderer = getThreadedRenderer();
6219            if (renderer != null) {
6220                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6221                    renderer.addFrameMetricsObserver(fmo);
6222                }
6223            } else {
6224                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6225            }
6226        }
6227    }
6228
6229    private FrameMetricsObserver findFrameMetricsObserver(
6230            Window.OnFrameMetricsAvailableListener listener) {
6231        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6232            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6233            if (observer.mListener == listener) {
6234                return observer;
6235            }
6236        }
6237
6238        return null;
6239    }
6240
6241    /**
6242     * Call this view's OnClickListener, if it is defined.  Performs all normal
6243     * actions associated with clicking: reporting accessibility event, playing
6244     * a sound, etc.
6245     *
6246     * @return True there was an assigned OnClickListener that was called, false
6247     *         otherwise is returned.
6248     */
6249    public boolean performClick() {
6250        final boolean result;
6251        final ListenerInfo li = mListenerInfo;
6252        if (li != null && li.mOnClickListener != null) {
6253            playSoundEffect(SoundEffectConstants.CLICK);
6254            li.mOnClickListener.onClick(this);
6255            result = true;
6256        } else {
6257            result = false;
6258        }
6259
6260        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6261
6262        notifyEnterOrExitForAutoFillIfNeeded(true);
6263
6264        return result;
6265    }
6266
6267    /**
6268     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6269     * this only calls the listener, and does not do any associated clicking
6270     * actions like reporting an accessibility event.
6271     *
6272     * @return True there was an assigned OnClickListener that was called, false
6273     *         otherwise is returned.
6274     */
6275    public boolean callOnClick() {
6276        ListenerInfo li = mListenerInfo;
6277        if (li != null && li.mOnClickListener != null) {
6278            li.mOnClickListener.onClick(this);
6279            return true;
6280        }
6281        return false;
6282    }
6283
6284    /**
6285     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6286     * context menu if the OnLongClickListener did not consume the event.
6287     *
6288     * @return {@code true} if one of the above receivers consumed the event,
6289     *         {@code false} otherwise
6290     */
6291    public boolean performLongClick() {
6292        return performLongClickInternal(mLongClickX, mLongClickY);
6293    }
6294
6295    /**
6296     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6297     * context menu if the OnLongClickListener did not consume the event,
6298     * anchoring it to an (x,y) coordinate.
6299     *
6300     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6301     *          to disable anchoring
6302     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6303     *          to disable anchoring
6304     * @return {@code true} if one of the above receivers consumed the event,
6305     *         {@code false} otherwise
6306     */
6307    public boolean performLongClick(float x, float y) {
6308        mLongClickX = x;
6309        mLongClickY = y;
6310        final boolean handled = performLongClick();
6311        mLongClickX = Float.NaN;
6312        mLongClickY = Float.NaN;
6313        return handled;
6314    }
6315
6316    /**
6317     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6318     * context menu if the OnLongClickListener did not consume the event,
6319     * optionally anchoring it to an (x,y) coordinate.
6320     *
6321     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6322     *          to disable anchoring
6323     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6324     *          to disable anchoring
6325     * @return {@code true} if one of the above receivers consumed the event,
6326     *         {@code false} otherwise
6327     */
6328    private boolean performLongClickInternal(float x, float y) {
6329        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6330
6331        boolean handled = false;
6332        final ListenerInfo li = mListenerInfo;
6333        if (li != null && li.mOnLongClickListener != null) {
6334            handled = li.mOnLongClickListener.onLongClick(View.this);
6335        }
6336        if (!handled) {
6337            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6338            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6339        }
6340        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6341            if (!handled) {
6342                handled = showLongClickTooltip((int) x, (int) y);
6343            }
6344        }
6345        if (handled) {
6346            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6347        }
6348        return handled;
6349    }
6350
6351    /**
6352     * Call this view's OnContextClickListener, if it is defined.
6353     *
6354     * @param x the x coordinate of the context click
6355     * @param y the y coordinate of the context click
6356     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6357     *         otherwise.
6358     */
6359    public boolean performContextClick(float x, float y) {
6360        return performContextClick();
6361    }
6362
6363    /**
6364     * Call this view's OnContextClickListener, if it is defined.
6365     *
6366     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6367     *         otherwise.
6368     */
6369    public boolean performContextClick() {
6370        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6371
6372        boolean handled = false;
6373        ListenerInfo li = mListenerInfo;
6374        if (li != null && li.mOnContextClickListener != null) {
6375            handled = li.mOnContextClickListener.onContextClick(View.this);
6376        }
6377        if (handled) {
6378            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6379        }
6380        return handled;
6381    }
6382
6383    /**
6384     * Performs button-related actions during a touch down event.
6385     *
6386     * @param event The event.
6387     * @return True if the down was consumed.
6388     *
6389     * @hide
6390     */
6391    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6392        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6393            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6394            showContextMenu(event.getX(), event.getY());
6395            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6396            return true;
6397        }
6398        return false;
6399    }
6400
6401    /**
6402     * Shows the context menu for this view.
6403     *
6404     * @return {@code true} if the context menu was shown, {@code false}
6405     *         otherwise
6406     * @see #showContextMenu(float, float)
6407     */
6408    public boolean showContextMenu() {
6409        return getParent().showContextMenuForChild(this);
6410    }
6411
6412    /**
6413     * Shows the context menu for this view anchored to the specified
6414     * view-relative coordinate.
6415     *
6416     * @param x the X coordinate in pixels relative to the view to which the
6417     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6418     * @param y the Y coordinate in pixels relative to the view to which the
6419     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6420     * @return {@code true} if the context menu was shown, {@code false}
6421     *         otherwise
6422     */
6423    public boolean showContextMenu(float x, float y) {
6424        return getParent().showContextMenuForChild(this, x, y);
6425    }
6426
6427    /**
6428     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6429     *
6430     * @param callback Callback that will control the lifecycle of the action mode
6431     * @return The new action mode if it is started, null otherwise
6432     *
6433     * @see ActionMode
6434     * @see #startActionMode(android.view.ActionMode.Callback, int)
6435     */
6436    public ActionMode startActionMode(ActionMode.Callback callback) {
6437        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6438    }
6439
6440    /**
6441     * Start an action mode with the given type.
6442     *
6443     * @param callback Callback that will control the lifecycle of the action mode
6444     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6445     * @return The new action mode if it is started, null otherwise
6446     *
6447     * @see ActionMode
6448     */
6449    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6450        ViewParent parent = getParent();
6451        if (parent == null) return null;
6452        try {
6453            return parent.startActionModeForChild(this, callback, type);
6454        } catch (AbstractMethodError ame) {
6455            // Older implementations of custom views might not implement this.
6456            return parent.startActionModeForChild(this, callback);
6457        }
6458    }
6459
6460    /**
6461     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6462     * Context, creating a unique View identifier to retrieve the result.
6463     *
6464     * @param intent The Intent to be started.
6465     * @param requestCode The request code to use.
6466     * @hide
6467     */
6468    public void startActivityForResult(Intent intent, int requestCode) {
6469        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6470        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6471    }
6472
6473    /**
6474     * If this View corresponds to the calling who, dispatches the activity result.
6475     * @param who The identifier for the targeted View to receive the result.
6476     * @param requestCode The integer request code originally supplied to
6477     *                    startActivityForResult(), allowing you to identify who this
6478     *                    result came from.
6479     * @param resultCode The integer result code returned by the child activity
6480     *                   through its setResult().
6481     * @param data An Intent, which can return result data to the caller
6482     *               (various data can be attached to Intent "extras").
6483     * @return {@code true} if the activity result was dispatched.
6484     * @hide
6485     */
6486    public boolean dispatchActivityResult(
6487            String who, int requestCode, int resultCode, Intent data) {
6488        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6489            onActivityResult(requestCode, resultCode, data);
6490            mStartActivityRequestWho = null;
6491            return true;
6492        }
6493        return false;
6494    }
6495
6496    /**
6497     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6498     *
6499     * @param requestCode The integer request code originally supplied to
6500     *                    startActivityForResult(), allowing you to identify who this
6501     *                    result came from.
6502     * @param resultCode The integer result code returned by the child activity
6503     *                   through its setResult().
6504     * @param data An Intent, which can return result data to the caller
6505     *               (various data can be attached to Intent "extras").
6506     * @hide
6507     */
6508    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6509        // Do nothing.
6510    }
6511
6512    /**
6513     * Register a callback to be invoked when a hardware key is pressed in this view.
6514     * Key presses in software input methods will generally not trigger the methods of
6515     * this listener.
6516     * @param l the key listener to attach to this view
6517     */
6518    public void setOnKeyListener(OnKeyListener l) {
6519        getListenerInfo().mOnKeyListener = l;
6520    }
6521
6522    /**
6523     * Register a callback to be invoked when a touch event is sent to this view.
6524     * @param l the touch listener to attach to this view
6525     */
6526    public void setOnTouchListener(OnTouchListener l) {
6527        getListenerInfo().mOnTouchListener = l;
6528    }
6529
6530    /**
6531     * Register a callback to be invoked when a generic motion event is sent to this view.
6532     * @param l the generic motion listener to attach to this view
6533     */
6534    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6535        getListenerInfo().mOnGenericMotionListener = l;
6536    }
6537
6538    /**
6539     * Register a callback to be invoked when a hover event is sent to this view.
6540     * @param l the hover listener to attach to this view
6541     */
6542    public void setOnHoverListener(OnHoverListener l) {
6543        getListenerInfo().mOnHoverListener = l;
6544    }
6545
6546    /**
6547     * Register a drag event listener callback object for this View. The parameter is
6548     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6549     * View, the system calls the
6550     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6551     * @param l An implementation of {@link android.view.View.OnDragListener}.
6552     */
6553    public void setOnDragListener(OnDragListener l) {
6554        getListenerInfo().mOnDragListener = l;
6555    }
6556
6557    /**
6558     * Give this view focus. This will cause
6559     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6560     *
6561     * Note: this does not check whether this {@link View} should get focus, it just
6562     * gives it focus no matter what.  It should only be called internally by framework
6563     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6564     *
6565     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6566     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6567     *        focus moved when requestFocus() is called. It may not always
6568     *        apply, in which case use the default View.FOCUS_DOWN.
6569     * @param previouslyFocusedRect The rectangle of the view that had focus
6570     *        prior in this View's coordinate system.
6571     */
6572    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6573        if (DBG) {
6574            System.out.println(this + " requestFocus()");
6575        }
6576
6577        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6578            mPrivateFlags |= PFLAG_FOCUSED;
6579
6580            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6581
6582            if (mParent != null) {
6583                mParent.requestChildFocus(this, this);
6584                updateFocusedInCluster(oldFocus, direction);
6585            }
6586
6587            if (mAttachInfo != null) {
6588                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6589            }
6590
6591            onFocusChanged(true, direction, previouslyFocusedRect);
6592            refreshDrawableState();
6593        }
6594    }
6595
6596    /**
6597     * Sets this view's preference for reveal behavior when it gains focus.
6598     *
6599     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6600     * this view would prefer to be brought fully into view when it gains focus.
6601     * For example, a text field that a user is meant to type into. Other views such
6602     * as scrolling containers may prefer to opt-out of this behavior.</p>
6603     *
6604     * <p>The default value for views is true, though subclasses may change this
6605     * based on their preferred behavior.</p>
6606     *
6607     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6608     *
6609     * @see #getRevealOnFocusHint()
6610     */
6611    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6612        if (revealOnFocus) {
6613            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6614        } else {
6615            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6616        }
6617    }
6618
6619    /**
6620     * Returns this view's preference for reveal behavior when it gains focus.
6621     *
6622     * <p>When this method returns true for a child view requesting focus, ancestor
6623     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6624     * should make a best effort to make the newly focused child fully visible to the user.
6625     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6626     * other properties affecting visibility to the user as part of the focus change.</p>
6627     *
6628     * @return true if this view would prefer to become fully visible when it gains focus,
6629     *         false if it would prefer not to disrupt scroll positioning
6630     *
6631     * @see #setRevealOnFocusHint(boolean)
6632     */
6633    public final boolean getRevealOnFocusHint() {
6634        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6635    }
6636
6637    /**
6638     * Populates <code>outRect</code> with the hotspot bounds. By default,
6639     * the hotspot bounds are identical to the screen bounds.
6640     *
6641     * @param outRect rect to populate with hotspot bounds
6642     * @hide Only for internal use by views and widgets.
6643     */
6644    public void getHotspotBounds(Rect outRect) {
6645        final Drawable background = getBackground();
6646        if (background != null) {
6647            background.getHotspotBounds(outRect);
6648        } else {
6649            getBoundsOnScreen(outRect);
6650        }
6651    }
6652
6653    /**
6654     * Request that a rectangle of this view be visible on the screen,
6655     * scrolling if necessary just enough.
6656     *
6657     * <p>A View should call this if it maintains some notion of which part
6658     * of its content is interesting.  For example, a text editing view
6659     * should call this when its cursor moves.
6660     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6661     * It should not be affected by which part of the View is currently visible or its scroll
6662     * position.
6663     *
6664     * @param rectangle The rectangle in the View's content coordinate space
6665     * @return Whether any parent scrolled.
6666     */
6667    public boolean requestRectangleOnScreen(Rect rectangle) {
6668        return requestRectangleOnScreen(rectangle, false);
6669    }
6670
6671    /**
6672     * Request that a rectangle of this view be visible on the screen,
6673     * scrolling if necessary just enough.
6674     *
6675     * <p>A View should call this if it maintains some notion of which part
6676     * of its content is interesting.  For example, a text editing view
6677     * should call this when its cursor moves.
6678     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6679     * It should not be affected by which part of the View is currently visible or its scroll
6680     * position.
6681     * <p>When <code>immediate</code> is set to true, scrolling will not be
6682     * animated.
6683     *
6684     * @param rectangle The rectangle in the View's content coordinate space
6685     * @param immediate True to forbid animated scrolling, false otherwise
6686     * @return Whether any parent scrolled.
6687     */
6688    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6689        if (mParent == null) {
6690            return false;
6691        }
6692
6693        View child = this;
6694
6695        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6696        position.set(rectangle);
6697
6698        ViewParent parent = mParent;
6699        boolean scrolled = false;
6700        while (parent != null) {
6701            rectangle.set((int) position.left, (int) position.top,
6702                    (int) position.right, (int) position.bottom);
6703
6704            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6705
6706            if (!(parent instanceof View)) {
6707                break;
6708            }
6709
6710            // move it from child's content coordinate space to parent's content coordinate space
6711            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6712
6713            child = (View) parent;
6714            parent = child.getParent();
6715        }
6716
6717        return scrolled;
6718    }
6719
6720    /**
6721     * Called when this view wants to give up focus. If focus is cleared
6722     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6723     * <p>
6724     * <strong>Note:</strong> When a View clears focus the framework is trying
6725     * to give focus to the first focusable View from the top. Hence, if this
6726     * View is the first from the top that can take focus, then all callbacks
6727     * related to clearing focus will be invoked after which the framework will
6728     * give focus to this view.
6729     * </p>
6730     */
6731    public void clearFocus() {
6732        if (DBG) {
6733            System.out.println(this + " clearFocus()");
6734        }
6735
6736        clearFocusInternal(null, true, true);
6737    }
6738
6739    /**
6740     * Clears focus from the view, optionally propagating the change up through
6741     * the parent hierarchy and requesting that the root view place new focus.
6742     *
6743     * @param propagate whether to propagate the change up through the parent
6744     *            hierarchy
6745     * @param refocus when propagate is true, specifies whether to request the
6746     *            root view place new focus
6747     */
6748    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6749        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6750            mPrivateFlags &= ~PFLAG_FOCUSED;
6751
6752            if (propagate && mParent != null) {
6753                mParent.clearChildFocus(this);
6754            }
6755
6756            onFocusChanged(false, 0, null);
6757            refreshDrawableState();
6758
6759            if (propagate && (!refocus || !rootViewRequestFocus())) {
6760                notifyGlobalFocusCleared(this);
6761            }
6762        }
6763    }
6764
6765    void notifyGlobalFocusCleared(View oldFocus) {
6766        if (oldFocus != null && mAttachInfo != null) {
6767            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6768        }
6769    }
6770
6771    boolean rootViewRequestFocus() {
6772        final View root = getRootView();
6773        return root != null && root.requestFocus();
6774    }
6775
6776    /**
6777     * Called internally by the view system when a new view is getting focus.
6778     * This is what clears the old focus.
6779     * <p>
6780     * <b>NOTE:</b> The parent view's focused child must be updated manually
6781     * after calling this method. Otherwise, the view hierarchy may be left in
6782     * an inconstent state.
6783     */
6784    void unFocus(View focused) {
6785        if (DBG) {
6786            System.out.println(this + " unFocus()");
6787        }
6788
6789        clearFocusInternal(focused, false, false);
6790    }
6791
6792    /**
6793     * Returns true if this view has focus itself, or is the ancestor of the
6794     * view that has focus.
6795     *
6796     * @return True if this view has or contains focus, false otherwise.
6797     */
6798    @ViewDebug.ExportedProperty(category = "focus")
6799    public boolean hasFocus() {
6800        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6801    }
6802
6803    /**
6804     * Returns true if this view is focusable or if it contains a reachable View
6805     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6806     * is a view whose parents do not block descendants focus.
6807     * Only {@link #VISIBLE} views are considered focusable.
6808     *
6809     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6810     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6811     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6812     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6813     * {@code false} for views not explicitly marked as focusable.
6814     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6815     * behavior.</p>
6816     *
6817     * @return {@code true} if the view is focusable or if the view contains a focusable
6818     *         view, {@code false} otherwise
6819     *
6820     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6821     * @see ViewGroup#getTouchscreenBlocksFocus()
6822     * @see #hasExplicitFocusable()
6823     */
6824    public boolean hasFocusable() {
6825        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6826    }
6827
6828    /**
6829     * Returns true if this view is focusable or if it contains a reachable View
6830     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6831     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6832     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6833     * {@link #FOCUSABLE} are considered focusable.
6834     *
6835     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6836     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6837     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6838     * to focusable will not.</p>
6839     *
6840     * @return {@code true} if the view is focusable or if the view contains a focusable
6841     *         view, {@code false} otherwise
6842     *
6843     * @see #hasFocusable()
6844     */
6845    public boolean hasExplicitFocusable() {
6846        return hasFocusable(false, true);
6847    }
6848
6849    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6850        if (!isFocusableInTouchMode()) {
6851            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6852                final ViewGroup g = (ViewGroup) p;
6853                if (g.shouldBlockFocusForTouchscreen()) {
6854                    return false;
6855                }
6856            }
6857        }
6858
6859        // Invisible and gone views are never focusable.
6860        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6861            return false;
6862        }
6863
6864        // Only use effective focusable value when allowed.
6865        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6866            return true;
6867        }
6868
6869        return false;
6870    }
6871
6872    /**
6873     * Called by the view system when the focus state of this view changes.
6874     * When the focus change event is caused by directional navigation, direction
6875     * and previouslyFocusedRect provide insight into where the focus is coming from.
6876     * When overriding, be sure to call up through to the super class so that
6877     * the standard focus handling will occur.
6878     *
6879     * @param gainFocus True if the View has focus; false otherwise.
6880     * @param direction The direction focus has moved when requestFocus()
6881     *                  is called to give this view focus. Values are
6882     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6883     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6884     *                  It may not always apply, in which case use the default.
6885     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6886     *        system, of the previously focused view.  If applicable, this will be
6887     *        passed in as finer grained information about where the focus is coming
6888     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6889     */
6890    @CallSuper
6891    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6892            @Nullable Rect previouslyFocusedRect) {
6893        if (gainFocus) {
6894            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6895        } else {
6896            notifyViewAccessibilityStateChangedIfNeeded(
6897                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6898        }
6899
6900        // Here we check whether we still need the default focus highlight, and switch it on/off.
6901        switchDefaultFocusHighlight();
6902
6903        InputMethodManager imm = InputMethodManager.peekInstance();
6904        if (!gainFocus) {
6905            if (isPressed()) {
6906                setPressed(false);
6907            }
6908            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6909                imm.focusOut(this);
6910            }
6911            onFocusLost();
6912        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6913            imm.focusIn(this);
6914        }
6915
6916        invalidate(true);
6917        ListenerInfo li = mListenerInfo;
6918        if (li != null && li.mOnFocusChangeListener != null) {
6919            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6920        }
6921
6922        if (mAttachInfo != null) {
6923            mAttachInfo.mKeyDispatchState.reset(this);
6924        }
6925
6926        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6927    }
6928
6929    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6930        if (isAutofillable() && isAttachedToWindow()) {
6931            AutofillManager afm = getAutofillManager();
6932            if (afm != null) {
6933                if (enter && hasWindowFocus() && isFocused()) {
6934                    // We have not been laid out yet, hence cannot evaluate
6935                    // whether this view is visible to the user, we will do
6936                    // the evaluation once layout is complete.
6937                    if (!isLaidOut()) {
6938                        mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
6939                    } else if (isVisibleToUser()) {
6940                        afm.notifyViewEntered(this);
6941                    }
6942                } else if (!hasWindowFocus() || !isFocused()) {
6943                    afm.notifyViewExited(this);
6944                }
6945            }
6946        }
6947    }
6948
6949    /**
6950     * Sends an accessibility event of the given type. If accessibility is
6951     * not enabled this method has no effect. The default implementation calls
6952     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6953     * to populate information about the event source (this View), then calls
6954     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6955     * populate the text content of the event source including its descendants,
6956     * and last calls
6957     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6958     * on its parent to request sending of the event to interested parties.
6959     * <p>
6960     * If an {@link AccessibilityDelegate} has been specified via calling
6961     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6962     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6963     * responsible for handling this call.
6964     * </p>
6965     *
6966     * @param eventType The type of the event to send, as defined by several types from
6967     * {@link android.view.accessibility.AccessibilityEvent}, such as
6968     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6969     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6970     *
6971     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6972     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6973     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6974     * @see AccessibilityDelegate
6975     */
6976    public void sendAccessibilityEvent(int eventType) {
6977        if (mAccessibilityDelegate != null) {
6978            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6979        } else {
6980            sendAccessibilityEventInternal(eventType);
6981        }
6982    }
6983
6984    /**
6985     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6986     * {@link AccessibilityEvent} to make an announcement which is related to some
6987     * sort of a context change for which none of the events representing UI transitions
6988     * is a good fit. For example, announcing a new page in a book. If accessibility
6989     * is not enabled this method does nothing.
6990     *
6991     * @param text The announcement text.
6992     */
6993    public void announceForAccessibility(CharSequence text) {
6994        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6995            AccessibilityEvent event = AccessibilityEvent.obtain(
6996                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6997            onInitializeAccessibilityEvent(event);
6998            event.getText().add(text);
6999            event.setContentDescription(null);
7000            mParent.requestSendAccessibilityEvent(this, event);
7001        }
7002    }
7003
7004    /**
7005     * @see #sendAccessibilityEvent(int)
7006     *
7007     * Note: Called from the default {@link AccessibilityDelegate}.
7008     *
7009     * @hide
7010     */
7011    public void sendAccessibilityEventInternal(int eventType) {
7012        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7013            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7014        }
7015    }
7016
7017    /**
7018     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7019     * takes as an argument an empty {@link AccessibilityEvent} and does not
7020     * perform a check whether accessibility is enabled.
7021     * <p>
7022     * If an {@link AccessibilityDelegate} has been specified via calling
7023     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7024     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7025     * is responsible for handling this call.
7026     * </p>
7027     *
7028     * @param event The event to send.
7029     *
7030     * @see #sendAccessibilityEvent(int)
7031     */
7032    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7033        if (mAccessibilityDelegate != null) {
7034            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7035        } else {
7036            sendAccessibilityEventUncheckedInternal(event);
7037        }
7038    }
7039
7040    /**
7041     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7042     *
7043     * Note: Called from the default {@link AccessibilityDelegate}.
7044     *
7045     * @hide
7046     */
7047    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7048        if (!isShown()) {
7049            return;
7050        }
7051        onInitializeAccessibilityEvent(event);
7052        // Only a subset of accessibility events populates text content.
7053        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7054            dispatchPopulateAccessibilityEvent(event);
7055        }
7056        // In the beginning we called #isShown(), so we know that getParent() is not null.
7057        ViewParent parent = getParent();
7058        if (parent != null) {
7059            getParent().requestSendAccessibilityEvent(this, event);
7060        }
7061    }
7062
7063    /**
7064     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7065     * to its children for adding their text content to the event. Note that the
7066     * event text is populated in a separate dispatch path since we add to the
7067     * event not only the text of the source but also the text of all its descendants.
7068     * A typical implementation will call
7069     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7070     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7071     * on each child. Override this method if custom population of the event text
7072     * content is required.
7073     * <p>
7074     * If an {@link AccessibilityDelegate} has been specified via calling
7075     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7076     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7077     * is responsible for handling this call.
7078     * </p>
7079     * <p>
7080     * <em>Note:</em> Accessibility events of certain types are not dispatched for
7081     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7082     * </p>
7083     *
7084     * @param event The event.
7085     *
7086     * @return True if the event population was completed.
7087     */
7088    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7089        if (mAccessibilityDelegate != null) {
7090            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7091        } else {
7092            return dispatchPopulateAccessibilityEventInternal(event);
7093        }
7094    }
7095
7096    /**
7097     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7098     *
7099     * Note: Called from the default {@link AccessibilityDelegate}.
7100     *
7101     * @hide
7102     */
7103    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7104        onPopulateAccessibilityEvent(event);
7105        return false;
7106    }
7107
7108    /**
7109     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7110     * giving a chance to this View to populate the accessibility event with its
7111     * text content. While this method is free to modify event
7112     * attributes other than text content, doing so should normally be performed in
7113     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7114     * <p>
7115     * Example: Adding formatted date string to an accessibility event in addition
7116     *          to the text added by the super implementation:
7117     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7118     *     super.onPopulateAccessibilityEvent(event);
7119     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7120     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7121     *         mCurrentDate.getTimeInMillis(), flags);
7122     *     event.getText().add(selectedDateUtterance);
7123     * }</pre>
7124     * <p>
7125     * If an {@link AccessibilityDelegate} has been specified via calling
7126     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7127     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7128     * is responsible for handling this call.
7129     * </p>
7130     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7131     * information to the event, in case the default implementation has basic information to add.
7132     * </p>
7133     *
7134     * @param event The accessibility event which to populate.
7135     *
7136     * @see #sendAccessibilityEvent(int)
7137     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7138     */
7139    @CallSuper
7140    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7141        if (mAccessibilityDelegate != null) {
7142            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7143        } else {
7144            onPopulateAccessibilityEventInternal(event);
7145        }
7146    }
7147
7148    /**
7149     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7150     *
7151     * Note: Called from the default {@link AccessibilityDelegate}.
7152     *
7153     * @hide
7154     */
7155    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7156    }
7157
7158    /**
7159     * Initializes an {@link AccessibilityEvent} with information about
7160     * this View which is the event source. In other words, the source of
7161     * an accessibility event is the view whose state change triggered firing
7162     * the event.
7163     * <p>
7164     * Example: Setting the password property of an event in addition
7165     *          to properties set by the super implementation:
7166     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7167     *     super.onInitializeAccessibilityEvent(event);
7168     *     event.setPassword(true);
7169     * }</pre>
7170     * <p>
7171     * If an {@link AccessibilityDelegate} has been specified via calling
7172     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7173     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7174     * is responsible for handling this call.
7175     * </p>
7176     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7177     * information to the event, in case the default implementation has basic information to add.
7178     * </p>
7179     * @param event The event to initialize.
7180     *
7181     * @see #sendAccessibilityEvent(int)
7182     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7183     */
7184    @CallSuper
7185    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7186        if (mAccessibilityDelegate != null) {
7187            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7188        } else {
7189            onInitializeAccessibilityEventInternal(event);
7190        }
7191    }
7192
7193    /**
7194     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7195     *
7196     * Note: Called from the default {@link AccessibilityDelegate}.
7197     *
7198     * @hide
7199     */
7200    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7201        event.setSource(this);
7202        event.setClassName(getAccessibilityClassName());
7203        event.setPackageName(getContext().getPackageName());
7204        event.setEnabled(isEnabled());
7205        event.setContentDescription(mContentDescription);
7206
7207        switch (event.getEventType()) {
7208            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7209                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7210                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7211                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7212                event.setItemCount(focusablesTempList.size());
7213                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7214                if (mAttachInfo != null) {
7215                    focusablesTempList.clear();
7216                }
7217            } break;
7218            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7219                CharSequence text = getIterableTextForAccessibility();
7220                if (text != null && text.length() > 0) {
7221                    event.setFromIndex(getAccessibilitySelectionStart());
7222                    event.setToIndex(getAccessibilitySelectionEnd());
7223                    event.setItemCount(text.length());
7224                }
7225            } break;
7226        }
7227    }
7228
7229    /**
7230     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7231     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7232     * This method is responsible for obtaining an accessibility node info from a
7233     * pool of reusable instances and calling
7234     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7235     * initialize the former.
7236     * <p>
7237     * Note: The client is responsible for recycling the obtained instance by calling
7238     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7239     * </p>
7240     *
7241     * @return A populated {@link AccessibilityNodeInfo}.
7242     *
7243     * @see AccessibilityNodeInfo
7244     */
7245    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7246        if (mAccessibilityDelegate != null) {
7247            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7248        } else {
7249            return createAccessibilityNodeInfoInternal();
7250        }
7251    }
7252
7253    /**
7254     * @see #createAccessibilityNodeInfo()
7255     *
7256     * @hide
7257     */
7258    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7259        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7260        if (provider != null) {
7261            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7262        } else {
7263            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7264            onInitializeAccessibilityNodeInfo(info);
7265            return info;
7266        }
7267    }
7268
7269    /**
7270     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7271     * The base implementation sets:
7272     * <ul>
7273     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7274     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7275     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7276     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7277     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7278     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7279     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7280     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7281     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7282     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7283     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7284     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7285     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7286     * </ul>
7287     * <p>
7288     * Subclasses should override this method, call the super implementation,
7289     * and set additional attributes.
7290     * </p>
7291     * <p>
7292     * If an {@link AccessibilityDelegate} has been specified via calling
7293     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7294     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7295     * is responsible for handling this call.
7296     * </p>
7297     *
7298     * @param info The instance to initialize.
7299     */
7300    @CallSuper
7301    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7302        if (mAccessibilityDelegate != null) {
7303            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7304        } else {
7305            onInitializeAccessibilityNodeInfoInternal(info);
7306        }
7307    }
7308
7309    /**
7310     * Gets the location of this view in screen coordinates.
7311     *
7312     * @param outRect The output location
7313     * @hide
7314     */
7315    public void getBoundsOnScreen(Rect outRect) {
7316        getBoundsOnScreen(outRect, false);
7317    }
7318
7319    /**
7320     * Gets the location of this view in screen coordinates.
7321     *
7322     * @param outRect The output location
7323     * @param clipToParent Whether to clip child bounds to the parent ones.
7324     * @hide
7325     */
7326    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7327        if (mAttachInfo == null) {
7328            return;
7329        }
7330
7331        RectF position = mAttachInfo.mTmpTransformRect;
7332        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7333        mapRectFromViewToScreenCoords(position, clipToParent);
7334        outRect.set(Math.round(position.left), Math.round(position.top),
7335                Math.round(position.right), Math.round(position.bottom));
7336    }
7337
7338    /**
7339     * Map a rectangle from view-relative coordinates to screen-relative coordinates
7340     *
7341     * @param rect The rectangle to be mapped
7342     * @param clipToParent Whether to clip child bounds to the parent ones.
7343     * @hide
7344     */
7345    public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7346        if (!hasIdentityMatrix()) {
7347            getMatrix().mapRect(rect);
7348        }
7349
7350        rect.offset(mLeft, mTop);
7351
7352        ViewParent parent = mParent;
7353        while (parent instanceof View) {
7354            View parentView = (View) parent;
7355
7356            rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7357
7358            if (clipToParent) {
7359                rect.left = Math.max(rect.left, 0);
7360                rect.top = Math.max(rect.top, 0);
7361                rect.right = Math.min(rect.right, parentView.getWidth());
7362                rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7363            }
7364
7365            if (!parentView.hasIdentityMatrix()) {
7366                parentView.getMatrix().mapRect(rect);
7367            }
7368
7369            rect.offset(parentView.mLeft, parentView.mTop);
7370
7371            parent = parentView.mParent;
7372        }
7373
7374        if (parent instanceof ViewRootImpl) {
7375            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7376            rect.offset(0, -viewRootImpl.mCurScrollY);
7377        }
7378
7379        rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7380    }
7381
7382    /**
7383     * Return the class name of this object to be used for accessibility purposes.
7384     * Subclasses should only override this if they are implementing something that
7385     * should be seen as a completely new class of view when used by accessibility,
7386     * unrelated to the class it is deriving from.  This is used to fill in
7387     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7388     */
7389    public CharSequence getAccessibilityClassName() {
7390        return View.class.getName();
7391    }
7392
7393    /**
7394     * Called when assist structure is being retrieved from a view as part of
7395     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7396     * @param structure Fill in with structured view data.  The default implementation
7397     * fills in all data that can be inferred from the view itself.
7398     */
7399    public void onProvideStructure(ViewStructure structure) {
7400        onProvideStructureForAssistOrAutofill(structure, false, 0);
7401    }
7402
7403    /**
7404     * Populates a {@link ViewStructure} to fullfil an autofill request.
7405     *
7406     * <p>The structure should contain at least the following properties:
7407     * <ul>
7408     *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
7409     *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
7410     *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
7411     *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
7412     * </ul>
7413     *
7414     * <p>It's also recommended to set the following properties - the more properties the structure
7415     * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
7416     * using the structure:
7417     *
7418     * <ul>
7419     *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
7420     *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
7421     *       view can only be filled with predefined values (typically used when the autofill type
7422     *       is {@link #AUTOFILL_TYPE_LIST}).
7423     *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
7424     *   <li>Class name ({@link ViewStructure#setClassName(String)}).
7425     *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
7426     *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
7427     *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
7428     *       opacity ({@link ViewStructure#setOpaque(boolean)}).
7429     *   <li>For views representing text fields, text properties such as the text itself
7430     *       ({@link ViewStructure#setText(CharSequence)}), text hints
7431     *       ({@link ViewStructure#setHint(CharSequence)}, input type
7432     *       ({@link ViewStructure#setInputType(int)}),
7433     *   <li>For views representing HTML nodes, its web domain
7434     *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
7435     *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
7436     * </ul>
7437     *
7438     * <p>The default implementation of this method already sets most of these properties based on
7439     * related {@link View} methods (for example, the autofill id is set using
7440     * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
7441     * and views in the standard Android widgets library also override it to set their
7442     * relevant properties (for example, {@link android.widget.TextView} already sets the text
7443     * properties), so it's recommended to only override this method
7444     * (and call {@code super.onProvideAutofillStructure()}) when:
7445     *
7446     * <ul>
7447     *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7448     *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7449     *   <li>The view can only be autofilled with predefined options, so it can call
7450     *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
7451     * </ul>
7452     *
7453     * <p><b>NOTE:</b> the {@code left} and {@code top} values set in
7454     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
7455     * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
7456     *
7457     * <p>Views support the Autofill Framework mainly by:
7458     * <ul>
7459     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7460     *   <li>Notifying the Android System when the view value changed by calling
7461     *       {@link AutofillManager#notifyValueChanged(View)}.
7462     *   <li>Implementing the methods that autofill the view.
7463     * </ul>
7464     * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
7465     * for the latter.
7466     *
7467     * @param structure fill in with structured view data for autofill purposes.
7468     * @param flags optional flags.
7469     *
7470     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7471     */
7472    public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7473        onProvideStructureForAssistOrAutofill(structure, true, flags);
7474    }
7475
7476    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7477            boolean forAutofill, @AutofillFlags int flags) {
7478        final int id = mID;
7479        if (id != NO_ID && !isViewIdGenerated(id)) {
7480            String pkg, type, entry;
7481            try {
7482                final Resources res = getResources();
7483                entry = res.getResourceEntryName(id);
7484                type = res.getResourceTypeName(id);
7485                pkg = res.getResourcePackageName(id);
7486            } catch (Resources.NotFoundException e) {
7487                entry = type = pkg = null;
7488            }
7489            structure.setId(id, pkg, type, entry);
7490        } else {
7491            structure.setId(id, null, null, null);
7492        }
7493
7494        if (forAutofill) {
7495            final @AutofillType int autofillType = getAutofillType();
7496            // Don't need to fill autofill info if view does not support it.
7497            // For example, only TextViews that are editable support autofill
7498            if (autofillType != AUTOFILL_TYPE_NONE) {
7499                structure.setAutofillType(autofillType);
7500                structure.setAutofillHints(getAutofillHints());
7501                structure.setAutofillValue(getAutofillValue());
7502            }
7503        }
7504
7505        int ignoredParentLeft = 0;
7506        int ignoredParentTop = 0;
7507        if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7508            View parentGroup = null;
7509
7510            ViewParent viewParent = getParent();
7511            if (viewParent instanceof View) {
7512                parentGroup = (View) viewParent;
7513            }
7514
7515            while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7516                ignoredParentLeft += parentGroup.mLeft;
7517                ignoredParentTop += parentGroup.mTop;
7518
7519                viewParent = parentGroup.getParent();
7520                if (viewParent instanceof View) {
7521                    parentGroup = (View) viewParent;
7522                } else {
7523                    break;
7524                }
7525            }
7526        }
7527
7528        structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7529                mRight - mLeft, mBottom - mTop);
7530        if (!forAutofill) {
7531            if (!hasIdentityMatrix()) {
7532                structure.setTransformation(getMatrix());
7533            }
7534            structure.setElevation(getZ());
7535        }
7536        structure.setVisibility(getVisibility());
7537        structure.setEnabled(isEnabled());
7538        if (isClickable()) {
7539            structure.setClickable(true);
7540        }
7541        if (isFocusable()) {
7542            structure.setFocusable(true);
7543        }
7544        if (isFocused()) {
7545            structure.setFocused(true);
7546        }
7547        if (isAccessibilityFocused()) {
7548            structure.setAccessibilityFocused(true);
7549        }
7550        if (isSelected()) {
7551            structure.setSelected(true);
7552        }
7553        if (isActivated()) {
7554            structure.setActivated(true);
7555        }
7556        if (isLongClickable()) {
7557            structure.setLongClickable(true);
7558        }
7559        if (this instanceof Checkable) {
7560            structure.setCheckable(true);
7561            if (((Checkable)this).isChecked()) {
7562                structure.setChecked(true);
7563            }
7564        }
7565        if (isOpaque()) {
7566            structure.setOpaque(true);
7567        }
7568        if (isContextClickable()) {
7569            structure.setContextClickable(true);
7570        }
7571        structure.setClassName(getAccessibilityClassName().toString());
7572        structure.setContentDescription(getContentDescription());
7573    }
7574
7575    /**
7576     * Called when assist structure is being retrieved from a view as part of
7577     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7578     * generate additional virtual structure under this view.  The defaullt implementation
7579     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7580     * view's virtual accessibility nodes, if any.  You can override this for a more
7581     * optimal implementation providing this data.
7582     */
7583    public void onProvideVirtualStructure(ViewStructure structure) {
7584        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7585        if (provider != null) {
7586            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7587            structure.setChildCount(1);
7588            ViewStructure root = structure.newChild(0);
7589            populateVirtualStructure(root, provider, info);
7590            info.recycle();
7591        }
7592    }
7593
7594    /**
7595     * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
7596     * request.
7597     *
7598     * <p>This method should be used when the view manages a virtual structure under this view. For
7599     * example, a view that draws input fields using {@link #draw(Canvas)}.
7600     *
7601     * <p>When implementing this method, subclasses must follow the rules below:
7602     *
7603     * <ul>
7604     *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
7605     *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
7606     *       identifying the children in the virtual structure.
7607     *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
7608     *       exclude intermediate levels that are irrelevant for autofill; that would improve the
7609     *       autofill performance.
7610     *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7611     *       children.
7612     *   <li>Set the autofill properties of the child structure as defined by
7613     *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
7614     *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
7615     *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
7616     *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7617     *       when the focused virtual child changed.
7618     *   <li>Call
7619     *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
7620     *       when the value of a virtual child changed.
7621     *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
7622     *       changed and the current context should be committed (for example, when the user tapped
7623     *       a {@code SUBMIT} button in an HTML page).
7624     *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
7625     *       changed and the current context should be canceled (for example, when the user tapped
7626     *       a {@code CANCEL} button in an HTML page).
7627     *   <li>Provide ways for users to manually request autofill by calling
7628     *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
7629     *   <li>The {@code left} and {@code top} values set in
7630     *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
7631     *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
7632     *       structure.
7633     * </ul>
7634     *
7635     * <p>Views with virtual children support the Autofill Framework mainly by:
7636     * <ul>
7637     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7638     *       autofilled.
7639     *   <li>Implementing the methods that autofill the virtual children.
7640     * </ul>
7641     * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
7642     * for the latter.
7643     *
7644     * @param structure fill in with virtual children data for autofill purposes.
7645     * @param flags optional flags.
7646     *
7647     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7648     */
7649    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7650    }
7651
7652    /**
7653     * Automatically fills the content of this view with the {@code value}.
7654     *
7655     * <p>Views support the Autofill Framework mainly by:
7656     * <ul>
7657     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7658     *   <li>Implementing the methods that autofill the view.
7659     * </ul>
7660     * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
7661     * this method is responsible for latter.
7662     *
7663     * <p>This method does nothing by default, but when overridden it typically:
7664     * <ol>
7665     *   <li>Checks if the provided value matches the expected type (which is defined by
7666     *       {@link #getAutofillType()}).
7667     *   <li>Checks if the view is editable - if it isn't, it should return right away.
7668     *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
7669     *   <li>Pass the actual value to the equivalent setter in the view.
7670     * </ol>
7671     *
7672     * <p>For example, a text-field view could implement the method this way:
7673     *
7674     * <pre class="prettyprint">
7675     * &#64;Override
7676     * public void autofill(AutofillValue value) {
7677     *   if (!value.isText() || !this.isEditable()) {
7678     *      return;
7679     *   }
7680     *   CharSequence text = value.getTextValue();
7681     *   if (text != null) {
7682     *     this.setText(text);
7683     *   }
7684     * }
7685     * </pre>
7686     *
7687     * <p>If the value is updated asynchronously, the next call to
7688     * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
7689     * changed to the autofilled value. If not, the view will not be considered autofilled.
7690     *
7691     * @param value value to be autofilled.
7692     */
7693    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7694    }
7695
7696    /**
7697     * Automatically fills the content of the virtual children within this view.
7698     *
7699     * <p>Views with virtual children support the Autofill Framework mainly by:
7700     * <ul>
7701     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7702     *       autofilled.
7703     *   <li>Implementing the methods that autofill the virtual children.
7704     * </ul>
7705     * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
7706     * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
7707     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
7708     *
7709     * <p>If a child value is updated asynchronously, the next call to
7710     * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
7711     * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
7712     * considered autofilled.
7713     *
7714     * <p><b>NOTE:</b> to indicate that a virtual view was autofilled,
7715     * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7716     * changes.
7717     *
7718     * @param values map of values to be autofilled, keyed by virtual child id.
7719     *
7720     * @attr ref android.R.styleable#Theme_autofilledHighlight
7721     */
7722    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7723    }
7724
7725    /**
7726     * Gets the unique identifier of this view in the screen, for autofill purposes.
7727     *
7728     * @return The View's autofill id.
7729     */
7730    public final AutofillId getAutofillId() {
7731        if (mAutofillId == null) {
7732            // The autofill id needs to be unique, but its value doesn't matter,
7733            // so it's better to reuse the accessibility id to save space.
7734            mAutofillId = new AutofillId(getAutofillViewId());
7735        }
7736        return mAutofillId;
7737    }
7738
7739    /**
7740     * Describes the autofill type of this view, so an
7741     * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
7742     * when autofilling the view.
7743     *
7744     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
7745     * support the Autofill Framework.
7746     *
7747     * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
7748     * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
7749     *
7750     * @see #onProvideAutofillStructure(ViewStructure, int)
7751     * @see #autofill(AutofillValue)
7752     */
7753    public @AutofillType int getAutofillType() {
7754        return AUTOFILL_TYPE_NONE;
7755    }
7756
7757    /**
7758     * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
7759     * to autofill the view with the user's data.
7760     *
7761     * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
7762     *
7763     * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
7764     * {@code null} if no hints were set.
7765     *
7766     * @attr ref android.R.styleable#View_autofillHints
7767     */
7768    @ViewDebug.ExportedProperty()
7769    @Nullable public String[] getAutofillHints() {
7770        return mAutofillHints;
7771    }
7772
7773    /**
7774     * @hide
7775     */
7776    public boolean isAutofilled() {
7777        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7778    }
7779
7780    /**
7781     * Gets the {@link View}'s current autofill value.
7782     *
7783     * <p>By default returns {@code null}, but views should override it to properly support the
7784     * Autofill Framework.
7785     *
7786     * @see #onProvideAutofillStructure(ViewStructure, int)
7787     * @see #autofill(AutofillValue)
7788     */
7789    @Nullable
7790    public AutofillValue getAutofillValue() {
7791        return null;
7792    }
7793
7794    /**
7795     * Gets the mode for determining whether this view is important for autofill.
7796     *
7797     * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
7798     * info about this mode.
7799     *
7800     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7801     * {@link #setImportantForAutofill(int)}.
7802     *
7803     * @attr ref android.R.styleable#View_importantForAutofill
7804     */
7805    @ViewDebug.ExportedProperty(mapping = {
7806            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7807            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7808            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7809            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7810                to = "yesExcludeDescendants"),
7811            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7812                to = "noExcludeDescendants")})
7813    public @AutofillImportance int getImportantForAutofill() {
7814        return (mPrivateFlags3
7815                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7816    }
7817
7818    /**
7819     * Sets the mode for determining whether this view is considered important for autofill.
7820     *
7821     * <p>The platform determines the importance for autofill automatically but you
7822     * can use this method to customize the behavior. For example:
7823     *
7824     * <ol>
7825     *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
7826     *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7827     *   <li>When both the view and its children are irrelevant for autofill (for example, the root
7828     *       view of an activity containing a spreadhseet editor), it should be
7829     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7830     *   <li>When the view content is relevant for autofill but its children aren't (for example,
7831     *       a credit card expiration date represented by a custom view that overrides the proper
7832     *       autofill methods and has 2 children representing the month and year), it should
7833     *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
7834     * </ol>
7835     *
7836     * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7837     * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
7838     * children) will be always be considered not important; for example, when the user explicitly
7839     * makes an autofill request, all views are considered important. See
7840     * {@link #isImportantForAutofill()} for more details about how the View's importance for
7841     * autofill is used.
7842     *
7843     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7844     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7845     * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7846     *
7847     * @attr ref android.R.styleable#View_importantForAutofill
7848     */
7849    public void setImportantForAutofill(@AutofillImportance int mode) {
7850        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7851        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7852                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7853    }
7854
7855    /**
7856     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7857     * associated with this view is considered important for autofill purposes.
7858     *
7859     * <p>Generally speaking, a view is important for autofill if:
7860     * <ol>
7861     * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
7862     * <li>The view contents can help an {@link android.service.autofill.AutofillService}
7863     *     determine how other views can be autofilled.
7864     * <ol>
7865     *
7866     * <p>For example, view containers should typically return {@code false} for performance reasons
7867     * (since the important info is provided by their children), but if its properties have relevant
7868     * information (for example, a resource id called {@code credentials}, it should return
7869     * {@code true}. On the other hand, views representing labels or editable fields should
7870     * typically return {@code true}, but in some cases they could return {@code false}
7871     * (for example, if they're part of a "Captcha" mechanism).
7872     *
7873     * <p>The value returned by this method depends on the value returned by
7874     * {@link #getImportantForAutofill()}:
7875     *
7876     * <ol>
7877     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
7878     *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
7879     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7880     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
7881     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
7882     *       that can return {@code true} in some cases (like a container with a resource id),
7883     *       but {@code false} in most.
7884     *   <li>otherwise, it returns {@code false}.
7885     * </ol>
7886     *
7887     * <p>When a view is considered important for autofill:
7888     * <ul>
7889     *   <li>The view might automatically trigger an autofill request when focused on.
7890     *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
7891     *       request.
7892     * </ul>
7893     *
7894     * <p>On the other hand, when a view is considered not important for autofill:
7895     * <ul>
7896     *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
7897     *       request through {@link AutofillManager#requestAutofill(View)}.
7898     *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
7899     *       autofill request, unless the request has the
7900     *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
7901     * </ul>
7902     *
7903     * @return whether the view is considered important for autofill.
7904     *
7905     * @see #setImportantForAutofill(int)
7906     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7907     * @see #IMPORTANT_FOR_AUTOFILL_YES
7908     * @see #IMPORTANT_FOR_AUTOFILL_NO
7909     * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7910     * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7911     * @see AutofillManager#requestAutofill(View)
7912     */
7913    public final boolean isImportantForAutofill() {
7914        // Check parent mode to ensure we're not hidden.
7915        ViewParent parent = mParent;
7916        while (parent instanceof View) {
7917            final int parentImportance = ((View) parent).getImportantForAutofill();
7918            if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7919                    || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7920                return false;
7921            }
7922            parent = parent.getParent();
7923        }
7924
7925        final int importance = getImportantForAutofill();
7926
7927        // First, check the explicit states.
7928        if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7929                || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7930            return true;
7931        }
7932        if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7933                || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7934            return false;
7935        }
7936
7937        // Then use some heuristics to handle AUTO.
7938
7939        // Always include views that have an explicit resource id.
7940        final int id = mID;
7941        if (id != NO_ID && !isViewIdGenerated(id)) {
7942            final Resources res = getResources();
7943            String entry = null;
7944            String pkg = null;
7945            try {
7946                entry = res.getResourceEntryName(id);
7947                pkg = res.getResourcePackageName(id);
7948            } catch (Resources.NotFoundException e) {
7949                // ignore
7950            }
7951            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7952                return true;
7953            }
7954        }
7955
7956        // Otherwise, assume it's not important...
7957        return false;
7958    }
7959
7960    @Nullable
7961    private AutofillManager getAutofillManager() {
7962        return mContext.getSystemService(AutofillManager.class);
7963    }
7964
7965    private boolean isAutofillable() {
7966        return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
7967                && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
7968    }
7969
7970    private void populateVirtualStructure(ViewStructure structure,
7971            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
7972        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7973                null, null, null);
7974        Rect rect = structure.getTempRect();
7975        info.getBoundsInParent(rect);
7976        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7977        structure.setVisibility(VISIBLE);
7978        structure.setEnabled(info.isEnabled());
7979        if (info.isClickable()) {
7980            structure.setClickable(true);
7981        }
7982        if (info.isFocusable()) {
7983            structure.setFocusable(true);
7984        }
7985        if (info.isFocused()) {
7986            structure.setFocused(true);
7987        }
7988        if (info.isAccessibilityFocused()) {
7989            structure.setAccessibilityFocused(true);
7990        }
7991        if (info.isSelected()) {
7992            structure.setSelected(true);
7993        }
7994        if (info.isLongClickable()) {
7995            structure.setLongClickable(true);
7996        }
7997        if (info.isCheckable()) {
7998            structure.setCheckable(true);
7999            if (info.isChecked()) {
8000                structure.setChecked(true);
8001            }
8002        }
8003        if (info.isContextClickable()) {
8004            structure.setContextClickable(true);
8005        }
8006        CharSequence cname = info.getClassName();
8007        structure.setClassName(cname != null ? cname.toString() : null);
8008        structure.setContentDescription(info.getContentDescription());
8009        if ((info.getText() != null || info.getError() != null)) {
8010            structure.setText(info.getText(), info.getTextSelectionStart(),
8011                    info.getTextSelectionEnd());
8012        }
8013        final int NCHILDREN = info.getChildCount();
8014        if (NCHILDREN > 0) {
8015            structure.setChildCount(NCHILDREN);
8016            for (int i=0; i<NCHILDREN; i++) {
8017                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
8018                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
8019                ViewStructure child = structure.newChild(i);
8020                populateVirtualStructure(child, provider, cinfo);
8021                cinfo.recycle();
8022            }
8023        }
8024    }
8025
8026    /**
8027     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
8028     * implementation calls {@link #onProvideStructure} and
8029     * {@link #onProvideVirtualStructure}.
8030     */
8031    public void dispatchProvideStructure(ViewStructure structure) {
8032        dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
8033    }
8034
8035    /**
8036     * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
8037     * when an Assist structure is being created as part of an autofill request.
8038     *
8039     * <p>The default implementation does the following:
8040     * <ul>
8041     *   <li>Sets the {@link AutofillId} in the structure.
8042     *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
8043     *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
8044     * </ul>
8045     *
8046     * <p>Typically, this method should only be overridden by subclasses that provide a view
8047     * hierarchy (such as {@link ViewGroup}) - other classes should override
8048     * {@link #onProvideAutofillStructure(ViewStructure, int)} or
8049     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
8050     *
8051     * <p>When overridden, it must:
8052     *
8053     * <ul>
8054     *   <li>Either call
8055     *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
8056     *       set the {@link AutofillId} in the structure (for example, by calling
8057     *       {@code structure.setAutofillId(getAutofillId())}).
8058     *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
8059     *       set, all views in the structure should be considered important for autofill,
8060     *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
8061     *       respect this flag to provide a better user experience - this flag is typically used
8062     *       when an user explicitly requested autofill. If the flag is not set,
8063     *       then only views marked as important for autofill should be included in the
8064     *       structure - skipping non-important views optimizes the overall autofill performance.
8065     * </ul>
8066     *
8067     * @param structure fill in with structured view data for autofill purposes.
8068     * @param flags optional flags.
8069     *
8070     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8071     */
8072    public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
8073            @AutofillFlags int flags) {
8074        dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
8075    }
8076
8077    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
8078            boolean forAutofill, @AutofillFlags int flags) {
8079        if (forAutofill) {
8080            structure.setAutofillId(getAutofillId());
8081            if (!isLaidOut()) {
8082                Log.w(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring");
8083                return;
8084            }
8085            onProvideAutofillStructure(structure, flags);
8086            onProvideAutofillVirtualStructure(structure, flags);
8087        } else if (!isAssistBlocked()) {
8088            onProvideStructure(structure);
8089            onProvideVirtualStructure(structure);
8090        } else {
8091            structure.setClassName(getAccessibilityClassName().toString());
8092            structure.setAssistBlocked(true);
8093        }
8094    }
8095
8096    /**
8097     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
8098     *
8099     * Note: Called from the default {@link AccessibilityDelegate}.
8100     *
8101     * @hide
8102     */
8103    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
8104        if (mAttachInfo == null) {
8105            return;
8106        }
8107
8108        Rect bounds = mAttachInfo.mTmpInvalRect;
8109
8110        getDrawingRect(bounds);
8111        info.setBoundsInParent(bounds);
8112
8113        getBoundsOnScreen(bounds, true);
8114        info.setBoundsInScreen(bounds);
8115
8116        ViewParent parent = getParentForAccessibility();
8117        if (parent instanceof View) {
8118            info.setParent((View) parent);
8119        }
8120
8121        if (mID != View.NO_ID) {
8122            View rootView = getRootView();
8123            if (rootView == null) {
8124                rootView = this;
8125            }
8126
8127            View label = rootView.findLabelForView(this, mID);
8128            if (label != null) {
8129                info.setLabeledBy(label);
8130            }
8131
8132            if ((mAttachInfo.mAccessibilityFetchFlags
8133                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
8134                    && Resources.resourceHasPackage(mID)) {
8135                try {
8136                    String viewId = getResources().getResourceName(mID);
8137                    info.setViewIdResourceName(viewId);
8138                } catch (Resources.NotFoundException nfe) {
8139                    /* ignore */
8140                }
8141            }
8142        }
8143
8144        if (mLabelForId != View.NO_ID) {
8145            View rootView = getRootView();
8146            if (rootView == null) {
8147                rootView = this;
8148            }
8149            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
8150            if (labeled != null) {
8151                info.setLabelFor(labeled);
8152            }
8153        }
8154
8155        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
8156            View rootView = getRootView();
8157            if (rootView == null) {
8158                rootView = this;
8159            }
8160            View next = rootView.findViewInsideOutShouldExist(this,
8161                    mAccessibilityTraversalBeforeId);
8162            if (next != null && next.includeForAccessibility()) {
8163                info.setTraversalBefore(next);
8164            }
8165        }
8166
8167        if (mAccessibilityTraversalAfterId != View.NO_ID) {
8168            View rootView = getRootView();
8169            if (rootView == null) {
8170                rootView = this;
8171            }
8172            View next = rootView.findViewInsideOutShouldExist(this,
8173                    mAccessibilityTraversalAfterId);
8174            if (next != null && next.includeForAccessibility()) {
8175                info.setTraversalAfter(next);
8176            }
8177        }
8178
8179        info.setVisibleToUser(isVisibleToUser());
8180
8181        info.setImportantForAccessibility(isImportantForAccessibility());
8182        info.setPackageName(mContext.getPackageName());
8183        info.setClassName(getAccessibilityClassName());
8184        info.setContentDescription(getContentDescription());
8185
8186        info.setEnabled(isEnabled());
8187        info.setClickable(isClickable());
8188        info.setFocusable(isFocusable());
8189        info.setFocused(isFocused());
8190        info.setAccessibilityFocused(isAccessibilityFocused());
8191        info.setSelected(isSelected());
8192        info.setLongClickable(isLongClickable());
8193        info.setContextClickable(isContextClickable());
8194        info.setLiveRegion(getAccessibilityLiveRegion());
8195
8196        // TODO: These make sense only if we are in an AdapterView but all
8197        // views can be selected. Maybe from accessibility perspective
8198        // we should report as selectable view in an AdapterView.
8199        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8200        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8201
8202        if (isFocusable()) {
8203            if (isFocused()) {
8204                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8205            } else {
8206                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8207            }
8208        }
8209
8210        if (!isAccessibilityFocused()) {
8211            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8212        } else {
8213            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8214        }
8215
8216        if (isClickable() && isEnabled()) {
8217            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8218        }
8219
8220        if (isLongClickable() && isEnabled()) {
8221            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8222        }
8223
8224        if (isContextClickable() && isEnabled()) {
8225            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8226        }
8227
8228        CharSequence text = getIterableTextForAccessibility();
8229        if (text != null && text.length() > 0) {
8230            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8231
8232            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8233            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8234            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8235            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8236                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8237                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8238        }
8239
8240        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8241        populateAccessibilityNodeInfoDrawingOrderInParent(info);
8242    }
8243
8244    /**
8245     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8246     * additional data.
8247     * <p>
8248     * This method only needs overloading if the node is marked as having extra data available.
8249     * </p>
8250     *
8251     * @param info The info to which to add the extra data. Never {@code null}.
8252     * @param extraDataKey A key specifying the type of extra data to add to the info. The
8253     *                     extra data should be added to the {@link Bundle} returned by
8254     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8255     *                     {@code null}.
8256     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8257     *                  {@code null} if the service provided no arguments.
8258     *
8259     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8260     */
8261    public void addExtraDataToAccessibilityNodeInfo(
8262            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8263            @Nullable Bundle arguments) {
8264    }
8265
8266    /**
8267     * Determine the order in which this view will be drawn relative to its siblings for a11y
8268     *
8269     * @param info The info whose drawing order should be populated
8270     */
8271    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8272        /*
8273         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8274         * drawing order may not be well-defined, and some Views with custom drawing order may
8275         * not be initialized sufficiently to respond properly getChildDrawingOrder.
8276         */
8277        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8278            info.setDrawingOrder(0);
8279            return;
8280        }
8281        int drawingOrderInParent = 1;
8282        // Iterate up the hierarchy if parents are not important for a11y
8283        View viewAtDrawingLevel = this;
8284        final ViewParent parent = getParentForAccessibility();
8285        while (viewAtDrawingLevel != parent) {
8286            final ViewParent currentParent = viewAtDrawingLevel.getParent();
8287            if (!(currentParent instanceof ViewGroup)) {
8288                // Should only happen for the Decor
8289                drawingOrderInParent = 0;
8290                break;
8291            } else {
8292                final ViewGroup parentGroup = (ViewGroup) currentParent;
8293                final int childCount = parentGroup.getChildCount();
8294                if (childCount > 1) {
8295                    List<View> preorderedList = parentGroup.buildOrderedChildList();
8296                    if (preorderedList != null) {
8297                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8298                        for (int i = 0; i < childDrawIndex; i++) {
8299                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8300                        }
8301                    } else {
8302                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8303                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8304                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8305                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
8306                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8307                        if (childDrawIndex != 0) {
8308                            for (int i = 0; i < numChildrenToIterate; i++) {
8309                                final int otherDrawIndex = (customOrder ?
8310                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
8311                                if (otherDrawIndex < childDrawIndex) {
8312                                    drawingOrderInParent +=
8313                                            numViewsForAccessibility(parentGroup.getChildAt(i));
8314                                }
8315                            }
8316                        }
8317                    }
8318                }
8319            }
8320            viewAtDrawingLevel = (View) currentParent;
8321        }
8322        info.setDrawingOrder(drawingOrderInParent);
8323    }
8324
8325    private static int numViewsForAccessibility(View view) {
8326        if (view != null) {
8327            if (view.includeForAccessibility()) {
8328                return 1;
8329            } else if (view instanceof ViewGroup) {
8330                return ((ViewGroup) view).getNumChildrenForAccessibility();
8331            }
8332        }
8333        return 0;
8334    }
8335
8336    private View findLabelForView(View view, int labeledId) {
8337        if (mMatchLabelForPredicate == null) {
8338            mMatchLabelForPredicate = new MatchLabelForPredicate();
8339        }
8340        mMatchLabelForPredicate.mLabeledId = labeledId;
8341        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8342    }
8343
8344    /**
8345     * Computes whether this view is visible to the user. Such a view is
8346     * attached, visible, all its predecessors are visible, it is not clipped
8347     * entirely by its predecessors, and has an alpha greater than zero.
8348     *
8349     * @return Whether the view is visible on the screen.
8350     *
8351     * @hide
8352     */
8353    protected boolean isVisibleToUser() {
8354        return isVisibleToUser(null);
8355    }
8356
8357    /**
8358     * Computes whether the given portion of this view is visible to the user.
8359     * Such a view is attached, visible, all its predecessors are visible,
8360     * has an alpha greater than zero, and the specified portion is not
8361     * clipped entirely by its predecessors.
8362     *
8363     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8364     *                    <code>null</code>, and the entire view will be tested in this case.
8365     *                    When <code>true</code> is returned by the function, the actual visible
8366     *                    region will be stored in this parameter; that is, if boundInView is fully
8367     *                    contained within the view, no modification will be made, otherwise regions
8368     *                    outside of the visible area of the view will be clipped.
8369     *
8370     * @return Whether the specified portion of the view is visible on the screen.
8371     *
8372     * @hide
8373     */
8374    protected boolean isVisibleToUser(Rect boundInView) {
8375        if (mAttachInfo != null) {
8376            // Attached to invisible window means this view is not visible.
8377            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8378                return false;
8379            }
8380            // An invisible predecessor or one with alpha zero means
8381            // that this view is not visible to the user.
8382            Object current = this;
8383            while (current instanceof View) {
8384                View view = (View) current;
8385                // We have attach info so this view is attached and there is no
8386                // need to check whether we reach to ViewRootImpl on the way up.
8387                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8388                        view.getVisibility() != VISIBLE) {
8389                    return false;
8390                }
8391                current = view.mParent;
8392            }
8393            // Check if the view is entirely covered by its predecessors.
8394            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8395            Point offset = mAttachInfo.mPoint;
8396            if (!getGlobalVisibleRect(visibleRect, offset)) {
8397                return false;
8398            }
8399            // Check if the visible portion intersects the rectangle of interest.
8400            if (boundInView != null) {
8401                visibleRect.offset(-offset.x, -offset.y);
8402                return boundInView.intersect(visibleRect);
8403            }
8404            return true;
8405        }
8406        return false;
8407    }
8408
8409    /**
8410     * Returns the delegate for implementing accessibility support via
8411     * composition. For more details see {@link AccessibilityDelegate}.
8412     *
8413     * @return The delegate, or null if none set.
8414     *
8415     * @hide
8416     */
8417    public AccessibilityDelegate getAccessibilityDelegate() {
8418        return mAccessibilityDelegate;
8419    }
8420
8421    /**
8422     * Sets a delegate for implementing accessibility support via composition
8423     * (as opposed to inheritance). For more details, see
8424     * {@link AccessibilityDelegate}.
8425     * <p>
8426     * <strong>Note:</strong> On platform versions prior to
8427     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8428     * views in the {@code android.widget.*} package are called <i>before</i>
8429     * host methods. This prevents certain properties such as class name from
8430     * being modified by overriding
8431     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8432     * as any changes will be overwritten by the host class.
8433     * <p>
8434     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8435     * methods are called <i>after</i> host methods, which all properties to be
8436     * modified without being overwritten by the host class.
8437     *
8438     * @param delegate the object to which accessibility method calls should be
8439     *                 delegated
8440     * @see AccessibilityDelegate
8441     */
8442    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8443        mAccessibilityDelegate = delegate;
8444    }
8445
8446    /**
8447     * Gets the provider for managing a virtual view hierarchy rooted at this View
8448     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8449     * that explore the window content.
8450     * <p>
8451     * If this method returns an instance, this instance is responsible for managing
8452     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8453     * View including the one representing the View itself. Similarly the returned
8454     * instance is responsible for performing accessibility actions on any virtual
8455     * view or the root view itself.
8456     * </p>
8457     * <p>
8458     * If an {@link AccessibilityDelegate} has been specified via calling
8459     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8460     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8461     * is responsible for handling this call.
8462     * </p>
8463     *
8464     * @return The provider.
8465     *
8466     * @see AccessibilityNodeProvider
8467     */
8468    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8469        if (mAccessibilityDelegate != null) {
8470            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8471        } else {
8472            return null;
8473        }
8474    }
8475
8476    /**
8477     * Gets the unique identifier of this view on the screen for accessibility purposes.
8478     *
8479     * @return The view accessibility id.
8480     *
8481     * @hide
8482     */
8483    public int getAccessibilityViewId() {
8484        if (mAccessibilityViewId == NO_ID) {
8485            mAccessibilityViewId = sNextAccessibilityViewId++;
8486        }
8487        return mAccessibilityViewId;
8488    }
8489
8490    /**
8491     * Gets the unique identifier of this view on the screen for autofill purposes.
8492     *
8493     * @return The view autofill id.
8494     *
8495     * @hide
8496     */
8497    public int getAutofillViewId() {
8498        if (mAutofillViewId == NO_ID) {
8499            mAutofillViewId = mContext.getNextAutofillId();
8500        }
8501        return mAutofillViewId;
8502    }
8503
8504    /**
8505     * Gets the unique identifier of the window in which this View reseides.
8506     *
8507     * @return The window accessibility id.
8508     *
8509     * @hide
8510     */
8511    public int getAccessibilityWindowId() {
8512        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8513                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8514    }
8515
8516    /**
8517     * Returns the {@link View}'s content description.
8518     * <p>
8519     * <strong>Note:</strong> Do not override this method, as it will have no
8520     * effect on the content description presented to accessibility services.
8521     * You must call {@link #setContentDescription(CharSequence)} to modify the
8522     * content description.
8523     *
8524     * @return the content description
8525     * @see #setContentDescription(CharSequence)
8526     * @attr ref android.R.styleable#View_contentDescription
8527     */
8528    @ViewDebug.ExportedProperty(category = "accessibility")
8529    public CharSequence getContentDescription() {
8530        return mContentDescription;
8531    }
8532
8533    /**
8534     * Sets the {@link View}'s content description.
8535     * <p>
8536     * A content description briefly describes the view and is primarily used
8537     * for accessibility support to determine how a view should be presented to
8538     * the user. In the case of a view with no textual representation, such as
8539     * {@link android.widget.ImageButton}, a useful content description
8540     * explains what the view does. For example, an image button with a phone
8541     * icon that is used to place a call may use "Call" as its content
8542     * description. An image of a floppy disk that is used to save a file may
8543     * use "Save".
8544     *
8545     * @param contentDescription The content description.
8546     * @see #getContentDescription()
8547     * @attr ref android.R.styleable#View_contentDescription
8548     */
8549    @RemotableViewMethod
8550    public void setContentDescription(CharSequence contentDescription) {
8551        if (mContentDescription == null) {
8552            if (contentDescription == null) {
8553                return;
8554            }
8555        } else if (mContentDescription.equals(contentDescription)) {
8556            return;
8557        }
8558        mContentDescription = contentDescription;
8559        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8560        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8561            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8562            notifySubtreeAccessibilityStateChangedIfNeeded();
8563        } else {
8564            notifyViewAccessibilityStateChangedIfNeeded(
8565                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8566        }
8567    }
8568
8569    /**
8570     * Sets the id of a view before which this one is visited in accessibility traversal.
8571     * A screen-reader must visit the content of this view before the content of the one
8572     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8573     * will traverse the entire content of B before traversing the entire content of A,
8574     * regardles of what traversal strategy it is using.
8575     * <p>
8576     * Views that do not have specified before/after relationships are traversed in order
8577     * determined by the screen-reader.
8578     * </p>
8579     * <p>
8580     * Setting that this view is before a view that is not important for accessibility
8581     * or if this view is not important for accessibility will have no effect as the
8582     * screen-reader is not aware of unimportant views.
8583     * </p>
8584     *
8585     * @param beforeId The id of a view this one precedes in accessibility traversal.
8586     *
8587     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8588     *
8589     * @see #setImportantForAccessibility(int)
8590     */
8591    @RemotableViewMethod
8592    public void setAccessibilityTraversalBefore(int beforeId) {
8593        if (mAccessibilityTraversalBeforeId == beforeId) {
8594            return;
8595        }
8596        mAccessibilityTraversalBeforeId = beforeId;
8597        notifyViewAccessibilityStateChangedIfNeeded(
8598                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8599    }
8600
8601    /**
8602     * Gets the id of a view before which this one is visited in accessibility traversal.
8603     *
8604     * @return The id of a view this one precedes in accessibility traversal if
8605     *         specified, otherwise {@link #NO_ID}.
8606     *
8607     * @see #setAccessibilityTraversalBefore(int)
8608     */
8609    public int getAccessibilityTraversalBefore() {
8610        return mAccessibilityTraversalBeforeId;
8611    }
8612
8613    /**
8614     * Sets the id of a view after which this one is visited in accessibility traversal.
8615     * A screen-reader must visit the content of the other view before the content of this
8616     * one. For example, if view B is set to be after view A, then a screen-reader
8617     * will traverse the entire content of A before traversing the entire content of B,
8618     * regardles of what traversal strategy it is using.
8619     * <p>
8620     * Views that do not have specified before/after relationships are traversed in order
8621     * determined by the screen-reader.
8622     * </p>
8623     * <p>
8624     * Setting that this view is after a view that is not important for accessibility
8625     * or if this view is not important for accessibility will have no effect as the
8626     * screen-reader is not aware of unimportant views.
8627     * </p>
8628     *
8629     * @param afterId The id of a view this one succedees in accessibility traversal.
8630     *
8631     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8632     *
8633     * @see #setImportantForAccessibility(int)
8634     */
8635    @RemotableViewMethod
8636    public void setAccessibilityTraversalAfter(int afterId) {
8637        if (mAccessibilityTraversalAfterId == afterId) {
8638            return;
8639        }
8640        mAccessibilityTraversalAfterId = afterId;
8641        notifyViewAccessibilityStateChangedIfNeeded(
8642                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8643    }
8644
8645    /**
8646     * Gets the id of a view after which this one is visited in accessibility traversal.
8647     *
8648     * @return The id of a view this one succeedes in accessibility traversal if
8649     *         specified, otherwise {@link #NO_ID}.
8650     *
8651     * @see #setAccessibilityTraversalAfter(int)
8652     */
8653    public int getAccessibilityTraversalAfter() {
8654        return mAccessibilityTraversalAfterId;
8655    }
8656
8657    /**
8658     * Gets the id of a view for which this view serves as a label for
8659     * accessibility purposes.
8660     *
8661     * @return The labeled view id.
8662     */
8663    @ViewDebug.ExportedProperty(category = "accessibility")
8664    public int getLabelFor() {
8665        return mLabelForId;
8666    }
8667
8668    /**
8669     * Sets the id of a view for which this view serves as a label for
8670     * accessibility purposes.
8671     *
8672     * @param id The labeled view id.
8673     */
8674    @RemotableViewMethod
8675    public void setLabelFor(@IdRes int id) {
8676        if (mLabelForId == id) {
8677            return;
8678        }
8679        mLabelForId = id;
8680        if (mLabelForId != View.NO_ID
8681                && mID == View.NO_ID) {
8682            mID = generateViewId();
8683        }
8684        notifyViewAccessibilityStateChangedIfNeeded(
8685                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8686    }
8687
8688    /**
8689     * Invoked whenever this view loses focus, either by losing window focus or by losing
8690     * focus within its window. This method can be used to clear any state tied to the
8691     * focus. For instance, if a button is held pressed with the trackball and the window
8692     * loses focus, this method can be used to cancel the press.
8693     *
8694     * Subclasses of View overriding this method should always call super.onFocusLost().
8695     *
8696     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8697     * @see #onWindowFocusChanged(boolean)
8698     *
8699     * @hide pending API council approval
8700     */
8701    @CallSuper
8702    protected void onFocusLost() {
8703        resetPressedState();
8704    }
8705
8706    private void resetPressedState() {
8707        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8708            return;
8709        }
8710
8711        if (isPressed()) {
8712            setPressed(false);
8713
8714            if (!mHasPerformedLongPress) {
8715                removeLongPressCallback();
8716            }
8717        }
8718    }
8719
8720    /**
8721     * Returns true if this view has focus
8722     *
8723     * @return True if this view has focus, false otherwise.
8724     */
8725    @ViewDebug.ExportedProperty(category = "focus")
8726    public boolean isFocused() {
8727        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8728    }
8729
8730    /**
8731     * Find the view in the hierarchy rooted at this view that currently has
8732     * focus.
8733     *
8734     * @return The view that currently has focus, or null if no focused view can
8735     *         be found.
8736     */
8737    public View findFocus() {
8738        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8739    }
8740
8741    /**
8742     * Indicates whether this view is one of the set of scrollable containers in
8743     * its window.
8744     *
8745     * @return whether this view is one of the set of scrollable containers in
8746     * its window
8747     *
8748     * @attr ref android.R.styleable#View_isScrollContainer
8749     */
8750    public boolean isScrollContainer() {
8751        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8752    }
8753
8754    /**
8755     * Change whether this view is one of the set of scrollable containers in
8756     * its window.  This will be used to determine whether the window can
8757     * resize or must pan when a soft input area is open -- scrollable
8758     * containers allow the window to use resize mode since the container
8759     * will appropriately shrink.
8760     *
8761     * @attr ref android.R.styleable#View_isScrollContainer
8762     */
8763    public void setScrollContainer(boolean isScrollContainer) {
8764        if (isScrollContainer) {
8765            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8766                mAttachInfo.mScrollContainers.add(this);
8767                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8768            }
8769            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8770        } else {
8771            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8772                mAttachInfo.mScrollContainers.remove(this);
8773            }
8774            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8775        }
8776    }
8777
8778    /**
8779     * Returns the quality of the drawing cache.
8780     *
8781     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8782     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8783     *
8784     * @see #setDrawingCacheQuality(int)
8785     * @see #setDrawingCacheEnabled(boolean)
8786     * @see #isDrawingCacheEnabled()
8787     *
8788     * @attr ref android.R.styleable#View_drawingCacheQuality
8789     */
8790    @DrawingCacheQuality
8791    public int getDrawingCacheQuality() {
8792        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8793    }
8794
8795    /**
8796     * Set the drawing cache quality of this view. This value is used only when the
8797     * drawing cache is enabled
8798     *
8799     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8800     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8801     *
8802     * @see #getDrawingCacheQuality()
8803     * @see #setDrawingCacheEnabled(boolean)
8804     * @see #isDrawingCacheEnabled()
8805     *
8806     * @attr ref android.R.styleable#View_drawingCacheQuality
8807     */
8808    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8809        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8810    }
8811
8812    /**
8813     * Returns whether the screen should remain on, corresponding to the current
8814     * value of {@link #KEEP_SCREEN_ON}.
8815     *
8816     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8817     *
8818     * @see #setKeepScreenOn(boolean)
8819     *
8820     * @attr ref android.R.styleable#View_keepScreenOn
8821     */
8822    public boolean getKeepScreenOn() {
8823        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8824    }
8825
8826    /**
8827     * Controls whether the screen should remain on, modifying the
8828     * value of {@link #KEEP_SCREEN_ON}.
8829     *
8830     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8831     *
8832     * @see #getKeepScreenOn()
8833     *
8834     * @attr ref android.R.styleable#View_keepScreenOn
8835     */
8836    public void setKeepScreenOn(boolean keepScreenOn) {
8837        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8838    }
8839
8840    /**
8841     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8842     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8843     *
8844     * @attr ref android.R.styleable#View_nextFocusLeft
8845     */
8846    public int getNextFocusLeftId() {
8847        return mNextFocusLeftId;
8848    }
8849
8850    /**
8851     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8852     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8853     * decide automatically.
8854     *
8855     * @attr ref android.R.styleable#View_nextFocusLeft
8856     */
8857    public void setNextFocusLeftId(int nextFocusLeftId) {
8858        mNextFocusLeftId = nextFocusLeftId;
8859    }
8860
8861    /**
8862     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8863     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8864     *
8865     * @attr ref android.R.styleable#View_nextFocusRight
8866     */
8867    public int getNextFocusRightId() {
8868        return mNextFocusRightId;
8869    }
8870
8871    /**
8872     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8873     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8874     * decide automatically.
8875     *
8876     * @attr ref android.R.styleable#View_nextFocusRight
8877     */
8878    public void setNextFocusRightId(int nextFocusRightId) {
8879        mNextFocusRightId = nextFocusRightId;
8880    }
8881
8882    /**
8883     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8884     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8885     *
8886     * @attr ref android.R.styleable#View_nextFocusUp
8887     */
8888    public int getNextFocusUpId() {
8889        return mNextFocusUpId;
8890    }
8891
8892    /**
8893     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8894     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8895     * decide automatically.
8896     *
8897     * @attr ref android.R.styleable#View_nextFocusUp
8898     */
8899    public void setNextFocusUpId(int nextFocusUpId) {
8900        mNextFocusUpId = nextFocusUpId;
8901    }
8902
8903    /**
8904     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8905     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8906     *
8907     * @attr ref android.R.styleable#View_nextFocusDown
8908     */
8909    public int getNextFocusDownId() {
8910        return mNextFocusDownId;
8911    }
8912
8913    /**
8914     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8915     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8916     * decide automatically.
8917     *
8918     * @attr ref android.R.styleable#View_nextFocusDown
8919     */
8920    public void setNextFocusDownId(int nextFocusDownId) {
8921        mNextFocusDownId = nextFocusDownId;
8922    }
8923
8924    /**
8925     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8926     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8927     *
8928     * @attr ref android.R.styleable#View_nextFocusForward
8929     */
8930    public int getNextFocusForwardId() {
8931        return mNextFocusForwardId;
8932    }
8933
8934    /**
8935     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8936     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8937     * decide automatically.
8938     *
8939     * @attr ref android.R.styleable#View_nextFocusForward
8940     */
8941    public void setNextFocusForwardId(int nextFocusForwardId) {
8942        mNextFocusForwardId = nextFocusForwardId;
8943    }
8944
8945    /**
8946     * Gets the id of the root of the next keyboard navigation cluster.
8947     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8948     * decide automatically.
8949     *
8950     * @attr ref android.R.styleable#View_nextClusterForward
8951     */
8952    public int getNextClusterForwardId() {
8953        return mNextClusterForwardId;
8954    }
8955
8956    /**
8957     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8958     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8959     * decide automatically.
8960     *
8961     * @attr ref android.R.styleable#View_nextClusterForward
8962     */
8963    public void setNextClusterForwardId(int nextClusterForwardId) {
8964        mNextClusterForwardId = nextClusterForwardId;
8965    }
8966
8967    /**
8968     * Returns the visibility of this view and all of its ancestors
8969     *
8970     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8971     */
8972    public boolean isShown() {
8973        View current = this;
8974        //noinspection ConstantConditions
8975        do {
8976            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8977                return false;
8978            }
8979            ViewParent parent = current.mParent;
8980            if (parent == null) {
8981                return false; // We are not attached to the view root
8982            }
8983            if (!(parent instanceof View)) {
8984                return true;
8985            }
8986            current = (View) parent;
8987        } while (current != null);
8988
8989        return false;
8990    }
8991
8992    /**
8993     * Called by the view hierarchy when the content insets for a window have
8994     * changed, to allow it to adjust its content to fit within those windows.
8995     * The content insets tell you the space that the status bar, input method,
8996     * and other system windows infringe on the application's window.
8997     *
8998     * <p>You do not normally need to deal with this function, since the default
8999     * window decoration given to applications takes care of applying it to the
9000     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
9001     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
9002     * and your content can be placed under those system elements.  You can then
9003     * use this method within your view hierarchy if you have parts of your UI
9004     * which you would like to ensure are not being covered.
9005     *
9006     * <p>The default implementation of this method simply applies the content
9007     * insets to the view's padding, consuming that content (modifying the
9008     * insets to be 0), and returning true.  This behavior is off by default, but can
9009     * be enabled through {@link #setFitsSystemWindows(boolean)}.
9010     *
9011     * <p>This function's traversal down the hierarchy is depth-first.  The same content
9012     * insets object is propagated down the hierarchy, so any changes made to it will
9013     * be seen by all following views (including potentially ones above in
9014     * the hierarchy since this is a depth-first traversal).  The first view
9015     * that returns true will abort the entire traversal.
9016     *
9017     * <p>The default implementation works well for a situation where it is
9018     * used with a container that covers the entire window, allowing it to
9019     * apply the appropriate insets to its content on all edges.  If you need
9020     * a more complicated layout (such as two different views fitting system
9021     * windows, one on the top of the window, and one on the bottom),
9022     * you can override the method and handle the insets however you would like.
9023     * Note that the insets provided by the framework are always relative to the
9024     * far edges of the window, not accounting for the location of the called view
9025     * within that window.  (In fact when this method is called you do not yet know
9026     * where the layout will place the view, as it is done before layout happens.)
9027     *
9028     * <p>Note: unlike many View methods, there is no dispatch phase to this
9029     * call.  If you are overriding it in a ViewGroup and want to allow the
9030     * call to continue to your children, you must be sure to call the super
9031     * implementation.
9032     *
9033     * <p>Here is a sample layout that makes use of fitting system windows
9034     * to have controls for a video view placed inside of the window decorations
9035     * that it hides and shows.  This can be used with code like the second
9036     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
9037     *
9038     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
9039     *
9040     * @param insets Current content insets of the window.  Prior to
9041     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
9042     * the insets or else you and Android will be unhappy.
9043     *
9044     * @return {@code true} if this view applied the insets and it should not
9045     * continue propagating further down the hierarchy, {@code false} otherwise.
9046     * @see #getFitsSystemWindows()
9047     * @see #setFitsSystemWindows(boolean)
9048     * @see #setSystemUiVisibility(int)
9049     *
9050     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
9051     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
9052     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
9053     * to implement handling their own insets.
9054     */
9055    @Deprecated
9056    protected boolean fitSystemWindows(Rect insets) {
9057        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
9058            if (insets == null) {
9059                // Null insets by definition have already been consumed.
9060                // This call cannot apply insets since there are none to apply,
9061                // so return false.
9062                return false;
9063            }
9064            // If we're not in the process of dispatching the newer apply insets call,
9065            // that means we're not in the compatibility path. Dispatch into the newer
9066            // apply insets path and take things from there.
9067            try {
9068                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
9069                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
9070            } finally {
9071                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
9072            }
9073        } else {
9074            // We're being called from the newer apply insets path.
9075            // Perform the standard fallback behavior.
9076            return fitSystemWindowsInt(insets);
9077        }
9078    }
9079
9080    private boolean fitSystemWindowsInt(Rect insets) {
9081        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
9082            mUserPaddingStart = UNDEFINED_PADDING;
9083            mUserPaddingEnd = UNDEFINED_PADDING;
9084            Rect localInsets = sThreadLocal.get();
9085            if (localInsets == null) {
9086                localInsets = new Rect();
9087                sThreadLocal.set(localInsets);
9088            }
9089            boolean res = computeFitSystemWindows(insets, localInsets);
9090            mUserPaddingLeftInitial = localInsets.left;
9091            mUserPaddingRightInitial = localInsets.right;
9092            internalSetPadding(localInsets.left, localInsets.top,
9093                    localInsets.right, localInsets.bottom);
9094            return res;
9095        }
9096        return false;
9097    }
9098
9099    /**
9100     * Called when the view should apply {@link WindowInsets} according to its internal policy.
9101     *
9102     * <p>This method should be overridden by views that wish to apply a policy different from or
9103     * in addition to the default behavior. Clients that wish to force a view subtree
9104     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
9105     *
9106     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
9107     * it will be called during dispatch instead of this method. The listener may optionally
9108     * call this method from its own implementation if it wishes to apply the view's default
9109     * insets policy in addition to its own.</p>
9110     *
9111     * <p>Implementations of this method should either return the insets parameter unchanged
9112     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
9113     * that this view applied itself. This allows new inset types added in future platform
9114     * versions to pass through existing implementations unchanged without being erroneously
9115     * consumed.</p>
9116     *
9117     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
9118     * property is set then the view will consume the system window insets and apply them
9119     * as padding for the view.</p>
9120     *
9121     * @param insets Insets to apply
9122     * @return The supplied insets with any applied insets consumed
9123     */
9124    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
9125        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
9126            // We weren't called from within a direct call to fitSystemWindows,
9127            // call into it as a fallback in case we're in a class that overrides it
9128            // and has logic to perform.
9129            if (fitSystemWindows(insets.getSystemWindowInsets())) {
9130                return insets.consumeSystemWindowInsets();
9131            }
9132        } else {
9133            // We were called from within a direct call to fitSystemWindows.
9134            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
9135                return insets.consumeSystemWindowInsets();
9136            }
9137        }
9138        return insets;
9139    }
9140
9141    /**
9142     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
9143     * window insets to this view. The listener's
9144     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
9145     * method will be called instead of the view's
9146     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
9147     *
9148     * @param listener Listener to set
9149     *
9150     * @see #onApplyWindowInsets(WindowInsets)
9151     */
9152    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
9153        getListenerInfo().mOnApplyWindowInsetsListener = listener;
9154    }
9155
9156    /**
9157     * Request to apply the given window insets to this view or another view in its subtree.
9158     *
9159     * <p>This method should be called by clients wishing to apply insets corresponding to areas
9160     * obscured by window decorations or overlays. This can include the status and navigation bars,
9161     * action bars, input methods and more. New inset categories may be added in the future.
9162     * The method returns the insets provided minus any that were applied by this view or its
9163     * children.</p>
9164     *
9165     * <p>Clients wishing to provide custom behavior should override the
9166     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
9167     * {@link OnApplyWindowInsetsListener} via the
9168     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
9169     * method.</p>
9170     *
9171     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
9172     * </p>
9173     *
9174     * @param insets Insets to apply
9175     * @return The provided insets minus the insets that were consumed
9176     */
9177    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
9178        try {
9179            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
9180            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
9181                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
9182            } else {
9183                return onApplyWindowInsets(insets);
9184            }
9185        } finally {
9186            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9187        }
9188    }
9189
9190    /**
9191     * Compute the view's coordinate within the surface.
9192     *
9193     * <p>Computes the coordinates of this view in its surface. The argument
9194     * must be an array of two integers. After the method returns, the array
9195     * contains the x and y location in that order.</p>
9196     * @hide
9197     * @param location an array of two integers in which to hold the coordinates
9198     */
9199    public void getLocationInSurface(@Size(2) int[] location) {
9200        getLocationInWindow(location);
9201        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9202            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9203            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9204        }
9205    }
9206
9207    /**
9208     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9209     * only available if the view is attached.
9210     *
9211     * @return WindowInsets from the top of the view hierarchy or null if View is detached
9212     */
9213    public WindowInsets getRootWindowInsets() {
9214        if (mAttachInfo != null) {
9215            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9216        }
9217        return null;
9218    }
9219
9220    /**
9221     * @hide Compute the insets that should be consumed by this view and the ones
9222     * that should propagate to those under it.
9223     */
9224    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9225        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9226                || mAttachInfo == null
9227                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9228                        && !mAttachInfo.mOverscanRequested)) {
9229            outLocalInsets.set(inoutInsets);
9230            inoutInsets.set(0, 0, 0, 0);
9231            return true;
9232        } else {
9233            // The application wants to take care of fitting system window for
9234            // the content...  however we still need to take care of any overscan here.
9235            final Rect overscan = mAttachInfo.mOverscanInsets;
9236            outLocalInsets.set(overscan);
9237            inoutInsets.left -= overscan.left;
9238            inoutInsets.top -= overscan.top;
9239            inoutInsets.right -= overscan.right;
9240            inoutInsets.bottom -= overscan.bottom;
9241            return false;
9242        }
9243    }
9244
9245    /**
9246     * Compute insets that should be consumed by this view and the ones that should propagate
9247     * to those under it.
9248     *
9249     * @param in Insets currently being processed by this View, likely received as a parameter
9250     *           to {@link #onApplyWindowInsets(WindowInsets)}.
9251     * @param outLocalInsets A Rect that will receive the insets that should be consumed
9252     *                       by this view
9253     * @return Insets that should be passed along to views under this one
9254     */
9255    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9256        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9257                || mAttachInfo == null
9258                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
9259            outLocalInsets.set(in.getSystemWindowInsets());
9260            return in.consumeSystemWindowInsets();
9261        } else {
9262            outLocalInsets.set(0, 0, 0, 0);
9263            return in;
9264        }
9265    }
9266
9267    /**
9268     * Sets whether or not this view should account for system screen decorations
9269     * such as the status bar and inset its content; that is, controlling whether
9270     * the default implementation of {@link #fitSystemWindows(Rect)} will be
9271     * executed.  See that method for more details.
9272     *
9273     * <p>Note that if you are providing your own implementation of
9274     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9275     * flag to true -- your implementation will be overriding the default
9276     * implementation that checks this flag.
9277     *
9278     * @param fitSystemWindows If true, then the default implementation of
9279     * {@link #fitSystemWindows(Rect)} will be executed.
9280     *
9281     * @attr ref android.R.styleable#View_fitsSystemWindows
9282     * @see #getFitsSystemWindows()
9283     * @see #fitSystemWindows(Rect)
9284     * @see #setSystemUiVisibility(int)
9285     */
9286    public void setFitsSystemWindows(boolean fitSystemWindows) {
9287        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9288    }
9289
9290    /**
9291     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9292     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9293     * will be executed.
9294     *
9295     * @return {@code true} if the default implementation of
9296     * {@link #fitSystemWindows(Rect)} will be executed.
9297     *
9298     * @attr ref android.R.styleable#View_fitsSystemWindows
9299     * @see #setFitsSystemWindows(boolean)
9300     * @see #fitSystemWindows(Rect)
9301     * @see #setSystemUiVisibility(int)
9302     */
9303    @ViewDebug.ExportedProperty
9304    public boolean getFitsSystemWindows() {
9305        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9306    }
9307
9308    /** @hide */
9309    public boolean fitsSystemWindows() {
9310        return getFitsSystemWindows();
9311    }
9312
9313    /**
9314     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9315     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9316     */
9317    @Deprecated
9318    public void requestFitSystemWindows() {
9319        if (mParent != null) {
9320            mParent.requestFitSystemWindows();
9321        }
9322    }
9323
9324    /**
9325     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9326     */
9327    public void requestApplyInsets() {
9328        requestFitSystemWindows();
9329    }
9330
9331    /**
9332     * For use by PhoneWindow to make its own system window fitting optional.
9333     * @hide
9334     */
9335    public void makeOptionalFitsSystemWindows() {
9336        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9337    }
9338
9339    /**
9340     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9341     * treat them as such.
9342     * @hide
9343     */
9344    public void getOutsets(Rect outOutsetRect) {
9345        if (mAttachInfo != null) {
9346            outOutsetRect.set(mAttachInfo.mOutsets);
9347        } else {
9348            outOutsetRect.setEmpty();
9349        }
9350    }
9351
9352    /**
9353     * Returns the visibility status for this view.
9354     *
9355     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9356     * @attr ref android.R.styleable#View_visibility
9357     */
9358    @ViewDebug.ExportedProperty(mapping = {
9359        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9360        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9361        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9362    })
9363    @Visibility
9364    public int getVisibility() {
9365        return mViewFlags & VISIBILITY_MASK;
9366    }
9367
9368    /**
9369     * Set the visibility state of this view.
9370     *
9371     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9372     * @attr ref android.R.styleable#View_visibility
9373     */
9374    @RemotableViewMethod
9375    public void setVisibility(@Visibility int visibility) {
9376        setFlags(visibility, VISIBILITY_MASK);
9377    }
9378
9379    /**
9380     * Returns the enabled status for this view. The interpretation of the
9381     * enabled state varies by subclass.
9382     *
9383     * @return True if this view is enabled, false otherwise.
9384     */
9385    @ViewDebug.ExportedProperty
9386    public boolean isEnabled() {
9387        return (mViewFlags & ENABLED_MASK) == ENABLED;
9388    }
9389
9390    /**
9391     * Set the enabled state of this view. The interpretation of the enabled
9392     * state varies by subclass.
9393     *
9394     * @param enabled True if this view is enabled, false otherwise.
9395     */
9396    @RemotableViewMethod
9397    public void setEnabled(boolean enabled) {
9398        if (enabled == isEnabled()) return;
9399
9400        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9401
9402        /*
9403         * The View most likely has to change its appearance, so refresh
9404         * the drawable state.
9405         */
9406        refreshDrawableState();
9407
9408        // Invalidate too, since the default behavior for views is to be
9409        // be drawn at 50% alpha rather than to change the drawable.
9410        invalidate(true);
9411
9412        if (!enabled) {
9413            cancelPendingInputEvents();
9414        }
9415    }
9416
9417    /**
9418     * Set whether this view can receive the focus.
9419     * <p>
9420     * Setting this to false will also ensure that this view is not focusable
9421     * in touch mode.
9422     *
9423     * @param focusable If true, this view can receive the focus.
9424     *
9425     * @see #setFocusableInTouchMode(boolean)
9426     * @see #setFocusable(int)
9427     * @attr ref android.R.styleable#View_focusable
9428     */
9429    public void setFocusable(boolean focusable) {
9430        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9431    }
9432
9433    /**
9434     * Sets whether this view can receive focus.
9435     * <p>
9436     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9437     * automatically based on the view's interactivity. This is the default.
9438     * <p>
9439     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9440     * in touch mode.
9441     *
9442     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9443     *                  or {@link #FOCUSABLE_AUTO}.
9444     * @see #setFocusableInTouchMode(boolean)
9445     * @attr ref android.R.styleable#View_focusable
9446     */
9447    public void setFocusable(@Focusable int focusable) {
9448        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9449            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9450        }
9451        setFlags(focusable, FOCUSABLE_MASK);
9452    }
9453
9454    /**
9455     * Set whether this view can receive focus while in touch mode.
9456     *
9457     * Setting this to true will also ensure that this view is focusable.
9458     *
9459     * @param focusableInTouchMode If true, this view can receive the focus while
9460     *   in touch mode.
9461     *
9462     * @see #setFocusable(boolean)
9463     * @attr ref android.R.styleable#View_focusableInTouchMode
9464     */
9465    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9466        // Focusable in touch mode should always be set before the focusable flag
9467        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9468        // which, in touch mode, will not successfully request focus on this view
9469        // because the focusable in touch mode flag is not set
9470        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9471
9472        // Clear FOCUSABLE_AUTO if set.
9473        if (focusableInTouchMode) {
9474            // Clears FOCUSABLE_AUTO if set.
9475            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9476        }
9477    }
9478
9479    /**
9480     * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
9481     * to autofill the view with the user's data.
9482     *
9483     * <p>Typically, there is only one way to autofill a view, but there could be more than one.
9484     * For example, if the application accepts either an username or email address to identify
9485     * an user.
9486     *
9487     * <p>These hints are not validated by the Android System, but passed "as is" to the service.
9488     * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
9489     * constants such as:
9490     * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
9491     * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
9492     * {@link #AUTOFILL_HINT_NAME},
9493     * {@link #AUTOFILL_HINT_PHONE},
9494     * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
9495     * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
9496     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
9497     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
9498     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
9499     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
9500     *
9501     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9502     * @attr ref android.R.styleable#View_autofillHints
9503     */
9504    public void setAutofillHints(@Nullable String... autofillHints) {
9505        if (autofillHints == null || autofillHints.length == 0) {
9506            mAutofillHints = null;
9507        } else {
9508            mAutofillHints = autofillHints;
9509        }
9510    }
9511
9512    /**
9513     * @hide
9514     */
9515    @TestApi
9516    public void setAutofilled(boolean isAutofilled) {
9517        boolean wasChanged = isAutofilled != isAutofilled();
9518
9519        if (wasChanged) {
9520            if (isAutofilled) {
9521                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9522            } else {
9523                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9524            }
9525
9526            invalidate();
9527        }
9528    }
9529
9530    /**
9531     * Set whether this view should have sound effects enabled for events such as
9532     * clicking and touching.
9533     *
9534     * <p>You may wish to disable sound effects for a view if you already play sounds,
9535     * for instance, a dial key that plays dtmf tones.
9536     *
9537     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9538     * @see #isSoundEffectsEnabled()
9539     * @see #playSoundEffect(int)
9540     * @attr ref android.R.styleable#View_soundEffectsEnabled
9541     */
9542    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9543        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9544    }
9545
9546    /**
9547     * @return whether this view should have sound effects enabled for events such as
9548     *     clicking and touching.
9549     *
9550     * @see #setSoundEffectsEnabled(boolean)
9551     * @see #playSoundEffect(int)
9552     * @attr ref android.R.styleable#View_soundEffectsEnabled
9553     */
9554    @ViewDebug.ExportedProperty
9555    public boolean isSoundEffectsEnabled() {
9556        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9557    }
9558
9559    /**
9560     * Set whether this view should have haptic feedback for events such as
9561     * long presses.
9562     *
9563     * <p>You may wish to disable haptic feedback if your view already controls
9564     * its own haptic feedback.
9565     *
9566     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9567     * @see #isHapticFeedbackEnabled()
9568     * @see #performHapticFeedback(int)
9569     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9570     */
9571    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9572        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9573    }
9574
9575    /**
9576     * @return whether this view should have haptic feedback enabled for events
9577     * long presses.
9578     *
9579     * @see #setHapticFeedbackEnabled(boolean)
9580     * @see #performHapticFeedback(int)
9581     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9582     */
9583    @ViewDebug.ExportedProperty
9584    public boolean isHapticFeedbackEnabled() {
9585        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9586    }
9587
9588    /**
9589     * Returns the layout direction for this view.
9590     *
9591     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9592     *   {@link #LAYOUT_DIRECTION_RTL},
9593     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9594     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9595     *
9596     * @attr ref android.R.styleable#View_layoutDirection
9597     *
9598     * @hide
9599     */
9600    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9601        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9602        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9603        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9604        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9605    })
9606    @LayoutDir
9607    public int getRawLayoutDirection() {
9608        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9609    }
9610
9611    /**
9612     * Set the layout direction for this view. This will propagate a reset of layout direction
9613     * resolution to the view's children and resolve layout direction for this view.
9614     *
9615     * @param layoutDirection the layout direction to set. Should be one of:
9616     *
9617     * {@link #LAYOUT_DIRECTION_LTR},
9618     * {@link #LAYOUT_DIRECTION_RTL},
9619     * {@link #LAYOUT_DIRECTION_INHERIT},
9620     * {@link #LAYOUT_DIRECTION_LOCALE}.
9621     *
9622     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9623     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9624     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9625     *
9626     * @attr ref android.R.styleable#View_layoutDirection
9627     */
9628    @RemotableViewMethod
9629    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9630        if (getRawLayoutDirection() != layoutDirection) {
9631            // Reset the current layout direction and the resolved one
9632            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9633            resetRtlProperties();
9634            // Set the new layout direction (filtered)
9635            mPrivateFlags2 |=
9636                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9637            // We need to resolve all RTL properties as they all depend on layout direction
9638            resolveRtlPropertiesIfNeeded();
9639            requestLayout();
9640            invalidate(true);
9641        }
9642    }
9643
9644    /**
9645     * Returns the resolved layout direction for this view.
9646     *
9647     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9648     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9649     *
9650     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9651     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9652     *
9653     * @attr ref android.R.styleable#View_layoutDirection
9654     */
9655    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9656        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9657        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9658    })
9659    @ResolvedLayoutDir
9660    public int getLayoutDirection() {
9661        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9662        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9663            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9664            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9665        }
9666        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9667                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9668    }
9669
9670    /**
9671     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9672     * layout attribute and/or the inherited value from the parent
9673     *
9674     * @return true if the layout is right-to-left.
9675     *
9676     * @hide
9677     */
9678    @ViewDebug.ExportedProperty(category = "layout")
9679    public boolean isLayoutRtl() {
9680        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9681    }
9682
9683    /**
9684     * Indicates whether the view is currently tracking transient state that the
9685     * app should not need to concern itself with saving and restoring, but that
9686     * the framework should take special note to preserve when possible.
9687     *
9688     * <p>A view with transient state cannot be trivially rebound from an external
9689     * data source, such as an adapter binding item views in a list. This may be
9690     * because the view is performing an animation, tracking user selection
9691     * of content, or similar.</p>
9692     *
9693     * @return true if the view has transient state
9694     */
9695    @ViewDebug.ExportedProperty(category = "layout")
9696    public boolean hasTransientState() {
9697        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9698    }
9699
9700    /**
9701     * Set whether this view is currently tracking transient state that the
9702     * framework should attempt to preserve when possible. This flag is reference counted,
9703     * so every call to setHasTransientState(true) should be paired with a later call
9704     * to setHasTransientState(false).
9705     *
9706     * <p>A view with transient state cannot be trivially rebound from an external
9707     * data source, such as an adapter binding item views in a list. This may be
9708     * because the view is performing an animation, tracking user selection
9709     * of content, or similar.</p>
9710     *
9711     * @param hasTransientState true if this view has transient state
9712     */
9713    public void setHasTransientState(boolean hasTransientState) {
9714        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9715                mTransientStateCount - 1;
9716        if (mTransientStateCount < 0) {
9717            mTransientStateCount = 0;
9718            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9719                    "unmatched pair of setHasTransientState calls");
9720        } else if ((hasTransientState && mTransientStateCount == 1) ||
9721                (!hasTransientState && mTransientStateCount == 0)) {
9722            // update flag if we've just incremented up from 0 or decremented down to 0
9723            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9724                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9725            if (mParent != null) {
9726                try {
9727                    mParent.childHasTransientStateChanged(this, hasTransientState);
9728                } catch (AbstractMethodError e) {
9729                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9730                            " does not fully implement ViewParent", e);
9731                }
9732            }
9733        }
9734    }
9735
9736    /**
9737     * Returns true if this view is currently attached to a window.
9738     */
9739    public boolean isAttachedToWindow() {
9740        return mAttachInfo != null;
9741    }
9742
9743    /**
9744     * Returns true if this view has been through at least one layout since it
9745     * was last attached to or detached from a window.
9746     */
9747    public boolean isLaidOut() {
9748        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9749    }
9750
9751    /**
9752     * If this view doesn't do any drawing on its own, set this flag to
9753     * allow further optimizations. By default, this flag is not set on
9754     * View, but could be set on some View subclasses such as ViewGroup.
9755     *
9756     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9757     * you should clear this flag.
9758     *
9759     * @param willNotDraw whether or not this View draw on its own
9760     */
9761    public void setWillNotDraw(boolean willNotDraw) {
9762        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9763    }
9764
9765    /**
9766     * Returns whether or not this View draws on its own.
9767     *
9768     * @return true if this view has nothing to draw, false otherwise
9769     */
9770    @ViewDebug.ExportedProperty(category = "drawing")
9771    public boolean willNotDraw() {
9772        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9773    }
9774
9775    /**
9776     * When a View's drawing cache is enabled, drawing is redirected to an
9777     * offscreen bitmap. Some views, like an ImageView, must be able to
9778     * bypass this mechanism if they already draw a single bitmap, to avoid
9779     * unnecessary usage of the memory.
9780     *
9781     * @param willNotCacheDrawing true if this view does not cache its
9782     *        drawing, false otherwise
9783     */
9784    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9785        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9786    }
9787
9788    /**
9789     * Returns whether or not this View can cache its drawing or not.
9790     *
9791     * @return true if this view does not cache its drawing, false otherwise
9792     */
9793    @ViewDebug.ExportedProperty(category = "drawing")
9794    public boolean willNotCacheDrawing() {
9795        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9796    }
9797
9798    /**
9799     * Indicates whether this view reacts to click events or not.
9800     *
9801     * @return true if the view is clickable, false otherwise
9802     *
9803     * @see #setClickable(boolean)
9804     * @attr ref android.R.styleable#View_clickable
9805     */
9806    @ViewDebug.ExportedProperty
9807    public boolean isClickable() {
9808        return (mViewFlags & CLICKABLE) == CLICKABLE;
9809    }
9810
9811    /**
9812     * Enables or disables click events for this view. When a view
9813     * is clickable it will change its state to "pressed" on every click.
9814     * Subclasses should set the view clickable to visually react to
9815     * user's clicks.
9816     *
9817     * @param clickable true to make the view clickable, false otherwise
9818     *
9819     * @see #isClickable()
9820     * @attr ref android.R.styleable#View_clickable
9821     */
9822    public void setClickable(boolean clickable) {
9823        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9824    }
9825
9826    /**
9827     * Indicates whether this view reacts to long click events or not.
9828     *
9829     * @return true if the view is long clickable, false otherwise
9830     *
9831     * @see #setLongClickable(boolean)
9832     * @attr ref android.R.styleable#View_longClickable
9833     */
9834    public boolean isLongClickable() {
9835        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9836    }
9837
9838    /**
9839     * Enables or disables long click events for this view. When a view is long
9840     * clickable it reacts to the user holding down the button for a longer
9841     * duration than a tap. This event can either launch the listener or a
9842     * context menu.
9843     *
9844     * @param longClickable true to make the view long clickable, false otherwise
9845     * @see #isLongClickable()
9846     * @attr ref android.R.styleable#View_longClickable
9847     */
9848    public void setLongClickable(boolean longClickable) {
9849        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9850    }
9851
9852    /**
9853     * Indicates whether this view reacts to context clicks or not.
9854     *
9855     * @return true if the view is context clickable, false otherwise
9856     * @see #setContextClickable(boolean)
9857     * @attr ref android.R.styleable#View_contextClickable
9858     */
9859    public boolean isContextClickable() {
9860        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9861    }
9862
9863    /**
9864     * Enables or disables context clicking for this view. This event can launch the listener.
9865     *
9866     * @param contextClickable true to make the view react to a context click, false otherwise
9867     * @see #isContextClickable()
9868     * @attr ref android.R.styleable#View_contextClickable
9869     */
9870    public void setContextClickable(boolean contextClickable) {
9871        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9872    }
9873
9874    /**
9875     * Sets the pressed state for this view and provides a touch coordinate for
9876     * animation hinting.
9877     *
9878     * @param pressed Pass true to set the View's internal state to "pressed",
9879     *            or false to reverts the View's internal state from a
9880     *            previously set "pressed" state.
9881     * @param x The x coordinate of the touch that caused the press
9882     * @param y The y coordinate of the touch that caused the press
9883     */
9884    private void setPressed(boolean pressed, float x, float y) {
9885        if (pressed) {
9886            drawableHotspotChanged(x, y);
9887        }
9888
9889        setPressed(pressed);
9890    }
9891
9892    /**
9893     * Sets the pressed state for this view.
9894     *
9895     * @see #isClickable()
9896     * @see #setClickable(boolean)
9897     *
9898     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9899     *        the View's internal state from a previously set "pressed" state.
9900     */
9901    public void setPressed(boolean pressed) {
9902        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9903
9904        if (pressed) {
9905            mPrivateFlags |= PFLAG_PRESSED;
9906        } else {
9907            mPrivateFlags &= ~PFLAG_PRESSED;
9908        }
9909
9910        if (needsRefresh) {
9911            refreshDrawableState();
9912        }
9913        dispatchSetPressed(pressed);
9914    }
9915
9916    /**
9917     * Dispatch setPressed to all of this View's children.
9918     *
9919     * @see #setPressed(boolean)
9920     *
9921     * @param pressed The new pressed state
9922     */
9923    protected void dispatchSetPressed(boolean pressed) {
9924    }
9925
9926    /**
9927     * Indicates whether the view is currently in pressed state. Unless
9928     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9929     * the pressed state.
9930     *
9931     * @see #setPressed(boolean)
9932     * @see #isClickable()
9933     * @see #setClickable(boolean)
9934     *
9935     * @return true if the view is currently pressed, false otherwise
9936     */
9937    @ViewDebug.ExportedProperty
9938    public boolean isPressed() {
9939        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9940    }
9941
9942    /**
9943     * @hide
9944     * Indicates whether this view will participate in data collection through
9945     * {@link ViewStructure}.  If true, it will not provide any data
9946     * for itself or its children.  If false, the normal data collection will be allowed.
9947     *
9948     * @return Returns false if assist data collection is not blocked, else true.
9949     *
9950     * @see #setAssistBlocked(boolean)
9951     * @attr ref android.R.styleable#View_assistBlocked
9952     */
9953    public boolean isAssistBlocked() {
9954        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9955    }
9956
9957    /**
9958     * @hide
9959     * Controls whether assist data collection from this view and its children is enabled
9960     * (that is, whether {@link #onProvideStructure} and
9961     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9962     * allowing normal assist collection.  Setting this to false will disable assist collection.
9963     *
9964     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9965     * (the default) to allow it.
9966     *
9967     * @see #isAssistBlocked()
9968     * @see #onProvideStructure
9969     * @see #onProvideVirtualStructure
9970     * @attr ref android.R.styleable#View_assistBlocked
9971     */
9972    public void setAssistBlocked(boolean enabled) {
9973        if (enabled) {
9974            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9975        } else {
9976            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9977        }
9978    }
9979
9980    /**
9981     * Indicates whether this view will save its state (that is,
9982     * whether its {@link #onSaveInstanceState} method will be called).
9983     *
9984     * @return Returns true if the view state saving is enabled, else false.
9985     *
9986     * @see #setSaveEnabled(boolean)
9987     * @attr ref android.R.styleable#View_saveEnabled
9988     */
9989    public boolean isSaveEnabled() {
9990        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9991    }
9992
9993    /**
9994     * Controls whether the saving of this view's state is
9995     * enabled (that is, whether its {@link #onSaveInstanceState} method
9996     * will be called).  Note that even if freezing is enabled, the
9997     * view still must have an id assigned to it (via {@link #setId(int)})
9998     * for its state to be saved.  This flag can only disable the
9999     * saving of this view; any child views may still have their state saved.
10000     *
10001     * @param enabled Set to false to <em>disable</em> state saving, or true
10002     * (the default) to allow it.
10003     *
10004     * @see #isSaveEnabled()
10005     * @see #setId(int)
10006     * @see #onSaveInstanceState()
10007     * @attr ref android.R.styleable#View_saveEnabled
10008     */
10009    public void setSaveEnabled(boolean enabled) {
10010        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
10011    }
10012
10013    /**
10014     * Gets whether the framework should discard touches when the view's
10015     * window is obscured by another visible window.
10016     * Refer to the {@link View} security documentation for more details.
10017     *
10018     * @return True if touch filtering is enabled.
10019     *
10020     * @see #setFilterTouchesWhenObscured(boolean)
10021     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10022     */
10023    @ViewDebug.ExportedProperty
10024    public boolean getFilterTouchesWhenObscured() {
10025        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
10026    }
10027
10028    /**
10029     * Sets whether the framework should discard touches when the view's
10030     * window is obscured by another visible window.
10031     * Refer to the {@link View} security documentation for more details.
10032     *
10033     * @param enabled True if touch filtering should be enabled.
10034     *
10035     * @see #getFilterTouchesWhenObscured
10036     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10037     */
10038    public void setFilterTouchesWhenObscured(boolean enabled) {
10039        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
10040                FILTER_TOUCHES_WHEN_OBSCURED);
10041    }
10042
10043    /**
10044     * Indicates whether the entire hierarchy under this view will save its
10045     * state when a state saving traversal occurs from its parent.  The default
10046     * is true; if false, these views will not be saved unless
10047     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10048     *
10049     * @return Returns true if the view state saving from parent is enabled, else false.
10050     *
10051     * @see #setSaveFromParentEnabled(boolean)
10052     */
10053    public boolean isSaveFromParentEnabled() {
10054        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
10055    }
10056
10057    /**
10058     * Controls whether the entire hierarchy under this view will save its
10059     * state when a state saving traversal occurs from its parent.  The default
10060     * is true; if false, these views will not be saved unless
10061     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10062     *
10063     * @param enabled Set to false to <em>disable</em> state saving, or true
10064     * (the default) to allow it.
10065     *
10066     * @see #isSaveFromParentEnabled()
10067     * @see #setId(int)
10068     * @see #onSaveInstanceState()
10069     */
10070    public void setSaveFromParentEnabled(boolean enabled) {
10071        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
10072    }
10073
10074
10075    /**
10076     * Returns whether this View is currently able to take focus.
10077     *
10078     * @return True if this view can take focus, or false otherwise.
10079     */
10080    @ViewDebug.ExportedProperty(category = "focus")
10081    public final boolean isFocusable() {
10082        return FOCUSABLE == (mViewFlags & FOCUSABLE);
10083    }
10084
10085    /**
10086     * Returns the focusable setting for this view.
10087     *
10088     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
10089     * @attr ref android.R.styleable#View_focusable
10090     */
10091    @ViewDebug.ExportedProperty(mapping = {
10092            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
10093            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
10094            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
10095            }, category = "focus")
10096    @Focusable
10097    public int getFocusable() {
10098        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
10099    }
10100
10101    /**
10102     * When a view is focusable, it may not want to take focus when in touch mode.
10103     * For example, a button would like focus when the user is navigating via a D-pad
10104     * so that the user can click on it, but once the user starts touching the screen,
10105     * the button shouldn't take focus
10106     * @return Whether the view is focusable in touch mode.
10107     * @attr ref android.R.styleable#View_focusableInTouchMode
10108     */
10109    @ViewDebug.ExportedProperty(category = "focus")
10110    public final boolean isFocusableInTouchMode() {
10111        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
10112    }
10113
10114    /**
10115     * Find the nearest view in the specified direction that can take focus.
10116     * This does not actually give focus to that view.
10117     *
10118     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10119     *
10120     * @return The nearest focusable in the specified direction, or null if none
10121     *         can be found.
10122     */
10123    public View focusSearch(@FocusRealDirection int direction) {
10124        if (mParent != null) {
10125            return mParent.focusSearch(this, direction);
10126        } else {
10127            return null;
10128        }
10129    }
10130
10131    /**
10132     * Returns whether this View is a root of a keyboard navigation cluster.
10133     *
10134     * @return True if this view is a root of a cluster, or false otherwise.
10135     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10136     */
10137    @ViewDebug.ExportedProperty(category = "focus")
10138    public final boolean isKeyboardNavigationCluster() {
10139        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
10140    }
10141
10142    /**
10143     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
10144     * will be ignored.
10145     *
10146     * @return the keyboard navigation cluster that this view is in (can be this view)
10147     *         or {@code null} if not in one
10148     */
10149    View findKeyboardNavigationCluster() {
10150        if (mParent instanceof View) {
10151            View cluster = ((View) mParent).findKeyboardNavigationCluster();
10152            if (cluster != null) {
10153                return cluster;
10154            } else if (isKeyboardNavigationCluster()) {
10155                return this;
10156            }
10157        }
10158        return null;
10159    }
10160
10161    /**
10162     * Set whether this view is a root of a keyboard navigation cluster.
10163     *
10164     * @param isCluster If true, this view is a root of a cluster.
10165     *
10166     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10167     */
10168    public void setKeyboardNavigationCluster(boolean isCluster) {
10169        if (isCluster) {
10170            mPrivateFlags3 |= PFLAG3_CLUSTER;
10171        } else {
10172            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
10173        }
10174    }
10175
10176    /**
10177     * Sets this View as the one which receives focus the next time cluster navigation jumps
10178     * to the cluster containing this View. This does NOT change focus even if the cluster
10179     * containing this view is current.
10180     *
10181     * @hide
10182     */
10183    @TestApi
10184    public final void setFocusedInCluster() {
10185        setFocusedInCluster(findKeyboardNavigationCluster());
10186    }
10187
10188    private void setFocusedInCluster(View cluster) {
10189        if (this instanceof ViewGroup) {
10190            ((ViewGroup) this).mFocusedInCluster = null;
10191        }
10192        if (cluster == this) {
10193            return;
10194        }
10195        ViewParent parent = mParent;
10196        View child = this;
10197        while (parent instanceof ViewGroup) {
10198            ((ViewGroup) parent).mFocusedInCluster = child;
10199            if (parent == cluster) {
10200                break;
10201            }
10202            child = (View) parent;
10203            parent = parent.getParent();
10204        }
10205    }
10206
10207    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10208        if (oldFocus != null) {
10209            View oldCluster = oldFocus.findKeyboardNavigationCluster();
10210            View cluster = findKeyboardNavigationCluster();
10211            if (oldCluster != cluster) {
10212                // Going from one cluster to another, so save last-focused.
10213                // This covers cluster jumps because they are always FOCUS_DOWN
10214                oldFocus.setFocusedInCluster(oldCluster);
10215                if (!(oldFocus.mParent instanceof ViewGroup)) {
10216                    return;
10217                }
10218                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10219                    // This is a result of ordered navigation so consider navigation through
10220                    // the previous cluster "complete" and clear its last-focused memory.
10221                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10222                } else if (oldFocus instanceof ViewGroup
10223                        && ((ViewGroup) oldFocus).getDescendantFocusability()
10224                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
10225                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10226                    // This means oldFocus is not focusable since it obviously has a focusable
10227                    // child (this). Don't restore focus to it in the future.
10228                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10229                }
10230            }
10231        }
10232    }
10233
10234    /**
10235     * Returns whether this View should receive focus when the focus is restored for the view
10236     * hierarchy containing this view.
10237     * <p>
10238     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10239     * window or serves as a target of cluster navigation.
10240     *
10241     * @see #restoreDefaultFocus()
10242     *
10243     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10244     * @attr ref android.R.styleable#View_focusedByDefault
10245     */
10246    @ViewDebug.ExportedProperty(category = "focus")
10247    public final boolean isFocusedByDefault() {
10248        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10249    }
10250
10251    /**
10252     * Sets whether this View should receive focus when the focus is restored for the view
10253     * hierarchy containing this view.
10254     * <p>
10255     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10256     * window or serves as a target of cluster navigation.
10257     *
10258     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10259     *                           {@code false} otherwise.
10260     *
10261     * @see #restoreDefaultFocus()
10262     *
10263     * @attr ref android.R.styleable#View_focusedByDefault
10264     */
10265    public void setFocusedByDefault(boolean isFocusedByDefault) {
10266        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10267            return;
10268        }
10269
10270        if (isFocusedByDefault) {
10271            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10272        } else {
10273            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10274        }
10275
10276        if (mParent instanceof ViewGroup) {
10277            if (isFocusedByDefault) {
10278                ((ViewGroup) mParent).setDefaultFocus(this);
10279            } else {
10280                ((ViewGroup) mParent).clearDefaultFocus(this);
10281            }
10282        }
10283    }
10284
10285    /**
10286     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
10287     *
10288     * @return {@code true} if this view has default focus, {@code false} otherwise
10289     */
10290    boolean hasDefaultFocus() {
10291        return isFocusedByDefault();
10292    }
10293
10294    /**
10295     * Find the nearest keyboard navigation cluster in the specified direction.
10296     * This does not actually give focus to that cluster.
10297     *
10298     * @param currentCluster The starting point of the search. Null means the current cluster is not
10299     *                       found yet
10300     * @param direction Direction to look
10301     *
10302     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
10303     *         can be found
10304     */
10305    public View keyboardNavigationClusterSearch(View currentCluster,
10306            @FocusDirection int direction) {
10307        if (isKeyboardNavigationCluster()) {
10308            currentCluster = this;
10309        }
10310        if (isRootNamespace()) {
10311            // Root namespace means we should consider ourselves the top of the
10312            // tree for group searching; otherwise we could be group searching
10313            // into other tabs.  see LocalActivityManager and TabHost for more info.
10314            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
10315                    this, currentCluster, direction);
10316        } else if (mParent != null) {
10317            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
10318        }
10319        return null;
10320    }
10321
10322    /**
10323     * This method is the last chance for the focused view and its ancestors to
10324     * respond to an arrow key. This is called when the focused view did not
10325     * consume the key internally, nor could the view system find a new view in
10326     * the requested direction to give focus to.
10327     *
10328     * @param focused The currently focused view.
10329     * @param direction The direction focus wants to move. One of FOCUS_UP,
10330     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
10331     * @return True if the this view consumed this unhandled move.
10332     */
10333    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
10334        return false;
10335    }
10336
10337    /**
10338     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10339     * have {@link android.R.attr#state_focused} defined in its background.
10340     *
10341     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10342     *                                      highlight, {@code false} otherwise.
10343     *
10344     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10345     */
10346    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10347        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10348    }
10349
10350    /**
10351
10352    /**
10353     * Returns whether this View should use a default focus highlight when it gets focused but
10354     * doesn't have {@link android.R.attr#state_focused} defined in its background.
10355     *
10356     * @return True if this View should use a default focus highlight.
10357     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10358     */
10359    @ViewDebug.ExportedProperty(category = "focus")
10360    public final boolean getDefaultFocusHighlightEnabled() {
10361        return mDefaultFocusHighlightEnabled;
10362    }
10363
10364    /**
10365     * If a user manually specified the next view id for a particular direction,
10366     * use the root to look up the view.
10367     * @param root The root view of the hierarchy containing this view.
10368     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10369     * or FOCUS_BACKWARD.
10370     * @return The user specified next view, or null if there is none.
10371     */
10372    View findUserSetNextFocus(View root, @FocusDirection int direction) {
10373        switch (direction) {
10374            case FOCUS_LEFT:
10375                if (mNextFocusLeftId == View.NO_ID) return null;
10376                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10377            case FOCUS_RIGHT:
10378                if (mNextFocusRightId == View.NO_ID) return null;
10379                return findViewInsideOutShouldExist(root, mNextFocusRightId);
10380            case FOCUS_UP:
10381                if (mNextFocusUpId == View.NO_ID) return null;
10382                return findViewInsideOutShouldExist(root, mNextFocusUpId);
10383            case FOCUS_DOWN:
10384                if (mNextFocusDownId == View.NO_ID) return null;
10385                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10386            case FOCUS_FORWARD:
10387                if (mNextFocusForwardId == View.NO_ID) return null;
10388                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10389            case FOCUS_BACKWARD: {
10390                if (mID == View.NO_ID) return null;
10391                final int id = mID;
10392                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10393                    @Override
10394                    public boolean test(View t) {
10395                        return t.mNextFocusForwardId == id;
10396                    }
10397                });
10398            }
10399        }
10400        return null;
10401    }
10402
10403    /**
10404     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10405     * use the root to look up the view.
10406     *
10407     * @param root the root view of the hierarchy containing this view
10408     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10409     * @return the user-specified next cluster, or {@code null} if there is none
10410     */
10411    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10412        switch (direction) {
10413            case FOCUS_FORWARD:
10414                if (mNextClusterForwardId == View.NO_ID) return null;
10415                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10416            case FOCUS_BACKWARD: {
10417                if (mID == View.NO_ID) return null;
10418                final int id = mID;
10419                return root.findViewByPredicateInsideOut(this,
10420                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10421            }
10422        }
10423        return null;
10424    }
10425
10426    private View findViewInsideOutShouldExist(View root, int id) {
10427        if (mMatchIdPredicate == null) {
10428            mMatchIdPredicate = new MatchIdPredicate();
10429        }
10430        mMatchIdPredicate.mId = id;
10431        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10432        if (result == null) {
10433            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10434        }
10435        return result;
10436    }
10437
10438    /**
10439     * Find and return all focusable views that are descendants of this view,
10440     * possibly including this view if it is focusable itself.
10441     *
10442     * @param direction The direction of the focus
10443     * @return A list of focusable views
10444     */
10445    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10446        ArrayList<View> result = new ArrayList<View>(24);
10447        addFocusables(result, direction);
10448        return result;
10449    }
10450
10451    /**
10452     * Add any focusable views that are descendants of this view (possibly
10453     * including this view if it is focusable itself) to views.  If we are in touch mode,
10454     * only add views that are also focusable in touch mode.
10455     *
10456     * @param views Focusable views found so far
10457     * @param direction The direction of the focus
10458     */
10459    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10460        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10461    }
10462
10463    /**
10464     * Adds any focusable views that are descendants of this view (possibly
10465     * including this view if it is focusable itself) to views. This method
10466     * adds all focusable views regardless if we are in touch mode or
10467     * only views focusable in touch mode if we are in touch mode or
10468     * only views that can take accessibility focus if accessibility is enabled
10469     * depending on the focusable mode parameter.
10470     *
10471     * @param views Focusable views found so far or null if all we are interested is
10472     *        the number of focusables.
10473     * @param direction The direction of the focus.
10474     * @param focusableMode The type of focusables to be added.
10475     *
10476     * @see #FOCUSABLES_ALL
10477     * @see #FOCUSABLES_TOUCH_MODE
10478     */
10479    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10480            @FocusableMode int focusableMode) {
10481        if (views == null) {
10482            return;
10483        }
10484        if (!isFocusable()) {
10485            return;
10486        }
10487        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10488                && !isFocusableInTouchMode()) {
10489            return;
10490        }
10491        views.add(this);
10492    }
10493
10494    /**
10495     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10496     * including this view if it is a cluster root itself) to views.
10497     *
10498     * @param views Keyboard navigation cluster roots found so far
10499     * @param direction Direction to look
10500     */
10501    public void addKeyboardNavigationClusters(
10502            @NonNull Collection<View> views,
10503            int direction) {
10504        if (!isKeyboardNavigationCluster()) {
10505            return;
10506        }
10507        if (!hasFocusable()) {
10508            return;
10509        }
10510        views.add(this);
10511    }
10512
10513    /**
10514     * Finds the Views that contain given text. The containment is case insensitive.
10515     * The search is performed by either the text that the View renders or the content
10516     * description that describes the view for accessibility purposes and the view does
10517     * not render or both. Clients can specify how the search is to be performed via
10518     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10519     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10520     *
10521     * @param outViews The output list of matching Views.
10522     * @param searched The text to match against.
10523     *
10524     * @see #FIND_VIEWS_WITH_TEXT
10525     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10526     * @see #setContentDescription(CharSequence)
10527     */
10528    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10529            @FindViewFlags int flags) {
10530        if (getAccessibilityNodeProvider() != null) {
10531            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10532                outViews.add(this);
10533            }
10534        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10535                && (searched != null && searched.length() > 0)
10536                && (mContentDescription != null && mContentDescription.length() > 0)) {
10537            String searchedLowerCase = searched.toString().toLowerCase();
10538            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10539            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10540                outViews.add(this);
10541            }
10542        }
10543    }
10544
10545    /**
10546     * Find and return all touchable views that are descendants of this view,
10547     * possibly including this view if it is touchable itself.
10548     *
10549     * @return A list of touchable views
10550     */
10551    public ArrayList<View> getTouchables() {
10552        ArrayList<View> result = new ArrayList<View>();
10553        addTouchables(result);
10554        return result;
10555    }
10556
10557    /**
10558     * Add any touchable views that are descendants of this view (possibly
10559     * including this view if it is touchable itself) to views.
10560     *
10561     * @param views Touchable views found so far
10562     */
10563    public void addTouchables(ArrayList<View> views) {
10564        final int viewFlags = mViewFlags;
10565
10566        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10567                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10568                && (viewFlags & ENABLED_MASK) == ENABLED) {
10569            views.add(this);
10570        }
10571    }
10572
10573    /**
10574     * Returns whether this View is accessibility focused.
10575     *
10576     * @return True if this View is accessibility focused.
10577     */
10578    public boolean isAccessibilityFocused() {
10579        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10580    }
10581
10582    /**
10583     * Call this to try to give accessibility focus to this view.
10584     *
10585     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10586     * returns false or the view is no visible or the view already has accessibility
10587     * focus.
10588     *
10589     * See also {@link #focusSearch(int)}, which is what you call to say that you
10590     * have focus, and you want your parent to look for the next one.
10591     *
10592     * @return Whether this view actually took accessibility focus.
10593     *
10594     * @hide
10595     */
10596    public boolean requestAccessibilityFocus() {
10597        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10598        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10599            return false;
10600        }
10601        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10602            return false;
10603        }
10604        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10605            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10606            ViewRootImpl viewRootImpl = getViewRootImpl();
10607            if (viewRootImpl != null) {
10608                viewRootImpl.setAccessibilityFocus(this, null);
10609            }
10610            invalidate();
10611            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10612            return true;
10613        }
10614        return false;
10615    }
10616
10617    /**
10618     * Call this to try to clear accessibility focus of this view.
10619     *
10620     * See also {@link #focusSearch(int)}, which is what you call to say that you
10621     * have focus, and you want your parent to look for the next one.
10622     *
10623     * @hide
10624     */
10625    public void clearAccessibilityFocus() {
10626        clearAccessibilityFocusNoCallbacks(0);
10627
10628        // Clear the global reference of accessibility focus if this view or
10629        // any of its descendants had accessibility focus. This will NOT send
10630        // an event or update internal state if focus is cleared from a
10631        // descendant view, which may leave views in inconsistent states.
10632        final ViewRootImpl viewRootImpl = getViewRootImpl();
10633        if (viewRootImpl != null) {
10634            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10635            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10636                viewRootImpl.setAccessibilityFocus(null, null);
10637            }
10638        }
10639    }
10640
10641    private void sendAccessibilityHoverEvent(int eventType) {
10642        // Since we are not delivering to a client accessibility events from not
10643        // important views (unless the clinet request that) we need to fire the
10644        // event from the deepest view exposed to the client. As a consequence if
10645        // the user crosses a not exposed view the client will see enter and exit
10646        // of the exposed predecessor followed by and enter and exit of that same
10647        // predecessor when entering and exiting the not exposed descendant. This
10648        // is fine since the client has a clear idea which view is hovered at the
10649        // price of a couple more events being sent. This is a simple and
10650        // working solution.
10651        View source = this;
10652        while (true) {
10653            if (source.includeForAccessibility()) {
10654                source.sendAccessibilityEvent(eventType);
10655                return;
10656            }
10657            ViewParent parent = source.getParent();
10658            if (parent instanceof View) {
10659                source = (View) parent;
10660            } else {
10661                return;
10662            }
10663        }
10664    }
10665
10666    /**
10667     * Clears accessibility focus without calling any callback methods
10668     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10669     * is used separately from that one for clearing accessibility focus when
10670     * giving this focus to another view.
10671     *
10672     * @param action The action, if any, that led to focus being cleared. Set to
10673     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10674     * the window.
10675     */
10676    void clearAccessibilityFocusNoCallbacks(int action) {
10677        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10678            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10679            invalidate();
10680            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10681                AccessibilityEvent event = AccessibilityEvent.obtain(
10682                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10683                event.setAction(action);
10684                if (mAccessibilityDelegate != null) {
10685                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10686                } else {
10687                    sendAccessibilityEventUnchecked(event);
10688                }
10689            }
10690        }
10691    }
10692
10693    /**
10694     * Call this to try to give focus to a specific view or to one of its
10695     * descendants.
10696     *
10697     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10698     * false), or if it is focusable and it is not focusable in touch mode
10699     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10700     *
10701     * See also {@link #focusSearch(int)}, which is what you call to say that you
10702     * have focus, and you want your parent to look for the next one.
10703     *
10704     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10705     * {@link #FOCUS_DOWN} and <code>null</code>.
10706     *
10707     * @return Whether this view or one of its descendants actually took focus.
10708     */
10709    public final boolean requestFocus() {
10710        return requestFocus(View.FOCUS_DOWN);
10711    }
10712
10713    /**
10714     * This will request focus for whichever View was last focused within this
10715     * cluster before a focus-jump out of it.
10716     *
10717     * @hide
10718     */
10719    @TestApi
10720    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10721        // Prioritize focusableByDefault over algorithmic focus selection.
10722        if (restoreDefaultFocus()) {
10723            return true;
10724        }
10725        return requestFocus(direction);
10726    }
10727
10728    /**
10729     * This will request focus for whichever View not in a cluster was last focused before a
10730     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10731     * the "first" focusable view it finds.
10732     *
10733     * @hide
10734     */
10735    @TestApi
10736    public boolean restoreFocusNotInCluster() {
10737        return requestFocus(View.FOCUS_DOWN);
10738    }
10739
10740    /**
10741     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10742     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10743     *
10744     * @return Whether this view or one of its descendants actually took focus
10745     */
10746    public boolean restoreDefaultFocus() {
10747        return requestFocus(View.FOCUS_DOWN);
10748    }
10749
10750    /**
10751     * Call this to try to give focus to a specific view or to one of its
10752     * descendants and give it a hint about what direction focus is heading.
10753     *
10754     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10755     * false), or if it is focusable and it is not focusable in touch mode
10756     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10757     *
10758     * See also {@link #focusSearch(int)}, which is what you call to say that you
10759     * have focus, and you want your parent to look for the next one.
10760     *
10761     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10762     * <code>null</code> set for the previously focused rectangle.
10763     *
10764     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10765     * @return Whether this view or one of its descendants actually took focus.
10766     */
10767    public final boolean requestFocus(int direction) {
10768        return requestFocus(direction, null);
10769    }
10770
10771    /**
10772     * Call this to try to give focus to a specific view or to one of its descendants
10773     * and give it hints about the direction and a specific rectangle that the focus
10774     * is coming from.  The rectangle can help give larger views a finer grained hint
10775     * about where focus is coming from, and therefore, where to show selection, or
10776     * forward focus change internally.
10777     *
10778     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10779     * false), or if it is focusable and it is not focusable in touch mode
10780     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10781     *
10782     * A View will not take focus if it is not visible.
10783     *
10784     * A View will not take focus if one of its parents has
10785     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10786     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10787     *
10788     * See also {@link #focusSearch(int)}, which is what you call to say that you
10789     * have focus, and you want your parent to look for the next one.
10790     *
10791     * You may wish to override this method if your custom {@link View} has an internal
10792     * {@link View} that it wishes to forward the request to.
10793     *
10794     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10795     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10796     *        to give a finer grained hint about where focus is coming from.  May be null
10797     *        if there is no hint.
10798     * @return Whether this view or one of its descendants actually took focus.
10799     */
10800    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10801        return requestFocusNoSearch(direction, previouslyFocusedRect);
10802    }
10803
10804    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10805        // need to be focusable
10806        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10807                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10808            return false;
10809        }
10810
10811        // need to be focusable in touch mode if in touch mode
10812        if (isInTouchMode() &&
10813            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10814               return false;
10815        }
10816
10817        // need to not have any parents blocking us
10818        if (hasAncestorThatBlocksDescendantFocus()) {
10819            return false;
10820        }
10821
10822        handleFocusGainInternal(direction, previouslyFocusedRect);
10823        return true;
10824    }
10825
10826    /**
10827     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10828     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10829     * touch mode to request focus when they are touched.
10830     *
10831     * @return Whether this view or one of its descendants actually took focus.
10832     *
10833     * @see #isInTouchMode()
10834     *
10835     */
10836    public final boolean requestFocusFromTouch() {
10837        // Leave touch mode if we need to
10838        if (isInTouchMode()) {
10839            ViewRootImpl viewRoot = getViewRootImpl();
10840            if (viewRoot != null) {
10841                viewRoot.ensureTouchMode(false);
10842            }
10843        }
10844        return requestFocus(View.FOCUS_DOWN);
10845    }
10846
10847    /**
10848     * @return Whether any ancestor of this view blocks descendant focus.
10849     */
10850    private boolean hasAncestorThatBlocksDescendantFocus() {
10851        final boolean focusableInTouchMode = isFocusableInTouchMode();
10852        ViewParent ancestor = mParent;
10853        while (ancestor instanceof ViewGroup) {
10854            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10855            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10856                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10857                return true;
10858            } else {
10859                ancestor = vgAncestor.getParent();
10860            }
10861        }
10862        return false;
10863    }
10864
10865    /**
10866     * Gets the mode for determining whether this View is important for accessibility.
10867     * A view is important for accessibility if it fires accessibility events and if it
10868     * is reported to accessibility services that query the screen.
10869     *
10870     * @return The mode for determining whether a view is important for accessibility, one
10871     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10872     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10873     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10874     *
10875     * @attr ref android.R.styleable#View_importantForAccessibility
10876     *
10877     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10878     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10879     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10880     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10881     */
10882    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10883            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10884            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10885            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10886            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10887                    to = "noHideDescendants")
10888        })
10889    public int getImportantForAccessibility() {
10890        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10891                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10892    }
10893
10894    /**
10895     * Sets the live region mode for this view. This indicates to accessibility
10896     * services whether they should automatically notify the user about changes
10897     * to the view's content description or text, or to the content descriptions
10898     * or text of the view's children (where applicable).
10899     * <p>
10900     * For example, in a login screen with a TextView that displays an "incorrect
10901     * password" notification, that view should be marked as a live region with
10902     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10903     * <p>
10904     * To disable change notifications for this view, use
10905     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10906     * mode for most views.
10907     * <p>
10908     * To indicate that the user should be notified of changes, use
10909     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10910     * <p>
10911     * If the view's changes should interrupt ongoing speech and notify the user
10912     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10913     *
10914     * @param mode The live region mode for this view, one of:
10915     *        <ul>
10916     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10917     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10918     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10919     *        </ul>
10920     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10921     */
10922    public void setAccessibilityLiveRegion(int mode) {
10923        if (mode != getAccessibilityLiveRegion()) {
10924            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10925            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10926                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10927            notifyViewAccessibilityStateChangedIfNeeded(
10928                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10929        }
10930    }
10931
10932    /**
10933     * Gets the live region mode for this View.
10934     *
10935     * @return The live region mode for the view.
10936     *
10937     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10938     *
10939     * @see #setAccessibilityLiveRegion(int)
10940     */
10941    public int getAccessibilityLiveRegion() {
10942        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10943                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10944    }
10945
10946    /**
10947     * Sets how to determine whether this view is important for accessibility
10948     * which is if it fires accessibility events and if it is reported to
10949     * accessibility services that query the screen.
10950     *
10951     * @param mode How to determine whether this view is important for accessibility.
10952     *
10953     * @attr ref android.R.styleable#View_importantForAccessibility
10954     *
10955     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10956     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10957     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10958     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10959     */
10960    public void setImportantForAccessibility(int mode) {
10961        final int oldMode = getImportantForAccessibility();
10962        if (mode != oldMode) {
10963            final boolean hideDescendants =
10964                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10965
10966            // If this node or its descendants are no longer important, try to
10967            // clear accessibility focus.
10968            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10969                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10970                if (focusHost != null) {
10971                    focusHost.clearAccessibilityFocus();
10972                }
10973            }
10974
10975            // If we're moving between AUTO and another state, we might not need
10976            // to send a subtree changed notification. We'll store the computed
10977            // importance, since we'll need to check it later to make sure.
10978            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10979                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10980            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10981            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10982            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10983                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10984            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10985                notifySubtreeAccessibilityStateChangedIfNeeded();
10986            } else {
10987                notifyViewAccessibilityStateChangedIfNeeded(
10988                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10989            }
10990        }
10991    }
10992
10993    /**
10994     * Returns the view within this view's hierarchy that is hosting
10995     * accessibility focus.
10996     *
10997     * @param searchDescendants whether to search for focus in descendant views
10998     * @return the view hosting accessibility focus, or {@code null}
10999     */
11000    private View findAccessibilityFocusHost(boolean searchDescendants) {
11001        if (isAccessibilityFocusedViewOrHost()) {
11002            return this;
11003        }
11004
11005        if (searchDescendants) {
11006            final ViewRootImpl viewRoot = getViewRootImpl();
11007            if (viewRoot != null) {
11008                final View focusHost = viewRoot.getAccessibilityFocusedHost();
11009                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
11010                    return focusHost;
11011                }
11012            }
11013        }
11014
11015        return null;
11016    }
11017
11018    /**
11019     * Computes whether this view should be exposed for accessibility. In
11020     * general, views that are interactive or provide information are exposed
11021     * while views that serve only as containers are hidden.
11022     * <p>
11023     * If an ancestor of this view has importance
11024     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
11025     * returns <code>false</code>.
11026     * <p>
11027     * Otherwise, the value is computed according to the view's
11028     * {@link #getImportantForAccessibility()} value:
11029     * <ol>
11030     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
11031     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
11032     * </code>
11033     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
11034     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
11035     * view satisfies any of the following:
11036     * <ul>
11037     * <li>Is actionable, e.g. {@link #isClickable()},
11038     * {@link #isLongClickable()}, or {@link #isFocusable()}
11039     * <li>Has an {@link AccessibilityDelegate}
11040     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
11041     * {@link OnKeyListener}, etc.
11042     * <li>Is an accessibility live region, e.g.
11043     * {@link #getAccessibilityLiveRegion()} is not
11044     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
11045     * </ul>
11046     * </ol>
11047     *
11048     * @return Whether the view is exposed for accessibility.
11049     * @see #setImportantForAccessibility(int)
11050     * @see #getImportantForAccessibility()
11051     */
11052    public boolean isImportantForAccessibility() {
11053        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11054                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11055        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
11056                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11057            return false;
11058        }
11059
11060        // Check parent mode to ensure we're not hidden.
11061        ViewParent parent = mParent;
11062        while (parent instanceof View) {
11063            if (((View) parent).getImportantForAccessibility()
11064                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11065                return false;
11066            }
11067            parent = parent.getParent();
11068        }
11069
11070        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
11071                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
11072                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
11073    }
11074
11075    /**
11076     * Gets the parent for accessibility purposes. Note that the parent for
11077     * accessibility is not necessary the immediate parent. It is the first
11078     * predecessor that is important for accessibility.
11079     *
11080     * @return The parent for accessibility purposes.
11081     */
11082    public ViewParent getParentForAccessibility() {
11083        if (mParent instanceof View) {
11084            View parentView = (View) mParent;
11085            if (parentView.includeForAccessibility()) {
11086                return mParent;
11087            } else {
11088                return mParent.getParentForAccessibility();
11089            }
11090        }
11091        return null;
11092    }
11093
11094    /**
11095     * Adds the children of this View relevant for accessibility to the given list
11096     * as output. Since some Views are not important for accessibility the added
11097     * child views are not necessarily direct children of this view, rather they are
11098     * the first level of descendants important for accessibility.
11099     *
11100     * @param outChildren The output list that will receive children for accessibility.
11101     */
11102    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
11103
11104    }
11105
11106    /**
11107     * Whether to regard this view for accessibility. A view is regarded for
11108     * accessibility if it is important for accessibility or the querying
11109     * accessibility service has explicitly requested that view not
11110     * important for accessibility are regarded.
11111     *
11112     * @return Whether to regard the view for accessibility.
11113     *
11114     * @hide
11115     */
11116    public boolean includeForAccessibility() {
11117        if (mAttachInfo != null) {
11118            return (mAttachInfo.mAccessibilityFetchFlags
11119                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
11120                    || isImportantForAccessibility();
11121        }
11122        return false;
11123    }
11124
11125    /**
11126     * Returns whether the View is considered actionable from
11127     * accessibility perspective. Such view are important for
11128     * accessibility.
11129     *
11130     * @return True if the view is actionable for accessibility.
11131     *
11132     * @hide
11133     */
11134    public boolean isActionableForAccessibility() {
11135        return (isClickable() || isLongClickable() || isFocusable());
11136    }
11137
11138    /**
11139     * Returns whether the View has registered callbacks which makes it
11140     * important for accessibility.
11141     *
11142     * @return True if the view is actionable for accessibility.
11143     */
11144    private boolean hasListenersForAccessibility() {
11145        ListenerInfo info = getListenerInfo();
11146        return mTouchDelegate != null || info.mOnKeyListener != null
11147                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
11148                || info.mOnHoverListener != null || info.mOnDragListener != null;
11149    }
11150
11151    /**
11152     * Notifies that the accessibility state of this view changed. The change
11153     * is local to this view and does not represent structural changes such
11154     * as children and parent. For example, the view became focusable. The
11155     * notification is at at most once every
11156     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11157     * to avoid unnecessary load to the system. Also once a view has a pending
11158     * notification this method is a NOP until the notification has been sent.
11159     *
11160     * @hide
11161     */
11162    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
11163        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11164            return;
11165        }
11166        // If this is a live region, we should send a subtree change event
11167        // from this view immediately. Otherwise, we can let it propagate up.
11168        if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
11169            final AccessibilityEvent event = AccessibilityEvent.obtain();
11170            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11171            event.setContentChangeTypes(changeType);
11172            sendAccessibilityEventUnchecked(event);
11173        } else if (mParent != null) {
11174            try {
11175                mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
11176            } catch (AbstractMethodError e) {
11177                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11178                        " does not fully implement ViewParent", e);
11179            }
11180        }
11181    }
11182
11183    /**
11184     * Notifies that the accessibility state of this view changed. The change
11185     * is *not* local to this view and does represent structural changes such
11186     * as children and parent. For example, the view size changed. The
11187     * notification is at at most once every
11188     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11189     * to avoid unnecessary load to the system. Also once a view has a pending
11190     * notification this method is a NOP until the notification has been sent.
11191     *
11192     * @hide
11193     */
11194    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11195        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11196            return;
11197        }
11198        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11199            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11200            if (mParent != null) {
11201                try {
11202                    mParent.notifySubtreeAccessibilityStateChanged(
11203                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11204                } catch (AbstractMethodError e) {
11205                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11206                            " does not fully implement ViewParent", e);
11207                }
11208            }
11209        }
11210    }
11211
11212    /**
11213     * Change the visibility of the View without triggering any other changes. This is
11214     * important for transitions, where visibility changes should not adjust focus or
11215     * trigger a new layout. This is only used when the visibility has already been changed
11216     * and we need a transient value during an animation. When the animation completes,
11217     * the original visibility value is always restored.
11218     *
11219     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11220     * @hide
11221     */
11222    public void setTransitionVisibility(@Visibility int visibility) {
11223        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11224    }
11225
11226    /**
11227     * Reset the flag indicating the accessibility state of the subtree rooted
11228     * at this view changed.
11229     */
11230    void resetSubtreeAccessibilityStateChanged() {
11231        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11232    }
11233
11234    /**
11235     * Report an accessibility action to this view's parents for delegated processing.
11236     *
11237     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
11238     * call this method to delegate an accessibility action to a supporting parent. If the parent
11239     * returns true from its
11240     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
11241     * method this method will return true to signify that the action was consumed.</p>
11242     *
11243     * <p>This method is useful for implementing nested scrolling child views. If
11244     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
11245     * a custom view implementation may invoke this method to allow a parent to consume the
11246     * scroll first. If this method returns true the custom view should skip its own scrolling
11247     * behavior.</p>
11248     *
11249     * @param action Accessibility action to delegate
11250     * @param arguments Optional action arguments
11251     * @return true if the action was consumed by a parent
11252     */
11253    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
11254        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
11255            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
11256                return true;
11257            }
11258        }
11259        return false;
11260    }
11261
11262    /**
11263     * Performs the specified accessibility action on the view. For
11264     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
11265     * <p>
11266     * If an {@link AccessibilityDelegate} has been specified via calling
11267     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11268     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
11269     * is responsible for handling this call.
11270     * </p>
11271     *
11272     * <p>The default implementation will delegate
11273     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
11274     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
11275     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
11276     *
11277     * @param action The action to perform.
11278     * @param arguments Optional action arguments.
11279     * @return Whether the action was performed.
11280     */
11281    public boolean performAccessibilityAction(int action, Bundle arguments) {
11282      if (mAccessibilityDelegate != null) {
11283          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
11284      } else {
11285          return performAccessibilityActionInternal(action, arguments);
11286      }
11287    }
11288
11289   /**
11290    * @see #performAccessibilityAction(int, Bundle)
11291    *
11292    * Note: Called from the default {@link AccessibilityDelegate}.
11293    *
11294    * @hide
11295    */
11296    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
11297        if (isNestedScrollingEnabled()
11298                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
11299                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
11300                || action == R.id.accessibilityActionScrollUp
11301                || action == R.id.accessibilityActionScrollLeft
11302                || action == R.id.accessibilityActionScrollDown
11303                || action == R.id.accessibilityActionScrollRight)) {
11304            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
11305                return true;
11306            }
11307        }
11308
11309        switch (action) {
11310            case AccessibilityNodeInfo.ACTION_CLICK: {
11311                if (isClickable()) {
11312                    performClick();
11313                    return true;
11314                }
11315            } break;
11316            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
11317                if (isLongClickable()) {
11318                    performLongClick();
11319                    return true;
11320                }
11321            } break;
11322            case AccessibilityNodeInfo.ACTION_FOCUS: {
11323                if (!hasFocus()) {
11324                    // Get out of touch mode since accessibility
11325                    // wants to move focus around.
11326                    getViewRootImpl().ensureTouchMode(false);
11327                    return requestFocus();
11328                }
11329            } break;
11330            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
11331                if (hasFocus()) {
11332                    clearFocus();
11333                    return !isFocused();
11334                }
11335            } break;
11336            case AccessibilityNodeInfo.ACTION_SELECT: {
11337                if (!isSelected()) {
11338                    setSelected(true);
11339                    return isSelected();
11340                }
11341            } break;
11342            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
11343                if (isSelected()) {
11344                    setSelected(false);
11345                    return !isSelected();
11346                }
11347            } break;
11348            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11349                if (!isAccessibilityFocused()) {
11350                    return requestAccessibilityFocus();
11351                }
11352            } break;
11353            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11354                if (isAccessibilityFocused()) {
11355                    clearAccessibilityFocus();
11356                    return true;
11357                }
11358            } break;
11359            case AccessibilityNodeInfo.ACTION_NEXT_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, true, extendSelection);
11366                }
11367            } break;
11368            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11369                if (arguments != null) {
11370                    final int granularity = arguments.getInt(
11371                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11372                    final boolean extendSelection = arguments.getBoolean(
11373                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11374                    return traverseAtGranularity(granularity, false, extendSelection);
11375                }
11376            } break;
11377            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11378                CharSequence text = getIterableTextForAccessibility();
11379                if (text == null) {
11380                    return false;
11381                }
11382                final int start = (arguments != null) ? arguments.getInt(
11383                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11384                final int end = (arguments != null) ? arguments.getInt(
11385                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11386                // Only cursor position can be specified (selection length == 0)
11387                if ((getAccessibilitySelectionStart() != start
11388                        || getAccessibilitySelectionEnd() != end)
11389                        && (start == end)) {
11390                    setAccessibilitySelection(start, end);
11391                    notifyViewAccessibilityStateChangedIfNeeded(
11392                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11393                    return true;
11394                }
11395            } break;
11396            case R.id.accessibilityActionShowOnScreen: {
11397                if (mAttachInfo != null) {
11398                    final Rect r = mAttachInfo.mTmpInvalRect;
11399                    getDrawingRect(r);
11400                    return requestRectangleOnScreen(r, true);
11401                }
11402            } break;
11403            case R.id.accessibilityActionContextClick: {
11404                if (isContextClickable()) {
11405                    performContextClick();
11406                    return true;
11407                }
11408            } break;
11409        }
11410        return false;
11411    }
11412
11413    private boolean traverseAtGranularity(int granularity, boolean forward,
11414            boolean extendSelection) {
11415        CharSequence text = getIterableTextForAccessibility();
11416        if (text == null || text.length() == 0) {
11417            return false;
11418        }
11419        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11420        if (iterator == null) {
11421            return false;
11422        }
11423        int current = getAccessibilitySelectionEnd();
11424        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11425            current = forward ? 0 : text.length();
11426        }
11427        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11428        if (range == null) {
11429            return false;
11430        }
11431        final int segmentStart = range[0];
11432        final int segmentEnd = range[1];
11433        int selectionStart;
11434        int selectionEnd;
11435        if (extendSelection && isAccessibilitySelectionExtendable()) {
11436            selectionStart = getAccessibilitySelectionStart();
11437            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11438                selectionStart = forward ? segmentStart : segmentEnd;
11439            }
11440            selectionEnd = forward ? segmentEnd : segmentStart;
11441        } else {
11442            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11443        }
11444        setAccessibilitySelection(selectionStart, selectionEnd);
11445        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11446                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11447        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11448        return true;
11449    }
11450
11451    /**
11452     * Gets the text reported for accessibility purposes.
11453     *
11454     * @return The accessibility text.
11455     *
11456     * @hide
11457     */
11458    public CharSequence getIterableTextForAccessibility() {
11459        return getContentDescription();
11460    }
11461
11462    /**
11463     * Gets whether accessibility selection can be extended.
11464     *
11465     * @return If selection is extensible.
11466     *
11467     * @hide
11468     */
11469    public boolean isAccessibilitySelectionExtendable() {
11470        return false;
11471    }
11472
11473    /**
11474     * @hide
11475     */
11476    public int getAccessibilitySelectionStart() {
11477        return mAccessibilityCursorPosition;
11478    }
11479
11480    /**
11481     * @hide
11482     */
11483    public int getAccessibilitySelectionEnd() {
11484        return getAccessibilitySelectionStart();
11485    }
11486
11487    /**
11488     * @hide
11489     */
11490    public void setAccessibilitySelection(int start, int end) {
11491        if (start ==  end && end == mAccessibilityCursorPosition) {
11492            return;
11493        }
11494        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11495            mAccessibilityCursorPosition = start;
11496        } else {
11497            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11498        }
11499        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11500    }
11501
11502    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11503            int fromIndex, int toIndex) {
11504        if (mParent == null) {
11505            return;
11506        }
11507        AccessibilityEvent event = AccessibilityEvent.obtain(
11508                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11509        onInitializeAccessibilityEvent(event);
11510        onPopulateAccessibilityEvent(event);
11511        event.setFromIndex(fromIndex);
11512        event.setToIndex(toIndex);
11513        event.setAction(action);
11514        event.setMovementGranularity(granularity);
11515        mParent.requestSendAccessibilityEvent(this, event);
11516    }
11517
11518    /**
11519     * @hide
11520     */
11521    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11522        switch (granularity) {
11523            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11524                CharSequence text = getIterableTextForAccessibility();
11525                if (text != null && text.length() > 0) {
11526                    CharacterTextSegmentIterator iterator =
11527                        CharacterTextSegmentIterator.getInstance(
11528                                mContext.getResources().getConfiguration().locale);
11529                    iterator.initialize(text.toString());
11530                    return iterator;
11531                }
11532            } break;
11533            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11534                CharSequence text = getIterableTextForAccessibility();
11535                if (text != null && text.length() > 0) {
11536                    WordTextSegmentIterator iterator =
11537                        WordTextSegmentIterator.getInstance(
11538                                mContext.getResources().getConfiguration().locale);
11539                    iterator.initialize(text.toString());
11540                    return iterator;
11541                }
11542            } break;
11543            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11544                CharSequence text = getIterableTextForAccessibility();
11545                if (text != null && text.length() > 0) {
11546                    ParagraphTextSegmentIterator iterator =
11547                        ParagraphTextSegmentIterator.getInstance();
11548                    iterator.initialize(text.toString());
11549                    return iterator;
11550                }
11551            } break;
11552        }
11553        return null;
11554    }
11555
11556    /**
11557     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11558     * and {@link #onFinishTemporaryDetach()}.
11559     *
11560     * <p>This method always returns {@code true} when called directly or indirectly from
11561     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11562     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11563     * <ul>
11564     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11565     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11566     * </ul>
11567     * </p>
11568     *
11569     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11570     * and {@link #onFinishTemporaryDetach()}.
11571     */
11572    public final boolean isTemporarilyDetached() {
11573        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11574    }
11575
11576    /**
11577     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11578     * a container View.
11579     */
11580    @CallSuper
11581    public void dispatchStartTemporaryDetach() {
11582        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11583        notifyEnterOrExitForAutoFillIfNeeded(false);
11584        onStartTemporaryDetach();
11585    }
11586
11587    /**
11588     * This is called when a container is going to temporarily detach a child, with
11589     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11590     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11591     * {@link #onDetachedFromWindow()} when the container is done.
11592     */
11593    public void onStartTemporaryDetach() {
11594        removeUnsetPressCallback();
11595        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11596    }
11597
11598    /**
11599     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11600     * a container View.
11601     */
11602    @CallSuper
11603    public void dispatchFinishTemporaryDetach() {
11604        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11605        onFinishTemporaryDetach();
11606        if (hasWindowFocus() && hasFocus()) {
11607            InputMethodManager.getInstance().focusIn(this);
11608        }
11609        notifyEnterOrExitForAutoFillIfNeeded(true);
11610    }
11611
11612    /**
11613     * Called after {@link #onStartTemporaryDetach} when the container is done
11614     * changing the view.
11615     */
11616    public void onFinishTemporaryDetach() {
11617    }
11618
11619    /**
11620     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11621     * for this view's window.  Returns null if the view is not currently attached
11622     * to the window.  Normally you will not need to use this directly, but
11623     * just use the standard high-level event callbacks like
11624     * {@link #onKeyDown(int, KeyEvent)}.
11625     */
11626    public KeyEvent.DispatcherState getKeyDispatcherState() {
11627        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11628    }
11629
11630    /**
11631     * Dispatch a key event before it is processed by any input method
11632     * associated with the view hierarchy.  This can be used to intercept
11633     * key events in special situations before the IME consumes them; a
11634     * typical example would be handling the BACK key to update the application's
11635     * UI instead of allowing the IME to see it and close itself.
11636     *
11637     * @param event The key event to be dispatched.
11638     * @return True if the event was handled, false otherwise.
11639     */
11640    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11641        return onKeyPreIme(event.getKeyCode(), event);
11642    }
11643
11644    /**
11645     * Dispatch a key event to the next view on the focus path. This path runs
11646     * from the top of the view tree down to the currently focused view. If this
11647     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11648     * the next node down the focus path. This method also fires any key
11649     * listeners.
11650     *
11651     * @param event The key event to be dispatched.
11652     * @return True if the event was handled, false otherwise.
11653     */
11654    public boolean dispatchKeyEvent(KeyEvent event) {
11655        if (mInputEventConsistencyVerifier != null) {
11656            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11657        }
11658
11659        // Give any attached key listener a first crack at the event.
11660        //noinspection SimplifiableIfStatement
11661        ListenerInfo li = mListenerInfo;
11662        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11663                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11664            return true;
11665        }
11666
11667        if (event.dispatch(this, mAttachInfo != null
11668                ? mAttachInfo.mKeyDispatchState : null, this)) {
11669            return true;
11670        }
11671
11672        if (mInputEventConsistencyVerifier != null) {
11673            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11674        }
11675        return false;
11676    }
11677
11678    /**
11679     * Dispatches a key shortcut event.
11680     *
11681     * @param event The key event to be dispatched.
11682     * @return True if the event was handled by the view, false otherwise.
11683     */
11684    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11685        return onKeyShortcut(event.getKeyCode(), event);
11686    }
11687
11688    /**
11689     * Pass the touch screen motion event down to the target view, or this
11690     * view if it is the target.
11691     *
11692     * @param event The motion event to be dispatched.
11693     * @return True if the event was handled by the view, false otherwise.
11694     */
11695    public boolean dispatchTouchEvent(MotionEvent event) {
11696        // If the event should be handled by accessibility focus first.
11697        if (event.isTargetAccessibilityFocus()) {
11698            // We don't have focus or no virtual descendant has it, do not handle the event.
11699            if (!isAccessibilityFocusedViewOrHost()) {
11700                return false;
11701            }
11702            // We have focus and got the event, then use normal event dispatch.
11703            event.setTargetAccessibilityFocus(false);
11704        }
11705
11706        boolean result = false;
11707
11708        if (mInputEventConsistencyVerifier != null) {
11709            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11710        }
11711
11712        final int actionMasked = event.getActionMasked();
11713        if (actionMasked == MotionEvent.ACTION_DOWN) {
11714            // Defensive cleanup for new gesture
11715            stopNestedScroll();
11716        }
11717
11718        if (onFilterTouchEventForSecurity(event)) {
11719            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11720                result = true;
11721            }
11722            //noinspection SimplifiableIfStatement
11723            ListenerInfo li = mListenerInfo;
11724            if (li != null && li.mOnTouchListener != null
11725                    && (mViewFlags & ENABLED_MASK) == ENABLED
11726                    && li.mOnTouchListener.onTouch(this, event)) {
11727                result = true;
11728            }
11729
11730            if (!result && onTouchEvent(event)) {
11731                result = true;
11732            }
11733        }
11734
11735        if (!result && mInputEventConsistencyVerifier != null) {
11736            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11737        }
11738
11739        // Clean up after nested scrolls if this is the end of a gesture;
11740        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11741        // of the gesture.
11742        if (actionMasked == MotionEvent.ACTION_UP ||
11743                actionMasked == MotionEvent.ACTION_CANCEL ||
11744                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11745            stopNestedScroll();
11746        }
11747
11748        return result;
11749    }
11750
11751    boolean isAccessibilityFocusedViewOrHost() {
11752        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11753                .getAccessibilityFocusedHost() == this);
11754    }
11755
11756    /**
11757     * Filter the touch event to apply security policies.
11758     *
11759     * @param event The motion event to be filtered.
11760     * @return True if the event should be dispatched, false if the event should be dropped.
11761     *
11762     * @see #getFilterTouchesWhenObscured
11763     */
11764    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11765        //noinspection RedundantIfStatement
11766        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11767                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11768            // Window is obscured, drop this touch.
11769            return false;
11770        }
11771        return true;
11772    }
11773
11774    /**
11775     * Pass a trackball motion event down to the focused view.
11776     *
11777     * @param event The motion event to be dispatched.
11778     * @return True if the event was handled by the view, false otherwise.
11779     */
11780    public boolean dispatchTrackballEvent(MotionEvent event) {
11781        if (mInputEventConsistencyVerifier != null) {
11782            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11783        }
11784
11785        return onTrackballEvent(event);
11786    }
11787
11788    /**
11789     * Pass a captured pointer event down to the focused view.
11790     *
11791     * @param event The motion event to be dispatched.
11792     * @return True if the event was handled by the view, false otherwise.
11793     */
11794    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11795        if (!hasPointerCapture()) {
11796            return false;
11797        }
11798        //noinspection SimplifiableIfStatement
11799        ListenerInfo li = mListenerInfo;
11800        if (li != null && li.mOnCapturedPointerListener != null
11801                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11802            return true;
11803        }
11804        return onCapturedPointerEvent(event);
11805    }
11806
11807    /**
11808     * Dispatch a generic motion event.
11809     * <p>
11810     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11811     * are delivered to the view under the pointer.  All other generic motion events are
11812     * delivered to the focused view.  Hover events are handled specially and are delivered
11813     * to {@link #onHoverEvent(MotionEvent)}.
11814     * </p>
11815     *
11816     * @param event The motion event to be dispatched.
11817     * @return True if the event was handled by the view, false otherwise.
11818     */
11819    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11820        if (mInputEventConsistencyVerifier != null) {
11821            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11822        }
11823
11824        final int source = event.getSource();
11825        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11826            final int action = event.getAction();
11827            if (action == MotionEvent.ACTION_HOVER_ENTER
11828                    || action == MotionEvent.ACTION_HOVER_MOVE
11829                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11830                if (dispatchHoverEvent(event)) {
11831                    return true;
11832                }
11833            } else if (dispatchGenericPointerEvent(event)) {
11834                return true;
11835            }
11836        } else if (dispatchGenericFocusedEvent(event)) {
11837            return true;
11838        }
11839
11840        if (dispatchGenericMotionEventInternal(event)) {
11841            return true;
11842        }
11843
11844        if (mInputEventConsistencyVerifier != null) {
11845            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11846        }
11847        return false;
11848    }
11849
11850    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11851        //noinspection SimplifiableIfStatement
11852        ListenerInfo li = mListenerInfo;
11853        if (li != null && li.mOnGenericMotionListener != null
11854                && (mViewFlags & ENABLED_MASK) == ENABLED
11855                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11856            return true;
11857        }
11858
11859        if (onGenericMotionEvent(event)) {
11860            return true;
11861        }
11862
11863        final int actionButton = event.getActionButton();
11864        switch (event.getActionMasked()) {
11865            case MotionEvent.ACTION_BUTTON_PRESS:
11866                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11867                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11868                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11869                    if (performContextClick(event.getX(), event.getY())) {
11870                        mInContextButtonPress = true;
11871                        setPressed(true, event.getX(), event.getY());
11872                        removeTapCallback();
11873                        removeLongPressCallback();
11874                        return true;
11875                    }
11876                }
11877                break;
11878
11879            case MotionEvent.ACTION_BUTTON_RELEASE:
11880                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11881                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11882                    mInContextButtonPress = false;
11883                    mIgnoreNextUpEvent = true;
11884                }
11885                break;
11886        }
11887
11888        if (mInputEventConsistencyVerifier != null) {
11889            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11890        }
11891        return false;
11892    }
11893
11894    /**
11895     * Dispatch a hover event.
11896     * <p>
11897     * Do not call this method directly.
11898     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11899     * </p>
11900     *
11901     * @param event The motion event to be dispatched.
11902     * @return True if the event was handled by the view, false otherwise.
11903     */
11904    protected boolean dispatchHoverEvent(MotionEvent event) {
11905        ListenerInfo li = mListenerInfo;
11906        //noinspection SimplifiableIfStatement
11907        if (li != null && li.mOnHoverListener != null
11908                && (mViewFlags & ENABLED_MASK) == ENABLED
11909                && li.mOnHoverListener.onHover(this, event)) {
11910            return true;
11911        }
11912
11913        return onHoverEvent(event);
11914    }
11915
11916    /**
11917     * Returns true if the view has a child to which it has recently sent
11918     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11919     * it does not have a hovered child, then it must be the innermost hovered view.
11920     * @hide
11921     */
11922    protected boolean hasHoveredChild() {
11923        return false;
11924    }
11925
11926    /**
11927     * Dispatch a generic motion event to the view under the first pointer.
11928     * <p>
11929     * Do not call this method directly.
11930     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11931     * </p>
11932     *
11933     * @param event The motion event to be dispatched.
11934     * @return True if the event was handled by the view, false otherwise.
11935     */
11936    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11937        return false;
11938    }
11939
11940    /**
11941     * Dispatch a generic motion event to the currently focused view.
11942     * <p>
11943     * Do not call this method directly.
11944     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11945     * </p>
11946     *
11947     * @param event The motion event to be dispatched.
11948     * @return True if the event was handled by the view, false otherwise.
11949     */
11950    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11951        return false;
11952    }
11953
11954    /**
11955     * Dispatch a pointer event.
11956     * <p>
11957     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11958     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11959     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11960     * and should not be expected to handle other pointing device features.
11961     * </p>
11962     *
11963     * @param event The motion event to be dispatched.
11964     * @return True if the event was handled by the view, false otherwise.
11965     * @hide
11966     */
11967    public final boolean dispatchPointerEvent(MotionEvent event) {
11968        if (event.isTouchEvent()) {
11969            return dispatchTouchEvent(event);
11970        } else {
11971            return dispatchGenericMotionEvent(event);
11972        }
11973    }
11974
11975    /**
11976     * Called when the window containing this view gains or loses window focus.
11977     * ViewGroups should override to route to their children.
11978     *
11979     * @param hasFocus True if the window containing this view now has focus,
11980     *        false otherwise.
11981     */
11982    public void dispatchWindowFocusChanged(boolean hasFocus) {
11983        onWindowFocusChanged(hasFocus);
11984    }
11985
11986    /**
11987     * Called when the window containing this view gains or loses focus.  Note
11988     * that this is separate from view focus: to receive key events, both
11989     * your view and its window must have focus.  If a window is displayed
11990     * on top of yours that takes input focus, then your own window will lose
11991     * focus but the view focus will remain unchanged.
11992     *
11993     * @param hasWindowFocus True if the window containing this view now has
11994     *        focus, false otherwise.
11995     */
11996    public void onWindowFocusChanged(boolean hasWindowFocus) {
11997        InputMethodManager imm = InputMethodManager.peekInstance();
11998        if (!hasWindowFocus) {
11999            if (isPressed()) {
12000                setPressed(false);
12001            }
12002            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12003            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12004                imm.focusOut(this);
12005            }
12006            removeLongPressCallback();
12007            removeTapCallback();
12008            onFocusLost();
12009        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12010            imm.focusIn(this);
12011        }
12012
12013        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
12014
12015        refreshDrawableState();
12016    }
12017
12018    /**
12019     * Returns true if this view is in a window that currently has window focus.
12020     * Note that this is not the same as the view itself having focus.
12021     *
12022     * @return True if this view is in a window that currently has window focus.
12023     */
12024    public boolean hasWindowFocus() {
12025        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
12026    }
12027
12028    /**
12029     * Dispatch a view visibility change down the view hierarchy.
12030     * ViewGroups should override to route to their children.
12031     * @param changedView The view whose visibility changed. Could be 'this' or
12032     * an ancestor view.
12033     * @param visibility The new visibility of changedView: {@link #VISIBLE},
12034     * {@link #INVISIBLE} or {@link #GONE}.
12035     */
12036    protected void dispatchVisibilityChanged(@NonNull View changedView,
12037            @Visibility int visibility) {
12038        onVisibilityChanged(changedView, visibility);
12039    }
12040
12041    /**
12042     * Called when the visibility of the view or an ancestor of the view has
12043     * changed.
12044     *
12045     * @param changedView The view whose visibility changed. May be
12046     *                    {@code this} or an ancestor view.
12047     * @param visibility The new visibility, one of {@link #VISIBLE},
12048     *                   {@link #INVISIBLE} or {@link #GONE}.
12049     */
12050    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
12051    }
12052
12053    /**
12054     * Dispatch a hint about whether this view is displayed. For instance, when
12055     * a View moves out of the screen, it might receives a display hint indicating
12056     * the view is not displayed. Applications should not <em>rely</em> on this hint
12057     * as there is no guarantee that they will receive one.
12058     *
12059     * @param hint A hint about whether or not this view is displayed:
12060     * {@link #VISIBLE} or {@link #INVISIBLE}.
12061     */
12062    public void dispatchDisplayHint(@Visibility int hint) {
12063        onDisplayHint(hint);
12064    }
12065
12066    /**
12067     * Gives this view a hint about whether is displayed or not. For instance, when
12068     * a View moves out of the screen, it might receives a display hint indicating
12069     * the view is not displayed. Applications should not <em>rely</em> on this hint
12070     * as there is no guarantee that they will receive one.
12071     *
12072     * @param hint A hint about whether or not this view is displayed:
12073     * {@link #VISIBLE} or {@link #INVISIBLE}.
12074     */
12075    protected void onDisplayHint(@Visibility int hint) {
12076    }
12077
12078    /**
12079     * Dispatch a window visibility change down the view hierarchy.
12080     * ViewGroups should override to route to their children.
12081     *
12082     * @param visibility The new visibility of the window.
12083     *
12084     * @see #onWindowVisibilityChanged(int)
12085     */
12086    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
12087        onWindowVisibilityChanged(visibility);
12088    }
12089
12090    /**
12091     * Called when the window containing has change its visibility
12092     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
12093     * that this tells you whether or not your window is being made visible
12094     * to the window manager; this does <em>not</em> tell you whether or not
12095     * your window is obscured by other windows on the screen, even if it
12096     * is itself visible.
12097     *
12098     * @param visibility The new visibility of the window.
12099     */
12100    protected void onWindowVisibilityChanged(@Visibility int visibility) {
12101        if (visibility == VISIBLE) {
12102            initialAwakenScrollBars();
12103        }
12104    }
12105
12106    /**
12107     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
12108     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
12109     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
12110     *
12111     * @param isVisible true if this view's visibility to the user is uninterrupted by its
12112     *                  ancestors or by window visibility
12113     * @return true if this view is visible to the user, not counting clipping or overlapping
12114     */
12115    boolean dispatchVisibilityAggregated(boolean isVisible) {
12116        final boolean thisVisible = getVisibility() == VISIBLE;
12117        // If we're not visible but something is telling us we are, ignore it.
12118        if (thisVisible || !isVisible) {
12119            onVisibilityAggregated(isVisible);
12120        }
12121        return thisVisible && isVisible;
12122    }
12123
12124    /**
12125     * Called when the user-visibility of this View is potentially affected by a change
12126     * to this view itself, an ancestor view or the window this view is attached to.
12127     *
12128     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
12129     *                  and this view's window is also visible
12130     */
12131    @CallSuper
12132    public void onVisibilityAggregated(boolean isVisible) {
12133        if (isVisible && mAttachInfo != null) {
12134            initialAwakenScrollBars();
12135        }
12136
12137        final Drawable dr = mBackground;
12138        if (dr != null && isVisible != dr.isVisible()) {
12139            dr.setVisible(isVisible, false);
12140        }
12141        final Drawable hl = mDefaultFocusHighlight;
12142        if (hl != null && isVisible != hl.isVisible()) {
12143            hl.setVisible(isVisible, false);
12144        }
12145        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
12146        if (fg != null && isVisible != fg.isVisible()) {
12147            fg.setVisible(isVisible, false);
12148        }
12149
12150        if (isAutofillable()) {
12151            AutofillManager afm = getAutofillManager();
12152
12153            if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
12154                if (mVisibilityChangeForAutofillHandler != null) {
12155                    mVisibilityChangeForAutofillHandler.removeMessages(0);
12156                }
12157
12158                // If the view is in the background but still part of the hierarchy this is called
12159                // with isVisible=false. Hence visibility==false requires further checks
12160                if (isVisible) {
12161                    afm.notifyViewVisibilityChanged(this, true);
12162                } else {
12163                    if (mVisibilityChangeForAutofillHandler == null) {
12164                        mVisibilityChangeForAutofillHandler =
12165                                new VisibilityChangeForAutofillHandler(afm, this);
12166                    }
12167                    // Let current operation (e.g. removal of the view from the hierarchy)
12168                    // finish before checking state
12169                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
12170                }
12171            }
12172        }
12173    }
12174
12175    /**
12176     * Returns the current visibility of the window this view is attached to
12177     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
12178     *
12179     * @return Returns the current visibility of the view's window.
12180     */
12181    @Visibility
12182    public int getWindowVisibility() {
12183        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
12184    }
12185
12186    /**
12187     * Retrieve the overall visible display size in which the window this view is
12188     * attached to has been positioned in.  This takes into account screen
12189     * decorations above the window, for both cases where the window itself
12190     * is being position inside of them or the window is being placed under
12191     * then and covered insets are used for the window to position its content
12192     * inside.  In effect, this tells you the available area where content can
12193     * be placed and remain visible to users.
12194     *
12195     * <p>This function requires an IPC back to the window manager to retrieve
12196     * the requested information, so should not be used in performance critical
12197     * code like drawing.
12198     *
12199     * @param outRect Filled in with the visible display frame.  If the view
12200     * is not attached to a window, this is simply the raw display size.
12201     */
12202    public void getWindowVisibleDisplayFrame(Rect outRect) {
12203        if (mAttachInfo != null) {
12204            try {
12205                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12206            } catch (RemoteException e) {
12207                return;
12208            }
12209            // XXX This is really broken, and probably all needs to be done
12210            // in the window manager, and we need to know more about whether
12211            // we want the area behind or in front of the IME.
12212            final Rect insets = mAttachInfo.mVisibleInsets;
12213            outRect.left += insets.left;
12214            outRect.top += insets.top;
12215            outRect.right -= insets.right;
12216            outRect.bottom -= insets.bottom;
12217            return;
12218        }
12219        // The view is not attached to a display so we don't have a context.
12220        // Make a best guess about the display size.
12221        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12222        d.getRectSize(outRect);
12223    }
12224
12225    /**
12226     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
12227     * is currently in without any insets.
12228     *
12229     * @hide
12230     */
12231    public void getWindowDisplayFrame(Rect outRect) {
12232        if (mAttachInfo != null) {
12233            try {
12234                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12235            } catch (RemoteException e) {
12236                return;
12237            }
12238            return;
12239        }
12240        // The view is not attached to a display so we don't have a context.
12241        // Make a best guess about the display size.
12242        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12243        d.getRectSize(outRect);
12244    }
12245
12246    /**
12247     * Dispatch a notification about a resource configuration change down
12248     * the view hierarchy.
12249     * ViewGroups should override to route to their children.
12250     *
12251     * @param newConfig The new resource configuration.
12252     *
12253     * @see #onConfigurationChanged(android.content.res.Configuration)
12254     */
12255    public void dispatchConfigurationChanged(Configuration newConfig) {
12256        onConfigurationChanged(newConfig);
12257    }
12258
12259    /**
12260     * Called when the current configuration of the resources being used
12261     * by the application have changed.  You can use this to decide when
12262     * to reload resources that can changed based on orientation and other
12263     * configuration characteristics.  You only need to use this if you are
12264     * not relying on the normal {@link android.app.Activity} mechanism of
12265     * recreating the activity instance upon a configuration change.
12266     *
12267     * @param newConfig The new resource configuration.
12268     */
12269    protected void onConfigurationChanged(Configuration newConfig) {
12270    }
12271
12272    /**
12273     * Private function to aggregate all per-view attributes in to the view
12274     * root.
12275     */
12276    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12277        performCollectViewAttributes(attachInfo, visibility);
12278    }
12279
12280    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12281        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
12282            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
12283                attachInfo.mKeepScreenOn = true;
12284            }
12285            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
12286            ListenerInfo li = mListenerInfo;
12287            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
12288                attachInfo.mHasSystemUiListeners = true;
12289            }
12290        }
12291    }
12292
12293    void needGlobalAttributesUpdate(boolean force) {
12294        final AttachInfo ai = mAttachInfo;
12295        if (ai != null && !ai.mRecomputeGlobalAttributes) {
12296            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
12297                    || ai.mHasSystemUiListeners) {
12298                ai.mRecomputeGlobalAttributes = true;
12299            }
12300        }
12301    }
12302
12303    /**
12304     * Returns whether the device is currently in touch mode.  Touch mode is entered
12305     * once the user begins interacting with the device by touch, and affects various
12306     * things like whether focus is always visible to the user.
12307     *
12308     * @return Whether the device is in touch mode.
12309     */
12310    @ViewDebug.ExportedProperty
12311    public boolean isInTouchMode() {
12312        if (mAttachInfo != null) {
12313            return mAttachInfo.mInTouchMode;
12314        } else {
12315            return ViewRootImpl.isInTouchMode();
12316        }
12317    }
12318
12319    /**
12320     * Returns the context the view is running in, through which it can
12321     * access the current theme, resources, etc.
12322     *
12323     * @return The view's Context.
12324     */
12325    @ViewDebug.CapturedViewProperty
12326    public final Context getContext() {
12327        return mContext;
12328    }
12329
12330    /**
12331     * Handle a key event before it is processed by any input method
12332     * associated with the view hierarchy.  This can be used to intercept
12333     * key events in special situations before the IME consumes them; a
12334     * typical example would be handling the BACK key to update the application's
12335     * UI instead of allowing the IME to see it and close itself.
12336     *
12337     * @param keyCode The value in event.getKeyCode().
12338     * @param event Description of the key event.
12339     * @return If you handled the event, return true. If you want to allow the
12340     *         event to be handled by the next receiver, return false.
12341     */
12342    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
12343        return false;
12344    }
12345
12346    /**
12347     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12348     * KeyEvent.Callback.onKeyDown()}: perform press of the view
12349     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12350     * is released, if the view is enabled and clickable.
12351     * <p>
12352     * Key presses in software keyboards will generally NOT trigger this
12353     * listener, although some may elect to do so in some situations. Do not
12354     * rely on this to catch software key presses.
12355     *
12356     * @param keyCode a key code that represents the button pressed, from
12357     *                {@link android.view.KeyEvent}
12358     * @param event the KeyEvent object that defines the button action
12359     */
12360    public boolean onKeyDown(int keyCode, KeyEvent event) {
12361        if (KeyEvent.isConfirmKey(keyCode)) {
12362            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12363                return true;
12364            }
12365
12366            if (event.getRepeatCount() == 0) {
12367                // Long clickable items don't necessarily have to be clickable.
12368                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12369                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12370                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12371                    // For the purposes of menu anchoring and drawable hotspots,
12372                    // key events are considered to be at the center of the view.
12373                    final float x = getWidth() / 2f;
12374                    final float y = getHeight() / 2f;
12375                    if (clickable) {
12376                        setPressed(true, x, y);
12377                    }
12378                    checkForLongClick(0, x, y);
12379                    return true;
12380                }
12381            }
12382        }
12383
12384        return false;
12385    }
12386
12387    /**
12388     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12389     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12390     * the event).
12391     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12392     * although some may elect to do so in some situations. Do not rely on this to
12393     * catch software key presses.
12394     */
12395    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12396        return false;
12397    }
12398
12399    /**
12400     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12401     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12402     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12403     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12404     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12405     * although some may elect to do so in some situations. Do not rely on this to
12406     * catch software key presses.
12407     *
12408     * @param keyCode A key code that represents the button pressed, from
12409     *                {@link android.view.KeyEvent}.
12410     * @param event   The KeyEvent object that defines the button action.
12411     */
12412    public boolean onKeyUp(int keyCode, KeyEvent event) {
12413        if (KeyEvent.isConfirmKey(keyCode)) {
12414            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12415                return true;
12416            }
12417            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12418                setPressed(false);
12419
12420                if (!mHasPerformedLongPress) {
12421                    // This is a tap, so remove the longpress check
12422                    removeLongPressCallback();
12423                    if (!event.isCanceled()) {
12424                        return performClick();
12425                    }
12426                }
12427            }
12428        }
12429        return false;
12430    }
12431
12432    /**
12433     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12434     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12435     * the event).
12436     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12437     * although some may elect to do so in some situations. Do not rely on this to
12438     * catch software key presses.
12439     *
12440     * @param keyCode     A key code that represents the button pressed, from
12441     *                    {@link android.view.KeyEvent}.
12442     * @param repeatCount The number of times the action was made.
12443     * @param event       The KeyEvent object that defines the button action.
12444     */
12445    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12446        return false;
12447    }
12448
12449    /**
12450     * Called on the focused view when a key shortcut event is not handled.
12451     * Override this method to implement local key shortcuts for the View.
12452     * Key shortcuts can also be implemented by setting the
12453     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12454     *
12455     * @param keyCode The value in event.getKeyCode().
12456     * @param event Description of the key event.
12457     * @return If you handled the event, return true. If you want to allow the
12458     *         event to be handled by the next receiver, return false.
12459     */
12460    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12461        return false;
12462    }
12463
12464    /**
12465     * Check whether the called view is a text editor, in which case it
12466     * would make sense to automatically display a soft input window for
12467     * it.  Subclasses should override this if they implement
12468     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12469     * a call on that method would return a non-null InputConnection, and
12470     * they are really a first-class editor that the user would normally
12471     * start typing on when the go into a window containing your view.
12472     *
12473     * <p>The default implementation always returns false.  This does
12474     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12475     * will not be called or the user can not otherwise perform edits on your
12476     * view; it is just a hint to the system that this is not the primary
12477     * purpose of this view.
12478     *
12479     * @return Returns true if this view is a text editor, else false.
12480     */
12481    public boolean onCheckIsTextEditor() {
12482        return false;
12483    }
12484
12485    /**
12486     * Create a new InputConnection for an InputMethod to interact
12487     * with the view.  The default implementation returns null, since it doesn't
12488     * support input methods.  You can override this to implement such support.
12489     * This is only needed for views that take focus and text input.
12490     *
12491     * <p>When implementing this, you probably also want to implement
12492     * {@link #onCheckIsTextEditor()} to indicate you will return a
12493     * non-null InputConnection.</p>
12494     *
12495     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12496     * object correctly and in its entirety, so that the connected IME can rely
12497     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12498     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12499     * must be filled in with the correct cursor position for IMEs to work correctly
12500     * with your application.</p>
12501     *
12502     * @param outAttrs Fill in with attribute information about the connection.
12503     */
12504    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12505        return null;
12506    }
12507
12508    /**
12509     * Called by the {@link android.view.inputmethod.InputMethodManager}
12510     * when a view who is not the current
12511     * input connection target is trying to make a call on the manager.  The
12512     * default implementation returns false; you can override this to return
12513     * true for certain views if you are performing InputConnection proxying
12514     * to them.
12515     * @param view The View that is making the InputMethodManager call.
12516     * @return Return true to allow the call, false to reject.
12517     */
12518    public boolean checkInputConnectionProxy(View view) {
12519        return false;
12520    }
12521
12522    /**
12523     * Show the context menu for this view. It is not safe to hold on to the
12524     * menu after returning from this method.
12525     *
12526     * You should normally not overload this method. Overload
12527     * {@link #onCreateContextMenu(ContextMenu)} or define an
12528     * {@link OnCreateContextMenuListener} to add items to the context menu.
12529     *
12530     * @param menu The context menu to populate
12531     */
12532    public void createContextMenu(ContextMenu menu) {
12533        ContextMenuInfo menuInfo = getContextMenuInfo();
12534
12535        // Sets the current menu info so all items added to menu will have
12536        // my extra info set.
12537        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12538
12539        onCreateContextMenu(menu);
12540        ListenerInfo li = mListenerInfo;
12541        if (li != null && li.mOnCreateContextMenuListener != null) {
12542            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12543        }
12544
12545        // Clear the extra information so subsequent items that aren't mine don't
12546        // have my extra info.
12547        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12548
12549        if (mParent != null) {
12550            mParent.createContextMenu(menu);
12551        }
12552    }
12553
12554    /**
12555     * Views should implement this if they have extra information to associate
12556     * with the context menu. The return result is supplied as a parameter to
12557     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12558     * callback.
12559     *
12560     * @return Extra information about the item for which the context menu
12561     *         should be shown. This information will vary across different
12562     *         subclasses of View.
12563     */
12564    protected ContextMenuInfo getContextMenuInfo() {
12565        return null;
12566    }
12567
12568    /**
12569     * Views should implement this if the view itself is going to add items to
12570     * the context menu.
12571     *
12572     * @param menu the context menu to populate
12573     */
12574    protected void onCreateContextMenu(ContextMenu menu) {
12575    }
12576
12577    /**
12578     * Implement this method to handle trackball motion events.  The
12579     * <em>relative</em> movement of the trackball since the last event
12580     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12581     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12582     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12583     * they will often be fractional values, representing the more fine-grained
12584     * movement information available from a trackball).
12585     *
12586     * @param event The motion event.
12587     * @return True if the event was handled, false otherwise.
12588     */
12589    public boolean onTrackballEvent(MotionEvent event) {
12590        return false;
12591    }
12592
12593    /**
12594     * Implement this method to handle generic motion events.
12595     * <p>
12596     * Generic motion events describe joystick movements, mouse hovers, track pad
12597     * touches, scroll wheel movements and other input events.  The
12598     * {@link MotionEvent#getSource() source} of the motion event specifies
12599     * the class of input that was received.  Implementations of this method
12600     * must examine the bits in the source before processing the event.
12601     * The following code example shows how this is done.
12602     * </p><p>
12603     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12604     * are delivered to the view under the pointer.  All other generic motion events are
12605     * delivered to the focused view.
12606     * </p>
12607     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12608     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12609     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12610     *             // process the joystick movement...
12611     *             return true;
12612     *         }
12613     *     }
12614     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12615     *         switch (event.getAction()) {
12616     *             case MotionEvent.ACTION_HOVER_MOVE:
12617     *                 // process the mouse hover movement...
12618     *                 return true;
12619     *             case MotionEvent.ACTION_SCROLL:
12620     *                 // process the scroll wheel movement...
12621     *                 return true;
12622     *         }
12623     *     }
12624     *     return super.onGenericMotionEvent(event);
12625     * }</pre>
12626     *
12627     * @param event The generic motion event being processed.
12628     * @return True if the event was handled, false otherwise.
12629     */
12630    public boolean onGenericMotionEvent(MotionEvent event) {
12631        return false;
12632    }
12633
12634    /**
12635     * Implement this method to handle hover events.
12636     * <p>
12637     * This method is called whenever a pointer is hovering into, over, or out of the
12638     * bounds of a view and the view is not currently being touched.
12639     * Hover events are represented as pointer events with action
12640     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12641     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12642     * </p>
12643     * <ul>
12644     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12645     * when the pointer enters the bounds of the view.</li>
12646     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12647     * when the pointer has already entered the bounds of the view and has moved.</li>
12648     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12649     * when the pointer has exited the bounds of the view or when the pointer is
12650     * about to go down due to a button click, tap, or similar user action that
12651     * causes the view to be touched.</li>
12652     * </ul>
12653     * <p>
12654     * The view should implement this method to return true to indicate that it is
12655     * handling the hover event, such as by changing its drawable state.
12656     * </p><p>
12657     * The default implementation calls {@link #setHovered} to update the hovered state
12658     * of the view when a hover enter or hover exit event is received, if the view
12659     * is enabled and is clickable.  The default implementation also sends hover
12660     * accessibility events.
12661     * </p>
12662     *
12663     * @param event The motion event that describes the hover.
12664     * @return True if the view handled the hover event.
12665     *
12666     * @see #isHovered
12667     * @see #setHovered
12668     * @see #onHoverChanged
12669     */
12670    public boolean onHoverEvent(MotionEvent event) {
12671        // The root view may receive hover (or touch) events that are outside the bounds of
12672        // the window.  This code ensures that we only send accessibility events for
12673        // hovers that are actually within the bounds of the root view.
12674        final int action = event.getActionMasked();
12675        if (!mSendingHoverAccessibilityEvents) {
12676            if ((action == MotionEvent.ACTION_HOVER_ENTER
12677                    || action == MotionEvent.ACTION_HOVER_MOVE)
12678                    && !hasHoveredChild()
12679                    && pointInView(event.getX(), event.getY())) {
12680                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12681                mSendingHoverAccessibilityEvents = true;
12682            }
12683        } else {
12684            if (action == MotionEvent.ACTION_HOVER_EXIT
12685                    || (action == MotionEvent.ACTION_MOVE
12686                            && !pointInView(event.getX(), event.getY()))) {
12687                mSendingHoverAccessibilityEvents = false;
12688                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12689            }
12690        }
12691
12692        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12693                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12694                && isOnScrollbar(event.getX(), event.getY())) {
12695            awakenScrollBars();
12696        }
12697
12698        // If we consider ourself hoverable, or if we we're already hovered,
12699        // handle changing state in response to ENTER and EXIT events.
12700        if (isHoverable() || isHovered()) {
12701            switch (action) {
12702                case MotionEvent.ACTION_HOVER_ENTER:
12703                    setHovered(true);
12704                    break;
12705                case MotionEvent.ACTION_HOVER_EXIT:
12706                    setHovered(false);
12707                    break;
12708            }
12709
12710            // Dispatch the event to onGenericMotionEvent before returning true.
12711            // This is to provide compatibility with existing applications that
12712            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12713            // break because of the new default handling for hoverable views
12714            // in onHoverEvent.
12715            // Note that onGenericMotionEvent will be called by default when
12716            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12717            dispatchGenericMotionEventInternal(event);
12718            // The event was already handled by calling setHovered(), so always
12719            // return true.
12720            return true;
12721        }
12722
12723        return false;
12724    }
12725
12726    /**
12727     * Returns true if the view should handle {@link #onHoverEvent}
12728     * by calling {@link #setHovered} to change its hovered state.
12729     *
12730     * @return True if the view is hoverable.
12731     */
12732    private boolean isHoverable() {
12733        final int viewFlags = mViewFlags;
12734        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12735            return false;
12736        }
12737
12738        return (viewFlags & CLICKABLE) == CLICKABLE
12739                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12740                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12741    }
12742
12743    /**
12744     * Returns true if the view is currently hovered.
12745     *
12746     * @return True if the view is currently hovered.
12747     *
12748     * @see #setHovered
12749     * @see #onHoverChanged
12750     */
12751    @ViewDebug.ExportedProperty
12752    public boolean isHovered() {
12753        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12754    }
12755
12756    /**
12757     * Sets whether the view is currently hovered.
12758     * <p>
12759     * Calling this method also changes the drawable state of the view.  This
12760     * enables the view to react to hover by using different drawable resources
12761     * to change its appearance.
12762     * </p><p>
12763     * The {@link #onHoverChanged} method is called when the hovered state changes.
12764     * </p>
12765     *
12766     * @param hovered True if the view is hovered.
12767     *
12768     * @see #isHovered
12769     * @see #onHoverChanged
12770     */
12771    public void setHovered(boolean hovered) {
12772        if (hovered) {
12773            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12774                mPrivateFlags |= PFLAG_HOVERED;
12775                refreshDrawableState();
12776                onHoverChanged(true);
12777            }
12778        } else {
12779            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12780                mPrivateFlags &= ~PFLAG_HOVERED;
12781                refreshDrawableState();
12782                onHoverChanged(false);
12783            }
12784        }
12785    }
12786
12787    /**
12788     * Implement this method to handle hover state changes.
12789     * <p>
12790     * This method is called whenever the hover state changes as a result of a
12791     * call to {@link #setHovered}.
12792     * </p>
12793     *
12794     * @param hovered The current hover state, as returned by {@link #isHovered}.
12795     *
12796     * @see #isHovered
12797     * @see #setHovered
12798     */
12799    public void onHoverChanged(boolean hovered) {
12800    }
12801
12802    /**
12803     * Handles scroll bar dragging by mouse input.
12804     *
12805     * @hide
12806     * @param event The motion event.
12807     *
12808     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12809     */
12810    protected boolean handleScrollBarDragging(MotionEvent event) {
12811        if (mScrollCache == null) {
12812            return false;
12813        }
12814        final float x = event.getX();
12815        final float y = event.getY();
12816        final int action = event.getAction();
12817        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12818                && action != MotionEvent.ACTION_DOWN)
12819                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12820                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12821            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12822            return false;
12823        }
12824
12825        switch (action) {
12826            case MotionEvent.ACTION_MOVE:
12827                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12828                    return false;
12829                }
12830                if (mScrollCache.mScrollBarDraggingState
12831                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12832                    final Rect bounds = mScrollCache.mScrollBarBounds;
12833                    getVerticalScrollBarBounds(bounds, null);
12834                    final int range = computeVerticalScrollRange();
12835                    final int offset = computeVerticalScrollOffset();
12836                    final int extent = computeVerticalScrollExtent();
12837
12838                    final int thumbLength = ScrollBarUtils.getThumbLength(
12839                            bounds.height(), bounds.width(), extent, range);
12840                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12841                            bounds.height(), thumbLength, extent, range, offset);
12842
12843                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12844                    final float maxThumbOffset = bounds.height() - thumbLength;
12845                    final float newThumbOffset =
12846                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12847                    final int height = getHeight();
12848                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12849                            && height > 0 && extent > 0) {
12850                        final int newY = Math.round((range - extent)
12851                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12852                        if (newY != getScrollY()) {
12853                            mScrollCache.mScrollBarDraggingPos = y;
12854                            setScrollY(newY);
12855                        }
12856                    }
12857                    return true;
12858                }
12859                if (mScrollCache.mScrollBarDraggingState
12860                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12861                    final Rect bounds = mScrollCache.mScrollBarBounds;
12862                    getHorizontalScrollBarBounds(bounds, null);
12863                    final int range = computeHorizontalScrollRange();
12864                    final int offset = computeHorizontalScrollOffset();
12865                    final int extent = computeHorizontalScrollExtent();
12866
12867                    final int thumbLength = ScrollBarUtils.getThumbLength(
12868                            bounds.width(), bounds.height(), extent, range);
12869                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12870                            bounds.width(), thumbLength, extent, range, offset);
12871
12872                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12873                    final float maxThumbOffset = bounds.width() - thumbLength;
12874                    final float newThumbOffset =
12875                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12876                    final int width = getWidth();
12877                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12878                            && width > 0 && extent > 0) {
12879                        final int newX = Math.round((range - extent)
12880                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12881                        if (newX != getScrollX()) {
12882                            mScrollCache.mScrollBarDraggingPos = x;
12883                            setScrollX(newX);
12884                        }
12885                    }
12886                    return true;
12887                }
12888            case MotionEvent.ACTION_DOWN:
12889                if (mScrollCache.state == ScrollabilityCache.OFF) {
12890                    return false;
12891                }
12892                if (isOnVerticalScrollbarThumb(x, y)) {
12893                    mScrollCache.mScrollBarDraggingState =
12894                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12895                    mScrollCache.mScrollBarDraggingPos = y;
12896                    return true;
12897                }
12898                if (isOnHorizontalScrollbarThumb(x, y)) {
12899                    mScrollCache.mScrollBarDraggingState =
12900                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12901                    mScrollCache.mScrollBarDraggingPos = x;
12902                    return true;
12903                }
12904        }
12905        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12906        return false;
12907    }
12908
12909    /**
12910     * Implement this method to handle touch screen motion events.
12911     * <p>
12912     * If this method is used to detect click actions, it is recommended that
12913     * the actions be performed by implementing and calling
12914     * {@link #performClick()}. This will ensure consistent system behavior,
12915     * including:
12916     * <ul>
12917     * <li>obeying click sound preferences
12918     * <li>dispatching OnClickListener calls
12919     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12920     * accessibility features are enabled
12921     * </ul>
12922     *
12923     * @param event The motion event.
12924     * @return True if the event was handled, false otherwise.
12925     */
12926    public boolean onTouchEvent(MotionEvent event) {
12927        final float x = event.getX();
12928        final float y = event.getY();
12929        final int viewFlags = mViewFlags;
12930        final int action = event.getAction();
12931
12932        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12933                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12934                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12935
12936        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12937            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12938                setPressed(false);
12939            }
12940            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12941            // A disabled view that is clickable still consumes the touch
12942            // events, it just doesn't respond to them.
12943            return clickable;
12944        }
12945        if (mTouchDelegate != null) {
12946            if (mTouchDelegate.onTouchEvent(event)) {
12947                return true;
12948            }
12949        }
12950
12951        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12952            switch (action) {
12953                case MotionEvent.ACTION_UP:
12954                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12955                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12956                        handleTooltipUp();
12957                    }
12958                    if (!clickable) {
12959                        removeTapCallback();
12960                        removeLongPressCallback();
12961                        mInContextButtonPress = false;
12962                        mHasPerformedLongPress = false;
12963                        mIgnoreNextUpEvent = false;
12964                        break;
12965                    }
12966                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12967                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12968                        // take focus if we don't have it already and we should in
12969                        // touch mode.
12970                        boolean focusTaken = false;
12971                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12972                            focusTaken = requestFocus();
12973                        }
12974
12975                        if (prepressed) {
12976                            // The button is being released before we actually
12977                            // showed it as pressed.  Make it show the pressed
12978                            // state now (before scheduling the click) to ensure
12979                            // the user sees it.
12980                            setPressed(true, x, y);
12981                        }
12982
12983                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12984                            // This is a tap, so remove the longpress check
12985                            removeLongPressCallback();
12986
12987                            // Only perform take click actions if we were in the pressed state
12988                            if (!focusTaken) {
12989                                // Use a Runnable and post this rather than calling
12990                                // performClick directly. This lets other visual state
12991                                // of the view update before click actions start.
12992                                if (mPerformClick == null) {
12993                                    mPerformClick = new PerformClick();
12994                                }
12995                                if (!post(mPerformClick)) {
12996                                    performClick();
12997                                }
12998                            }
12999                        }
13000
13001                        if (mUnsetPressedState == null) {
13002                            mUnsetPressedState = new UnsetPressedState();
13003                        }
13004
13005                        if (prepressed) {
13006                            postDelayed(mUnsetPressedState,
13007                                    ViewConfiguration.getPressedStateDuration());
13008                        } else if (!post(mUnsetPressedState)) {
13009                            // If the post failed, unpress right now
13010                            mUnsetPressedState.run();
13011                        }
13012
13013                        removeTapCallback();
13014                    }
13015                    mIgnoreNextUpEvent = false;
13016                    break;
13017
13018                case MotionEvent.ACTION_DOWN:
13019                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
13020                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
13021                    }
13022                    mHasPerformedLongPress = false;
13023
13024                    if (!clickable) {
13025                        checkForLongClick(0, x, y);
13026                        break;
13027                    }
13028
13029                    if (performButtonActionOnTouchDown(event)) {
13030                        break;
13031                    }
13032
13033                    // Walk up the hierarchy to determine if we're inside a scrolling container.
13034                    boolean isInScrollingContainer = isInScrollingContainer();
13035
13036                    // For views inside a scrolling container, delay the pressed feedback for
13037                    // a short period in case this is a scroll.
13038                    if (isInScrollingContainer) {
13039                        mPrivateFlags |= PFLAG_PREPRESSED;
13040                        if (mPendingCheckForTap == null) {
13041                            mPendingCheckForTap = new CheckForTap();
13042                        }
13043                        mPendingCheckForTap.x = event.getX();
13044                        mPendingCheckForTap.y = event.getY();
13045                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
13046                    } else {
13047                        // Not inside a scrolling container, so show the feedback right away
13048                        setPressed(true, x, y);
13049                        checkForLongClick(0, x, y);
13050                    }
13051                    break;
13052
13053                case MotionEvent.ACTION_CANCEL:
13054                    if (clickable) {
13055                        setPressed(false);
13056                    }
13057                    removeTapCallback();
13058                    removeLongPressCallback();
13059                    mInContextButtonPress = false;
13060                    mHasPerformedLongPress = false;
13061                    mIgnoreNextUpEvent = false;
13062                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13063                    break;
13064
13065                case MotionEvent.ACTION_MOVE:
13066                    if (clickable) {
13067                        drawableHotspotChanged(x, y);
13068                    }
13069
13070                    // Be lenient about moving outside of buttons
13071                    if (!pointInView(x, y, mTouchSlop)) {
13072                        // Outside button
13073                        // Remove any future long press/tap checks
13074                        removeTapCallback();
13075                        removeLongPressCallback();
13076                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
13077                            setPressed(false);
13078                        }
13079                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13080                    }
13081                    break;
13082            }
13083
13084            return true;
13085        }
13086
13087        return false;
13088    }
13089
13090    /**
13091     * @hide
13092     */
13093    public boolean isInScrollingContainer() {
13094        ViewParent p = getParent();
13095        while (p != null && p instanceof ViewGroup) {
13096            if (((ViewGroup) p).shouldDelayChildPressedState()) {
13097                return true;
13098            }
13099            p = p.getParent();
13100        }
13101        return false;
13102    }
13103
13104    /**
13105     * Remove the longpress detection timer.
13106     */
13107    private void removeLongPressCallback() {
13108        if (mPendingCheckForLongPress != null) {
13109            removeCallbacks(mPendingCheckForLongPress);
13110        }
13111    }
13112
13113    /**
13114     * Remove the pending click action
13115     */
13116    private void removePerformClickCallback() {
13117        if (mPerformClick != null) {
13118            removeCallbacks(mPerformClick);
13119        }
13120    }
13121
13122    /**
13123     * Remove the prepress detection timer.
13124     */
13125    private void removeUnsetPressCallback() {
13126        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
13127            setPressed(false);
13128            removeCallbacks(mUnsetPressedState);
13129        }
13130    }
13131
13132    /**
13133     * Remove the tap detection timer.
13134     */
13135    private void removeTapCallback() {
13136        if (mPendingCheckForTap != null) {
13137            mPrivateFlags &= ~PFLAG_PREPRESSED;
13138            removeCallbacks(mPendingCheckForTap);
13139        }
13140    }
13141
13142    /**
13143     * Cancels a pending long press.  Your subclass can use this if you
13144     * want the context menu to come up if the user presses and holds
13145     * at the same place, but you don't want it to come up if they press
13146     * and then move around enough to cause scrolling.
13147     */
13148    public void cancelLongPress() {
13149        removeLongPressCallback();
13150
13151        /*
13152         * The prepressed state handled by the tap callback is a display
13153         * construct, but the tap callback will post a long press callback
13154         * less its own timeout. Remove it here.
13155         */
13156        removeTapCallback();
13157    }
13158
13159    /**
13160     * Remove the pending callback for sending a
13161     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
13162     */
13163    private void removeSendViewScrolledAccessibilityEventCallback() {
13164        if (mSendViewScrolledAccessibilityEvent != null) {
13165            removeCallbacks(mSendViewScrolledAccessibilityEvent);
13166            mSendViewScrolledAccessibilityEvent.mIsPending = false;
13167        }
13168    }
13169
13170    /**
13171     * Sets the TouchDelegate for this View.
13172     */
13173    public void setTouchDelegate(TouchDelegate delegate) {
13174        mTouchDelegate = delegate;
13175    }
13176
13177    /**
13178     * Gets the TouchDelegate for this View.
13179     */
13180    public TouchDelegate getTouchDelegate() {
13181        return mTouchDelegate;
13182    }
13183
13184    /**
13185     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
13186     *
13187     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
13188     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
13189     * available. This method should only be called for touch events.
13190     *
13191     * <p class="note">This api is not intended for most applications. Buffered dispatch
13192     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
13193     * streams will not improve your input latency. Side effects include: increased latency,
13194     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13195     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13196     * you.</p>
13197     */
13198    public final void requestUnbufferedDispatch(MotionEvent event) {
13199        final int action = event.getAction();
13200        if (mAttachInfo == null
13201                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13202                || !event.isTouchEvent()) {
13203            return;
13204        }
13205        mAttachInfo.mUnbufferedDispatchRequested = true;
13206    }
13207
13208    /**
13209     * Set flags controlling behavior of this view.
13210     *
13211     * @param flags Constant indicating the value which should be set
13212     * @param mask Constant indicating the bit range that should be changed
13213     */
13214    void setFlags(int flags, int mask) {
13215        final boolean accessibilityEnabled =
13216                AccessibilityManager.getInstance(mContext).isEnabled();
13217        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
13218
13219        int old = mViewFlags;
13220        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
13221
13222        int changed = mViewFlags ^ old;
13223        if (changed == 0) {
13224            return;
13225        }
13226        int privateFlags = mPrivateFlags;
13227
13228        // If focusable is auto, update the FOCUSABLE bit.
13229        int focusableChangedByAuto = 0;
13230        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
13231                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
13232            // Heuristic only takes into account whether view is clickable.
13233            final int newFocus;
13234            if ((mViewFlags & CLICKABLE) != 0) {
13235                newFocus = FOCUSABLE;
13236            } else {
13237                newFocus = NOT_FOCUSABLE;
13238            }
13239            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
13240            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
13241            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
13242        }
13243
13244        /* Check if the FOCUSABLE bit has changed */
13245        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
13246            if (((old & FOCUSABLE) == FOCUSABLE)
13247                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
13248                /* Give up focus if we are no longer focusable */
13249                clearFocus();
13250            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
13251                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
13252                /*
13253                 * Tell the view system that we are now available to take focus
13254                 * if no one else already has it.
13255                 */
13256                if (mParent != null) {
13257                    ViewRootImpl viewRootImpl = getViewRootImpl();
13258                    if (!sAutoFocusableOffUIThreadWontNotifyParents
13259                            || focusableChangedByAuto == 0
13260                            || viewRootImpl == null
13261                            || viewRootImpl.mThread == Thread.currentThread()) {
13262                        mParent.focusableViewAvailable(this);
13263                    }
13264                }
13265            }
13266        }
13267
13268        final int newVisibility = flags & VISIBILITY_MASK;
13269        if (newVisibility == VISIBLE) {
13270            if ((changed & VISIBILITY_MASK) != 0) {
13271                /*
13272                 * If this view is becoming visible, invalidate it in case it changed while
13273                 * it was not visible. Marking it drawn ensures that the invalidation will
13274                 * go through.
13275                 */
13276                mPrivateFlags |= PFLAG_DRAWN;
13277                invalidate(true);
13278
13279                needGlobalAttributesUpdate(true);
13280
13281                // a view becoming visible is worth notifying the parent
13282                // about in case nothing has focus.  even if this specific view
13283                // isn't focusable, it may contain something that is, so let
13284                // the root view try to give this focus if nothing else does.
13285                if ((mParent != null)) {
13286                    mParent.focusableViewAvailable(this);
13287                }
13288            }
13289        }
13290
13291        /* Check if the GONE bit has changed */
13292        if ((changed & GONE) != 0) {
13293            needGlobalAttributesUpdate(false);
13294            requestLayout();
13295
13296            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
13297                if (hasFocus()) clearFocus();
13298                clearAccessibilityFocus();
13299                destroyDrawingCache();
13300                if (mParent instanceof View) {
13301                    // GONE views noop invalidation, so invalidate the parent
13302                    ((View) mParent).invalidate(true);
13303                }
13304                // Mark the view drawn to ensure that it gets invalidated properly the next
13305                // time it is visible and gets invalidated
13306                mPrivateFlags |= PFLAG_DRAWN;
13307            }
13308            if (mAttachInfo != null) {
13309                mAttachInfo.mViewVisibilityChanged = true;
13310            }
13311        }
13312
13313        /* Check if the VISIBLE bit has changed */
13314        if ((changed & INVISIBLE) != 0) {
13315            needGlobalAttributesUpdate(false);
13316            /*
13317             * If this view is becoming invisible, set the DRAWN flag so that
13318             * the next invalidate() will not be skipped.
13319             */
13320            mPrivateFlags |= PFLAG_DRAWN;
13321
13322            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
13323                // root view becoming invisible shouldn't clear focus and accessibility focus
13324                if (getRootView() != this) {
13325                    if (hasFocus()) clearFocus();
13326                    clearAccessibilityFocus();
13327                }
13328            }
13329            if (mAttachInfo != null) {
13330                mAttachInfo.mViewVisibilityChanged = true;
13331            }
13332        }
13333
13334        if ((changed & VISIBILITY_MASK) != 0) {
13335            // If the view is invisible, cleanup its display list to free up resources
13336            if (newVisibility != VISIBLE && mAttachInfo != null) {
13337                cleanupDraw();
13338            }
13339
13340            if (mParent instanceof ViewGroup) {
13341                ((ViewGroup) mParent).onChildVisibilityChanged(this,
13342                        (changed & VISIBILITY_MASK), newVisibility);
13343                ((View) mParent).invalidate(true);
13344            } else if (mParent != null) {
13345                mParent.invalidateChild(this, null);
13346            }
13347
13348            if (mAttachInfo != null) {
13349                dispatchVisibilityChanged(this, newVisibility);
13350
13351                // Aggregated visibility changes are dispatched to attached views
13352                // in visible windows where the parent is currently shown/drawn
13353                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13354                // discounting clipping or overlapping. This makes it a good place
13355                // to change animation states.
13356                if (mParent != null && getWindowVisibility() == VISIBLE &&
13357                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13358                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
13359                }
13360                notifySubtreeAccessibilityStateChangedIfNeeded();
13361            }
13362        }
13363
13364        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13365            destroyDrawingCache();
13366        }
13367
13368        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13369            destroyDrawingCache();
13370            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13371            invalidateParentCaches();
13372        }
13373
13374        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13375            destroyDrawingCache();
13376            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13377        }
13378
13379        if ((changed & DRAW_MASK) != 0) {
13380            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13381                if (mBackground != null
13382                        || mDefaultFocusHighlight != null
13383                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13384                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13385                } else {
13386                    mPrivateFlags |= PFLAG_SKIP_DRAW;
13387                }
13388            } else {
13389                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13390            }
13391            requestLayout();
13392            invalidate(true);
13393        }
13394
13395        if ((changed & KEEP_SCREEN_ON) != 0) {
13396            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13397                mParent.recomputeViewAttributes(this);
13398            }
13399        }
13400
13401        if (accessibilityEnabled) {
13402            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13403                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13404                    || (changed & CONTEXT_CLICKABLE) != 0) {
13405                if (oldIncludeForAccessibility != includeForAccessibility()) {
13406                    notifySubtreeAccessibilityStateChangedIfNeeded();
13407                } else {
13408                    notifyViewAccessibilityStateChangedIfNeeded(
13409                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13410                }
13411            } else if ((changed & ENABLED_MASK) != 0) {
13412                notifyViewAccessibilityStateChangedIfNeeded(
13413                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13414            }
13415        }
13416    }
13417
13418    /**
13419     * Change the view's z order in the tree, so it's on top of other sibling
13420     * views. This ordering change may affect layout, if the parent container
13421     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13422     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13423     * method should be followed by calls to {@link #requestLayout()} and
13424     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13425     * with the new child ordering.
13426     *
13427     * @see ViewGroup#bringChildToFront(View)
13428     */
13429    public void bringToFront() {
13430        if (mParent != null) {
13431            mParent.bringChildToFront(this);
13432        }
13433    }
13434
13435    /**
13436     * This is called in response to an internal scroll in this view (i.e., the
13437     * view scrolled its own contents). This is typically as a result of
13438     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13439     * called.
13440     *
13441     * @param l Current horizontal scroll origin.
13442     * @param t Current vertical scroll origin.
13443     * @param oldl Previous horizontal scroll origin.
13444     * @param oldt Previous vertical scroll origin.
13445     */
13446    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13447        notifySubtreeAccessibilityStateChangedIfNeeded();
13448
13449        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13450            postSendViewScrolledAccessibilityEventCallback();
13451        }
13452
13453        mBackgroundSizeChanged = true;
13454        mDefaultFocusHighlightSizeChanged = true;
13455        if (mForegroundInfo != null) {
13456            mForegroundInfo.mBoundsChanged = true;
13457        }
13458
13459        final AttachInfo ai = mAttachInfo;
13460        if (ai != null) {
13461            ai.mViewScrollChanged = true;
13462        }
13463
13464        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13465            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13466        }
13467    }
13468
13469    /**
13470     * Interface definition for a callback to be invoked when the scroll
13471     * X or Y positions of a view change.
13472     * <p>
13473     * <b>Note:</b> Some views handle scrolling independently from View and may
13474     * have their own separate listeners for scroll-type events. For example,
13475     * {@link android.widget.ListView ListView} allows clients to register an
13476     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13477     * to listen for changes in list scroll position.
13478     *
13479     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13480     */
13481    public interface OnScrollChangeListener {
13482        /**
13483         * Called when the scroll position of a view changes.
13484         *
13485         * @param v The view whose scroll position has changed.
13486         * @param scrollX Current horizontal scroll origin.
13487         * @param scrollY Current vertical scroll origin.
13488         * @param oldScrollX Previous horizontal scroll origin.
13489         * @param oldScrollY Previous vertical scroll origin.
13490         */
13491        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13492    }
13493
13494    /**
13495     * Interface definition for a callback to be invoked when the layout bounds of a view
13496     * changes due to layout processing.
13497     */
13498    public interface OnLayoutChangeListener {
13499        /**
13500         * Called when the layout bounds of a view changes due to layout processing.
13501         *
13502         * @param v The view whose bounds have changed.
13503         * @param left The new value of the view's left property.
13504         * @param top The new value of the view's top property.
13505         * @param right The new value of the view's right property.
13506         * @param bottom The new value of the view's bottom property.
13507         * @param oldLeft The previous value of the view's left property.
13508         * @param oldTop The previous value of the view's top property.
13509         * @param oldRight The previous value of the view's right property.
13510         * @param oldBottom The previous value of the view's bottom property.
13511         */
13512        void onLayoutChange(View v, int left, int top, int right, int bottom,
13513            int oldLeft, int oldTop, int oldRight, int oldBottom);
13514    }
13515
13516    /**
13517     * This is called during layout when the size of this view has changed. If
13518     * you were just added to the view hierarchy, you're called with the old
13519     * values of 0.
13520     *
13521     * @param w Current width of this view.
13522     * @param h Current height of this view.
13523     * @param oldw Old width of this view.
13524     * @param oldh Old height of this view.
13525     */
13526    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13527    }
13528
13529    /**
13530     * Called by draw to draw the child views. This may be overridden
13531     * by derived classes to gain control just before its children are drawn
13532     * (but after its own view has been drawn).
13533     * @param canvas the canvas on which to draw the view
13534     */
13535    protected void dispatchDraw(Canvas canvas) {
13536
13537    }
13538
13539    /**
13540     * Gets the parent of this view. Note that the parent is a
13541     * ViewParent and not necessarily a View.
13542     *
13543     * @return Parent of this view.
13544     */
13545    public final ViewParent getParent() {
13546        return mParent;
13547    }
13548
13549    /**
13550     * Set the horizontal scrolled position of your view. This will cause a call to
13551     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13552     * invalidated.
13553     * @param value the x position to scroll to
13554     */
13555    public void setScrollX(int value) {
13556        scrollTo(value, mScrollY);
13557    }
13558
13559    /**
13560     * Set the vertical scrolled position of your view. This will cause a call to
13561     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13562     * invalidated.
13563     * @param value the y position to scroll to
13564     */
13565    public void setScrollY(int value) {
13566        scrollTo(mScrollX, value);
13567    }
13568
13569    /**
13570     * Return the scrolled left position of this view. This is the left edge of
13571     * the displayed part of your view. You do not need to draw any pixels
13572     * farther left, since those are outside of the frame of your view on
13573     * screen.
13574     *
13575     * @return The left edge of the displayed part of your view, in pixels.
13576     */
13577    public final int getScrollX() {
13578        return mScrollX;
13579    }
13580
13581    /**
13582     * Return the scrolled top position of this view. This is the top edge of
13583     * the displayed part of your view. You do not need to draw any pixels above
13584     * it, since those are outside of the frame of your view on screen.
13585     *
13586     * @return The top edge of the displayed part of your view, in pixels.
13587     */
13588    public final int getScrollY() {
13589        return mScrollY;
13590    }
13591
13592    /**
13593     * Return the width of the your view.
13594     *
13595     * @return The width of your view, in pixels.
13596     */
13597    @ViewDebug.ExportedProperty(category = "layout")
13598    public final int getWidth() {
13599        return mRight - mLeft;
13600    }
13601
13602    /**
13603     * Return the height of your view.
13604     *
13605     * @return The height of your view, in pixels.
13606     */
13607    @ViewDebug.ExportedProperty(category = "layout")
13608    public final int getHeight() {
13609        return mBottom - mTop;
13610    }
13611
13612    /**
13613     * Return the visible drawing bounds of your view. Fills in the output
13614     * rectangle with the values from getScrollX(), getScrollY(),
13615     * getWidth(), and getHeight(). These bounds do not account for any
13616     * transformation properties currently set on the view, such as
13617     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13618     *
13619     * @param outRect The (scrolled) drawing bounds of the view.
13620     */
13621    public void getDrawingRect(Rect outRect) {
13622        outRect.left = mScrollX;
13623        outRect.top = mScrollY;
13624        outRect.right = mScrollX + (mRight - mLeft);
13625        outRect.bottom = mScrollY + (mBottom - mTop);
13626    }
13627
13628    /**
13629     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13630     * raw width component (that is the result is masked by
13631     * {@link #MEASURED_SIZE_MASK}).
13632     *
13633     * @return The raw measured width of this view.
13634     */
13635    public final int getMeasuredWidth() {
13636        return mMeasuredWidth & MEASURED_SIZE_MASK;
13637    }
13638
13639    /**
13640     * Return the full width measurement information for this view as computed
13641     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13642     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13643     * This should be used during measurement and layout calculations only. Use
13644     * {@link #getWidth()} to see how wide a view is after layout.
13645     *
13646     * @return The measured width of this view as a bit mask.
13647     */
13648    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13649            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13650                    name = "MEASURED_STATE_TOO_SMALL"),
13651    })
13652    public final int getMeasuredWidthAndState() {
13653        return mMeasuredWidth;
13654    }
13655
13656    /**
13657     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13658     * raw height component (that is the result is masked by
13659     * {@link #MEASURED_SIZE_MASK}).
13660     *
13661     * @return The raw measured height of this view.
13662     */
13663    public final int getMeasuredHeight() {
13664        return mMeasuredHeight & MEASURED_SIZE_MASK;
13665    }
13666
13667    /**
13668     * Return the full height measurement information for this view as computed
13669     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13670     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13671     * This should be used during measurement and layout calculations only. Use
13672     * {@link #getHeight()} to see how wide a view is after layout.
13673     *
13674     * @return The measured height of this view as a bit mask.
13675     */
13676    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13677            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13678                    name = "MEASURED_STATE_TOO_SMALL"),
13679    })
13680    public final int getMeasuredHeightAndState() {
13681        return mMeasuredHeight;
13682    }
13683
13684    /**
13685     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13686     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13687     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13688     * and the height component is at the shifted bits
13689     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13690     */
13691    public final int getMeasuredState() {
13692        return (mMeasuredWidth&MEASURED_STATE_MASK)
13693                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13694                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13695    }
13696
13697    /**
13698     * The transform matrix of this view, which is calculated based on the current
13699     * rotation, scale, and pivot properties.
13700     *
13701     * @see #getRotation()
13702     * @see #getScaleX()
13703     * @see #getScaleY()
13704     * @see #getPivotX()
13705     * @see #getPivotY()
13706     * @return The current transform matrix for the view
13707     */
13708    public Matrix getMatrix() {
13709        ensureTransformationInfo();
13710        final Matrix matrix = mTransformationInfo.mMatrix;
13711        mRenderNode.getMatrix(matrix);
13712        return matrix;
13713    }
13714
13715    /**
13716     * Returns true if the transform matrix is the identity matrix.
13717     * Recomputes the matrix if necessary.
13718     *
13719     * @return True if the transform matrix is the identity matrix, false otherwise.
13720     */
13721    final boolean hasIdentityMatrix() {
13722        return mRenderNode.hasIdentityMatrix();
13723    }
13724
13725    void ensureTransformationInfo() {
13726        if (mTransformationInfo == null) {
13727            mTransformationInfo = new TransformationInfo();
13728        }
13729    }
13730
13731    /**
13732     * Utility method to retrieve the inverse of the current mMatrix property.
13733     * We cache the matrix to avoid recalculating it when transform properties
13734     * have not changed.
13735     *
13736     * @return The inverse of the current matrix of this view.
13737     * @hide
13738     */
13739    public final Matrix getInverseMatrix() {
13740        ensureTransformationInfo();
13741        if (mTransformationInfo.mInverseMatrix == null) {
13742            mTransformationInfo.mInverseMatrix = new Matrix();
13743        }
13744        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13745        mRenderNode.getInverseMatrix(matrix);
13746        return matrix;
13747    }
13748
13749    /**
13750     * Gets the distance along the Z axis from the camera to this view.
13751     *
13752     * @see #setCameraDistance(float)
13753     *
13754     * @return The distance along the Z axis.
13755     */
13756    public float getCameraDistance() {
13757        final float dpi = mResources.getDisplayMetrics().densityDpi;
13758        return -(mRenderNode.getCameraDistance() * dpi);
13759    }
13760
13761    /**
13762     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13763     * views are drawn) from the camera to this view. The camera's distance
13764     * affects 3D transformations, for instance rotations around the X and Y
13765     * axis. If the rotationX or rotationY properties are changed and this view is
13766     * large (more than half the size of the screen), it is recommended to always
13767     * use a camera distance that's greater than the height (X axis rotation) or
13768     * the width (Y axis rotation) of this view.</p>
13769     *
13770     * <p>The distance of the camera from the view plane can have an affect on the
13771     * perspective distortion of the view when it is rotated around the x or y axis.
13772     * For example, a large distance will result in a large viewing angle, and there
13773     * will not be much perspective distortion of the view as it rotates. A short
13774     * distance may cause much more perspective distortion upon rotation, and can
13775     * also result in some drawing artifacts if the rotated view ends up partially
13776     * behind the camera (which is why the recommendation is to use a distance at
13777     * least as far as the size of the view, if the view is to be rotated.)</p>
13778     *
13779     * <p>The distance is expressed in "depth pixels." The default distance depends
13780     * on the screen density. For instance, on a medium density display, the
13781     * default distance is 1280. On a high density display, the default distance
13782     * is 1920.</p>
13783     *
13784     * <p>If you want to specify a distance that leads to visually consistent
13785     * results across various densities, use the following formula:</p>
13786     * <pre>
13787     * float scale = context.getResources().getDisplayMetrics().density;
13788     * view.setCameraDistance(distance * scale);
13789     * </pre>
13790     *
13791     * <p>The density scale factor of a high density display is 1.5,
13792     * and 1920 = 1280 * 1.5.</p>
13793     *
13794     * @param distance The distance in "depth pixels", if negative the opposite
13795     *        value is used
13796     *
13797     * @see #setRotationX(float)
13798     * @see #setRotationY(float)
13799     */
13800    public void setCameraDistance(float distance) {
13801        final float dpi = mResources.getDisplayMetrics().densityDpi;
13802
13803        invalidateViewProperty(true, false);
13804        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13805        invalidateViewProperty(false, false);
13806
13807        invalidateParentIfNeededAndWasQuickRejected();
13808    }
13809
13810    /**
13811     * The degrees that the view is rotated around the pivot point.
13812     *
13813     * @see #setRotation(float)
13814     * @see #getPivotX()
13815     * @see #getPivotY()
13816     *
13817     * @return The degrees of rotation.
13818     */
13819    @ViewDebug.ExportedProperty(category = "drawing")
13820    public float getRotation() {
13821        return mRenderNode.getRotation();
13822    }
13823
13824    /**
13825     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13826     * result in clockwise rotation.
13827     *
13828     * @param rotation The degrees of rotation.
13829     *
13830     * @see #getRotation()
13831     * @see #getPivotX()
13832     * @see #getPivotY()
13833     * @see #setRotationX(float)
13834     * @see #setRotationY(float)
13835     *
13836     * @attr ref android.R.styleable#View_rotation
13837     */
13838    public void setRotation(float rotation) {
13839        if (rotation != getRotation()) {
13840            // Double-invalidation is necessary to capture view's old and new areas
13841            invalidateViewProperty(true, false);
13842            mRenderNode.setRotation(rotation);
13843            invalidateViewProperty(false, true);
13844
13845            invalidateParentIfNeededAndWasQuickRejected();
13846            notifySubtreeAccessibilityStateChangedIfNeeded();
13847        }
13848    }
13849
13850    /**
13851     * The degrees that the view is rotated around the vertical axis through the pivot point.
13852     *
13853     * @see #getPivotX()
13854     * @see #getPivotY()
13855     * @see #setRotationY(float)
13856     *
13857     * @return The degrees of Y rotation.
13858     */
13859    @ViewDebug.ExportedProperty(category = "drawing")
13860    public float getRotationY() {
13861        return mRenderNode.getRotationY();
13862    }
13863
13864    /**
13865     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13866     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13867     * down the y axis.
13868     *
13869     * When rotating large views, it is recommended to adjust the camera distance
13870     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13871     *
13872     * @param rotationY The degrees of Y rotation.
13873     *
13874     * @see #getRotationY()
13875     * @see #getPivotX()
13876     * @see #getPivotY()
13877     * @see #setRotation(float)
13878     * @see #setRotationX(float)
13879     * @see #setCameraDistance(float)
13880     *
13881     * @attr ref android.R.styleable#View_rotationY
13882     */
13883    public void setRotationY(float rotationY) {
13884        if (rotationY != getRotationY()) {
13885            invalidateViewProperty(true, false);
13886            mRenderNode.setRotationY(rotationY);
13887            invalidateViewProperty(false, true);
13888
13889            invalidateParentIfNeededAndWasQuickRejected();
13890            notifySubtreeAccessibilityStateChangedIfNeeded();
13891        }
13892    }
13893
13894    /**
13895     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13896     *
13897     * @see #getPivotX()
13898     * @see #getPivotY()
13899     * @see #setRotationX(float)
13900     *
13901     * @return The degrees of X rotation.
13902     */
13903    @ViewDebug.ExportedProperty(category = "drawing")
13904    public float getRotationX() {
13905        return mRenderNode.getRotationX();
13906    }
13907
13908    /**
13909     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13910     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13911     * x axis.
13912     *
13913     * When rotating large views, it is recommended to adjust the camera distance
13914     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13915     *
13916     * @param rotationX The degrees of X rotation.
13917     *
13918     * @see #getRotationX()
13919     * @see #getPivotX()
13920     * @see #getPivotY()
13921     * @see #setRotation(float)
13922     * @see #setRotationY(float)
13923     * @see #setCameraDistance(float)
13924     *
13925     * @attr ref android.R.styleable#View_rotationX
13926     */
13927    public void setRotationX(float rotationX) {
13928        if (rotationX != getRotationX()) {
13929            invalidateViewProperty(true, false);
13930            mRenderNode.setRotationX(rotationX);
13931            invalidateViewProperty(false, true);
13932
13933            invalidateParentIfNeededAndWasQuickRejected();
13934            notifySubtreeAccessibilityStateChangedIfNeeded();
13935        }
13936    }
13937
13938    /**
13939     * The amount that the view is scaled in x around the pivot point, as a proportion of
13940     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13941     *
13942     * <p>By default, this is 1.0f.
13943     *
13944     * @see #getPivotX()
13945     * @see #getPivotY()
13946     * @return The scaling factor.
13947     */
13948    @ViewDebug.ExportedProperty(category = "drawing")
13949    public float getScaleX() {
13950        return mRenderNode.getScaleX();
13951    }
13952
13953    /**
13954     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13955     * the view's unscaled width. A value of 1 means that no scaling is applied.
13956     *
13957     * @param scaleX The scaling factor.
13958     * @see #getPivotX()
13959     * @see #getPivotY()
13960     *
13961     * @attr ref android.R.styleable#View_scaleX
13962     */
13963    public void setScaleX(float scaleX) {
13964        if (scaleX != getScaleX()) {
13965            invalidateViewProperty(true, false);
13966            mRenderNode.setScaleX(scaleX);
13967            invalidateViewProperty(false, true);
13968
13969            invalidateParentIfNeededAndWasQuickRejected();
13970            notifySubtreeAccessibilityStateChangedIfNeeded();
13971        }
13972    }
13973
13974    /**
13975     * The amount that the view is scaled in y around the pivot point, as a proportion of
13976     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13977     *
13978     * <p>By default, this is 1.0f.
13979     *
13980     * @see #getPivotX()
13981     * @see #getPivotY()
13982     * @return The scaling factor.
13983     */
13984    @ViewDebug.ExportedProperty(category = "drawing")
13985    public float getScaleY() {
13986        return mRenderNode.getScaleY();
13987    }
13988
13989    /**
13990     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13991     * the view's unscaled width. A value of 1 means that no scaling is applied.
13992     *
13993     * @param scaleY The scaling factor.
13994     * @see #getPivotX()
13995     * @see #getPivotY()
13996     *
13997     * @attr ref android.R.styleable#View_scaleY
13998     */
13999    public void setScaleY(float scaleY) {
14000        if (scaleY != getScaleY()) {
14001            invalidateViewProperty(true, false);
14002            mRenderNode.setScaleY(scaleY);
14003            invalidateViewProperty(false, true);
14004
14005            invalidateParentIfNeededAndWasQuickRejected();
14006            notifySubtreeAccessibilityStateChangedIfNeeded();
14007        }
14008    }
14009
14010    /**
14011     * The x location of the point around which the view is {@link #setRotation(float) rotated}
14012     * and {@link #setScaleX(float) scaled}.
14013     *
14014     * @see #getRotation()
14015     * @see #getScaleX()
14016     * @see #getScaleY()
14017     * @see #getPivotY()
14018     * @return The x location of the pivot point.
14019     *
14020     * @attr ref android.R.styleable#View_transformPivotX
14021     */
14022    @ViewDebug.ExportedProperty(category = "drawing")
14023    public float getPivotX() {
14024        return mRenderNode.getPivotX();
14025    }
14026
14027    /**
14028     * Sets the x location of the point around which the view is
14029     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
14030     * By default, the pivot point is centered on the object.
14031     * Setting this property disables this behavior and causes the view to use only the
14032     * explicitly set pivotX and pivotY values.
14033     *
14034     * @param pivotX The x location of the pivot point.
14035     * @see #getRotation()
14036     * @see #getScaleX()
14037     * @see #getScaleY()
14038     * @see #getPivotY()
14039     *
14040     * @attr ref android.R.styleable#View_transformPivotX
14041     */
14042    public void setPivotX(float pivotX) {
14043        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
14044            invalidateViewProperty(true, false);
14045            mRenderNode.setPivotX(pivotX);
14046            invalidateViewProperty(false, true);
14047
14048            invalidateParentIfNeededAndWasQuickRejected();
14049        }
14050    }
14051
14052    /**
14053     * The y location of the point around which the view is {@link #setRotation(float) rotated}
14054     * and {@link #setScaleY(float) scaled}.
14055     *
14056     * @see #getRotation()
14057     * @see #getScaleX()
14058     * @see #getScaleY()
14059     * @see #getPivotY()
14060     * @return The y location of the pivot point.
14061     *
14062     * @attr ref android.R.styleable#View_transformPivotY
14063     */
14064    @ViewDebug.ExportedProperty(category = "drawing")
14065    public float getPivotY() {
14066        return mRenderNode.getPivotY();
14067    }
14068
14069    /**
14070     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
14071     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
14072     * Setting this property disables this behavior and causes the view to use only the
14073     * explicitly set pivotX and pivotY values.
14074     *
14075     * @param pivotY The y location of the pivot point.
14076     * @see #getRotation()
14077     * @see #getScaleX()
14078     * @see #getScaleY()
14079     * @see #getPivotY()
14080     *
14081     * @attr ref android.R.styleable#View_transformPivotY
14082     */
14083    public void setPivotY(float pivotY) {
14084        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
14085            invalidateViewProperty(true, false);
14086            mRenderNode.setPivotY(pivotY);
14087            invalidateViewProperty(false, true);
14088
14089            invalidateParentIfNeededAndWasQuickRejected();
14090        }
14091    }
14092
14093    /**
14094     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
14095     * completely transparent and 1 means the view is completely opaque.
14096     *
14097     * <p>By default this is 1.0f.
14098     * @return The opacity of the view.
14099     */
14100    @ViewDebug.ExportedProperty(category = "drawing")
14101    public float getAlpha() {
14102        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
14103    }
14104
14105    /**
14106     * Sets the behavior for overlapping rendering for this view (see {@link
14107     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
14108     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
14109     * providing the value which is then used internally. That is, when {@link
14110     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
14111     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
14112     * instead.
14113     *
14114     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
14115     * instead of that returned by {@link #hasOverlappingRendering()}.
14116     *
14117     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
14118     */
14119    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
14120        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
14121        if (hasOverlappingRendering) {
14122            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14123        } else {
14124            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14125        }
14126    }
14127
14128    /**
14129     * Returns the value for overlapping rendering that is used internally. This is either
14130     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
14131     * the return value of {@link #hasOverlappingRendering()}, otherwise.
14132     *
14133     * @return The value for overlapping rendering being used internally.
14134     */
14135    public final boolean getHasOverlappingRendering() {
14136        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
14137                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
14138                hasOverlappingRendering();
14139    }
14140
14141    /**
14142     * Returns whether this View has content which overlaps.
14143     *
14144     * <p>This function, intended to be overridden by specific View types, is an optimization when
14145     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
14146     * an offscreen buffer and then composited into place, which can be expensive. If the view has
14147     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
14148     * directly. An example of overlapping rendering is a TextView with a background image, such as
14149     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
14150     * ImageView with only the foreground image. The default implementation returns true; subclasses
14151     * should override if they have cases which can be optimized.</p>
14152     *
14153     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
14154     * necessitates that a View return true if it uses the methods internally without passing the
14155     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
14156     *
14157     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
14158     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
14159     *
14160     * @return true if the content in this view might overlap, false otherwise.
14161     */
14162    @ViewDebug.ExportedProperty(category = "drawing")
14163    public boolean hasOverlappingRendering() {
14164        return true;
14165    }
14166
14167    /**
14168     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
14169     * completely transparent and 1 means the view is completely opaque.
14170     *
14171     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
14172     * can have significant performance implications, especially for large views. It is best to use
14173     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
14174     *
14175     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
14176     * strongly recommended for performance reasons to either override
14177     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
14178     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
14179     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
14180     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
14181     * of rendering cost, even for simple or small views. Starting with
14182     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
14183     * applied to the view at the rendering level.</p>
14184     *
14185     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
14186     * responsible for applying the opacity itself.</p>
14187     *
14188     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
14189     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
14190     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
14191     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
14192     *
14193     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
14194     * value will clip a View to its bounds, unless the View returns <code>false</code> from
14195     * {@link #hasOverlappingRendering}.</p>
14196     *
14197     * @param alpha The opacity of the view.
14198     *
14199     * @see #hasOverlappingRendering()
14200     * @see #setLayerType(int, android.graphics.Paint)
14201     *
14202     * @attr ref android.R.styleable#View_alpha
14203     */
14204    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
14205        ensureTransformationInfo();
14206        if (mTransformationInfo.mAlpha != alpha) {
14207            // Report visibility changes, which can affect children, to accessibility
14208            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
14209                notifySubtreeAccessibilityStateChangedIfNeeded();
14210            }
14211            mTransformationInfo.mAlpha = alpha;
14212            if (onSetAlpha((int) (alpha * 255))) {
14213                mPrivateFlags |= PFLAG_ALPHA_SET;
14214                // subclass is handling alpha - don't optimize rendering cache invalidation
14215                invalidateParentCaches();
14216                invalidate(true);
14217            } else {
14218                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14219                invalidateViewProperty(true, false);
14220                mRenderNode.setAlpha(getFinalAlpha());
14221            }
14222        }
14223    }
14224
14225    /**
14226     * Faster version of setAlpha() which performs the same steps except there are
14227     * no calls to invalidate(). The caller of this function should perform proper invalidation
14228     * on the parent and this object. The return value indicates whether the subclass handles
14229     * alpha (the return value for onSetAlpha()).
14230     *
14231     * @param alpha The new value for the alpha property
14232     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
14233     *         the new value for the alpha property is different from the old value
14234     */
14235    boolean setAlphaNoInvalidation(float alpha) {
14236        ensureTransformationInfo();
14237        if (mTransformationInfo.mAlpha != alpha) {
14238            mTransformationInfo.mAlpha = alpha;
14239            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
14240            if (subclassHandlesAlpha) {
14241                mPrivateFlags |= PFLAG_ALPHA_SET;
14242                return true;
14243            } else {
14244                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14245                mRenderNode.setAlpha(getFinalAlpha());
14246            }
14247        }
14248        return false;
14249    }
14250
14251    /**
14252     * This property is hidden and intended only for use by the Fade transition, which
14253     * animates it to produce a visual translucency that does not side-effect (or get
14254     * affected by) the real alpha property. This value is composited with the other
14255     * alpha value (and the AlphaAnimation value, when that is present) to produce
14256     * a final visual translucency result, which is what is passed into the DisplayList.
14257     *
14258     * @hide
14259     */
14260    public void setTransitionAlpha(float alpha) {
14261        ensureTransformationInfo();
14262        if (mTransformationInfo.mTransitionAlpha != alpha) {
14263            mTransformationInfo.mTransitionAlpha = alpha;
14264            mPrivateFlags &= ~PFLAG_ALPHA_SET;
14265            invalidateViewProperty(true, false);
14266            mRenderNode.setAlpha(getFinalAlpha());
14267        }
14268    }
14269
14270    /**
14271     * Calculates the visual alpha of this view, which is a combination of the actual
14272     * alpha value and the transitionAlpha value (if set).
14273     */
14274    private float getFinalAlpha() {
14275        if (mTransformationInfo != null) {
14276            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
14277        }
14278        return 1;
14279    }
14280
14281    /**
14282     * This property is hidden and intended only for use by the Fade transition, which
14283     * animates it to produce a visual translucency that does not side-effect (or get
14284     * affected by) the real alpha property. This value is composited with the other
14285     * alpha value (and the AlphaAnimation value, when that is present) to produce
14286     * a final visual translucency result, which is what is passed into the DisplayList.
14287     *
14288     * @hide
14289     */
14290    @ViewDebug.ExportedProperty(category = "drawing")
14291    public float getTransitionAlpha() {
14292        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
14293    }
14294
14295    /**
14296     * Top position of this view relative to its parent.
14297     *
14298     * @return The top of this view, in pixels.
14299     */
14300    @ViewDebug.CapturedViewProperty
14301    public final int getTop() {
14302        return mTop;
14303    }
14304
14305    /**
14306     * Sets the top position of this view relative to its parent. This method is meant to be called
14307     * by the layout system and should not generally be called otherwise, because the property
14308     * may be changed at any time by the layout.
14309     *
14310     * @param top The top of this view, in pixels.
14311     */
14312    public final void setTop(int top) {
14313        if (top != mTop) {
14314            final boolean matrixIsIdentity = hasIdentityMatrix();
14315            if (matrixIsIdentity) {
14316                if (mAttachInfo != null) {
14317                    int minTop;
14318                    int yLoc;
14319                    if (top < mTop) {
14320                        minTop = top;
14321                        yLoc = top - mTop;
14322                    } else {
14323                        minTop = mTop;
14324                        yLoc = 0;
14325                    }
14326                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
14327                }
14328            } else {
14329                // Double-invalidation is necessary to capture view's old and new areas
14330                invalidate(true);
14331            }
14332
14333            int width = mRight - mLeft;
14334            int oldHeight = mBottom - mTop;
14335
14336            mTop = top;
14337            mRenderNode.setTop(mTop);
14338
14339            sizeChange(width, mBottom - mTop, width, oldHeight);
14340
14341            if (!matrixIsIdentity) {
14342                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14343                invalidate(true);
14344            }
14345            mBackgroundSizeChanged = true;
14346            mDefaultFocusHighlightSizeChanged = true;
14347            if (mForegroundInfo != null) {
14348                mForegroundInfo.mBoundsChanged = true;
14349            }
14350            invalidateParentIfNeeded();
14351            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14352                // View was rejected last time it was drawn by its parent; this may have changed
14353                invalidateParentIfNeeded();
14354            }
14355        }
14356    }
14357
14358    /**
14359     * Bottom position of this view relative to its parent.
14360     *
14361     * @return The bottom of this view, in pixels.
14362     */
14363    @ViewDebug.CapturedViewProperty
14364    public final int getBottom() {
14365        return mBottom;
14366    }
14367
14368    /**
14369     * True if this view has changed since the last time being drawn.
14370     *
14371     * @return The dirty state of this view.
14372     */
14373    public boolean isDirty() {
14374        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14375    }
14376
14377    /**
14378     * Sets the bottom position of this view relative to its parent. This method is meant to be
14379     * called by the layout system and should not generally be called otherwise, because the
14380     * property may be changed at any time by the layout.
14381     *
14382     * @param bottom The bottom of this view, in pixels.
14383     */
14384    public final void setBottom(int bottom) {
14385        if (bottom != mBottom) {
14386            final boolean matrixIsIdentity = hasIdentityMatrix();
14387            if (matrixIsIdentity) {
14388                if (mAttachInfo != null) {
14389                    int maxBottom;
14390                    if (bottom < mBottom) {
14391                        maxBottom = mBottom;
14392                    } else {
14393                        maxBottom = bottom;
14394                    }
14395                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14396                }
14397            } else {
14398                // Double-invalidation is necessary to capture view's old and new areas
14399                invalidate(true);
14400            }
14401
14402            int width = mRight - mLeft;
14403            int oldHeight = mBottom - mTop;
14404
14405            mBottom = bottom;
14406            mRenderNode.setBottom(mBottom);
14407
14408            sizeChange(width, mBottom - mTop, width, oldHeight);
14409
14410            if (!matrixIsIdentity) {
14411                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14412                invalidate(true);
14413            }
14414            mBackgroundSizeChanged = true;
14415            mDefaultFocusHighlightSizeChanged = true;
14416            if (mForegroundInfo != null) {
14417                mForegroundInfo.mBoundsChanged = true;
14418            }
14419            invalidateParentIfNeeded();
14420            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14421                // View was rejected last time it was drawn by its parent; this may have changed
14422                invalidateParentIfNeeded();
14423            }
14424        }
14425    }
14426
14427    /**
14428     * Left position of this view relative to its parent.
14429     *
14430     * @return The left edge of this view, in pixels.
14431     */
14432    @ViewDebug.CapturedViewProperty
14433    public final int getLeft() {
14434        return mLeft;
14435    }
14436
14437    /**
14438     * Sets the left position of this view relative to its parent. This method is meant to be called
14439     * by the layout system and should not generally be called otherwise, because the property
14440     * may be changed at any time by the layout.
14441     *
14442     * @param left The left of this view, in pixels.
14443     */
14444    public final void setLeft(int left) {
14445        if (left != mLeft) {
14446            final boolean matrixIsIdentity = hasIdentityMatrix();
14447            if (matrixIsIdentity) {
14448                if (mAttachInfo != null) {
14449                    int minLeft;
14450                    int xLoc;
14451                    if (left < mLeft) {
14452                        minLeft = left;
14453                        xLoc = left - mLeft;
14454                    } else {
14455                        minLeft = mLeft;
14456                        xLoc = 0;
14457                    }
14458                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14459                }
14460            } else {
14461                // Double-invalidation is necessary to capture view's old and new areas
14462                invalidate(true);
14463            }
14464
14465            int oldWidth = mRight - mLeft;
14466            int height = mBottom - mTop;
14467
14468            mLeft = left;
14469            mRenderNode.setLeft(left);
14470
14471            sizeChange(mRight - mLeft, height, oldWidth, height);
14472
14473            if (!matrixIsIdentity) {
14474                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14475                invalidate(true);
14476            }
14477            mBackgroundSizeChanged = true;
14478            mDefaultFocusHighlightSizeChanged = true;
14479            if (mForegroundInfo != null) {
14480                mForegroundInfo.mBoundsChanged = true;
14481            }
14482            invalidateParentIfNeeded();
14483            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14484                // View was rejected last time it was drawn by its parent; this may have changed
14485                invalidateParentIfNeeded();
14486            }
14487        }
14488    }
14489
14490    /**
14491     * Right position of this view relative to its parent.
14492     *
14493     * @return The right edge of this view, in pixels.
14494     */
14495    @ViewDebug.CapturedViewProperty
14496    public final int getRight() {
14497        return mRight;
14498    }
14499
14500    /**
14501     * Sets the right position of this view relative to its parent. This method is meant to be called
14502     * by the layout system and should not generally be called otherwise, because the property
14503     * may be changed at any time by the layout.
14504     *
14505     * @param right The right of this view, in pixels.
14506     */
14507    public final void setRight(int right) {
14508        if (right != mRight) {
14509            final boolean matrixIsIdentity = hasIdentityMatrix();
14510            if (matrixIsIdentity) {
14511                if (mAttachInfo != null) {
14512                    int maxRight;
14513                    if (right < mRight) {
14514                        maxRight = mRight;
14515                    } else {
14516                        maxRight = right;
14517                    }
14518                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14519                }
14520            } else {
14521                // Double-invalidation is necessary to capture view's old and new areas
14522                invalidate(true);
14523            }
14524
14525            int oldWidth = mRight - mLeft;
14526            int height = mBottom - mTop;
14527
14528            mRight = right;
14529            mRenderNode.setRight(mRight);
14530
14531            sizeChange(mRight - mLeft, height, oldWidth, height);
14532
14533            if (!matrixIsIdentity) {
14534                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14535                invalidate(true);
14536            }
14537            mBackgroundSizeChanged = true;
14538            mDefaultFocusHighlightSizeChanged = true;
14539            if (mForegroundInfo != null) {
14540                mForegroundInfo.mBoundsChanged = true;
14541            }
14542            invalidateParentIfNeeded();
14543            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14544                // View was rejected last time it was drawn by its parent; this may have changed
14545                invalidateParentIfNeeded();
14546            }
14547        }
14548    }
14549
14550    /**
14551     * The visual x position of this view, in pixels. This is equivalent to the
14552     * {@link #setTranslationX(float) translationX} property plus the current
14553     * {@link #getLeft() left} property.
14554     *
14555     * @return The visual x position of this view, in pixels.
14556     */
14557    @ViewDebug.ExportedProperty(category = "drawing")
14558    public float getX() {
14559        return mLeft + getTranslationX();
14560    }
14561
14562    /**
14563     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14564     * {@link #setTranslationX(float) translationX} property to be the difference between
14565     * the x value passed in and the current {@link #getLeft() left} property.
14566     *
14567     * @param x The visual x position of this view, in pixels.
14568     */
14569    public void setX(float x) {
14570        setTranslationX(x - mLeft);
14571    }
14572
14573    /**
14574     * The visual y position of this view, in pixels. This is equivalent to the
14575     * {@link #setTranslationY(float) translationY} property plus the current
14576     * {@link #getTop() top} property.
14577     *
14578     * @return The visual y position of this view, in pixels.
14579     */
14580    @ViewDebug.ExportedProperty(category = "drawing")
14581    public float getY() {
14582        return mTop + getTranslationY();
14583    }
14584
14585    /**
14586     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14587     * {@link #setTranslationY(float) translationY} property to be the difference between
14588     * the y value passed in and the current {@link #getTop() top} property.
14589     *
14590     * @param y The visual y position of this view, in pixels.
14591     */
14592    public void setY(float y) {
14593        setTranslationY(y - mTop);
14594    }
14595
14596    /**
14597     * The visual z position of this view, in pixels. This is equivalent to the
14598     * {@link #setTranslationZ(float) translationZ} property plus the current
14599     * {@link #getElevation() elevation} property.
14600     *
14601     * @return The visual z position of this view, in pixels.
14602     */
14603    @ViewDebug.ExportedProperty(category = "drawing")
14604    public float getZ() {
14605        return getElevation() + getTranslationZ();
14606    }
14607
14608    /**
14609     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14610     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14611     * the x value passed in and the current {@link #getElevation() elevation} property.
14612     *
14613     * @param z The visual z position of this view, in pixels.
14614     */
14615    public void setZ(float z) {
14616        setTranslationZ(z - getElevation());
14617    }
14618
14619    /**
14620     * The base elevation of this view relative to its parent, in pixels.
14621     *
14622     * @return The base depth position of the view, in pixels.
14623     */
14624    @ViewDebug.ExportedProperty(category = "drawing")
14625    public float getElevation() {
14626        return mRenderNode.getElevation();
14627    }
14628
14629    /**
14630     * Sets the base elevation of this view, in pixels.
14631     *
14632     * @attr ref android.R.styleable#View_elevation
14633     */
14634    public void setElevation(float elevation) {
14635        if (elevation != getElevation()) {
14636            invalidateViewProperty(true, false);
14637            mRenderNode.setElevation(elevation);
14638            invalidateViewProperty(false, true);
14639
14640            invalidateParentIfNeededAndWasQuickRejected();
14641        }
14642    }
14643
14644    /**
14645     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14646     * This position is post-layout, in addition to wherever the object's
14647     * layout placed it.
14648     *
14649     * @return The horizontal position of this view relative to its left position, in pixels.
14650     */
14651    @ViewDebug.ExportedProperty(category = "drawing")
14652    public float getTranslationX() {
14653        return mRenderNode.getTranslationX();
14654    }
14655
14656    /**
14657     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14658     * This effectively positions the object post-layout, in addition to wherever the object's
14659     * layout placed it.
14660     *
14661     * @param translationX The horizontal position of this view relative to its left position,
14662     * in pixels.
14663     *
14664     * @attr ref android.R.styleable#View_translationX
14665     */
14666    public void setTranslationX(float translationX) {
14667        if (translationX != getTranslationX()) {
14668            invalidateViewProperty(true, false);
14669            mRenderNode.setTranslationX(translationX);
14670            invalidateViewProperty(false, true);
14671
14672            invalidateParentIfNeededAndWasQuickRejected();
14673            notifySubtreeAccessibilityStateChangedIfNeeded();
14674        }
14675    }
14676
14677    /**
14678     * The vertical location of this view relative to its {@link #getTop() top} position.
14679     * This position is post-layout, in addition to wherever the object's
14680     * layout placed it.
14681     *
14682     * @return The vertical position of this view relative to its top position,
14683     * in pixels.
14684     */
14685    @ViewDebug.ExportedProperty(category = "drawing")
14686    public float getTranslationY() {
14687        return mRenderNode.getTranslationY();
14688    }
14689
14690    /**
14691     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14692     * This effectively positions the object post-layout, in addition to wherever the object's
14693     * layout placed it.
14694     *
14695     * @param translationY The vertical position of this view relative to its top position,
14696     * in pixels.
14697     *
14698     * @attr ref android.R.styleable#View_translationY
14699     */
14700    public void setTranslationY(float translationY) {
14701        if (translationY != getTranslationY()) {
14702            invalidateViewProperty(true, false);
14703            mRenderNode.setTranslationY(translationY);
14704            invalidateViewProperty(false, true);
14705
14706            invalidateParentIfNeededAndWasQuickRejected();
14707            notifySubtreeAccessibilityStateChangedIfNeeded();
14708        }
14709    }
14710
14711    /**
14712     * The depth location of this view relative to its {@link #getElevation() elevation}.
14713     *
14714     * @return The depth of this view relative to its elevation.
14715     */
14716    @ViewDebug.ExportedProperty(category = "drawing")
14717    public float getTranslationZ() {
14718        return mRenderNode.getTranslationZ();
14719    }
14720
14721    /**
14722     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14723     *
14724     * @attr ref android.R.styleable#View_translationZ
14725     */
14726    public void setTranslationZ(float translationZ) {
14727        if (translationZ != getTranslationZ()) {
14728            invalidateViewProperty(true, false);
14729            mRenderNode.setTranslationZ(translationZ);
14730            invalidateViewProperty(false, true);
14731
14732            invalidateParentIfNeededAndWasQuickRejected();
14733        }
14734    }
14735
14736    /** @hide */
14737    public void setAnimationMatrix(Matrix matrix) {
14738        invalidateViewProperty(true, false);
14739        mRenderNode.setAnimationMatrix(matrix);
14740        invalidateViewProperty(false, true);
14741
14742        invalidateParentIfNeededAndWasQuickRejected();
14743    }
14744
14745    /**
14746     * Returns the current StateListAnimator if exists.
14747     *
14748     * @return StateListAnimator or null if it does not exists
14749     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14750     */
14751    public StateListAnimator getStateListAnimator() {
14752        return mStateListAnimator;
14753    }
14754
14755    /**
14756     * Attaches the provided StateListAnimator to this View.
14757     * <p>
14758     * Any previously attached StateListAnimator will be detached.
14759     *
14760     * @param stateListAnimator The StateListAnimator to update the view
14761     * @see android.animation.StateListAnimator
14762     */
14763    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14764        if (mStateListAnimator == stateListAnimator) {
14765            return;
14766        }
14767        if (mStateListAnimator != null) {
14768            mStateListAnimator.setTarget(null);
14769        }
14770        mStateListAnimator = stateListAnimator;
14771        if (stateListAnimator != null) {
14772            stateListAnimator.setTarget(this);
14773            if (isAttachedToWindow()) {
14774                stateListAnimator.setState(getDrawableState());
14775            }
14776        }
14777    }
14778
14779    /**
14780     * Returns whether the Outline should be used to clip the contents of the View.
14781     * <p>
14782     * Note that this flag will only be respected if the View's Outline returns true from
14783     * {@link Outline#canClip()}.
14784     *
14785     * @see #setOutlineProvider(ViewOutlineProvider)
14786     * @see #setClipToOutline(boolean)
14787     */
14788    public final boolean getClipToOutline() {
14789        return mRenderNode.getClipToOutline();
14790    }
14791
14792    /**
14793     * Sets whether the View's Outline should be used to clip the contents of the View.
14794     * <p>
14795     * Only a single non-rectangular clip can be applied on a View at any time.
14796     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14797     * circular reveal} animation take priority over Outline clipping, and
14798     * child Outline clipping takes priority over Outline clipping done by a
14799     * parent.
14800     * <p>
14801     * Note that this flag will only be respected if the View's Outline returns true from
14802     * {@link Outline#canClip()}.
14803     *
14804     * @see #setOutlineProvider(ViewOutlineProvider)
14805     * @see #getClipToOutline()
14806     */
14807    public void setClipToOutline(boolean clipToOutline) {
14808        damageInParent();
14809        if (getClipToOutline() != clipToOutline) {
14810            mRenderNode.setClipToOutline(clipToOutline);
14811        }
14812    }
14813
14814    // correspond to the enum values of View_outlineProvider
14815    private static final int PROVIDER_BACKGROUND = 0;
14816    private static final int PROVIDER_NONE = 1;
14817    private static final int PROVIDER_BOUNDS = 2;
14818    private static final int PROVIDER_PADDED_BOUNDS = 3;
14819    private void setOutlineProviderFromAttribute(int providerInt) {
14820        switch (providerInt) {
14821            case PROVIDER_BACKGROUND:
14822                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14823                break;
14824            case PROVIDER_NONE:
14825                setOutlineProvider(null);
14826                break;
14827            case PROVIDER_BOUNDS:
14828                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14829                break;
14830            case PROVIDER_PADDED_BOUNDS:
14831                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14832                break;
14833        }
14834    }
14835
14836    /**
14837     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14838     * the shape of the shadow it casts, and enables outline clipping.
14839     * <p>
14840     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14841     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14842     * outline provider with this method allows this behavior to be overridden.
14843     * <p>
14844     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14845     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14846     * <p>
14847     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14848     *
14849     * @see #setClipToOutline(boolean)
14850     * @see #getClipToOutline()
14851     * @see #getOutlineProvider()
14852     */
14853    public void setOutlineProvider(ViewOutlineProvider provider) {
14854        mOutlineProvider = provider;
14855        invalidateOutline();
14856    }
14857
14858    /**
14859     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14860     * that defines the shape of the shadow it casts, and enables outline clipping.
14861     *
14862     * @see #setOutlineProvider(ViewOutlineProvider)
14863     */
14864    public ViewOutlineProvider getOutlineProvider() {
14865        return mOutlineProvider;
14866    }
14867
14868    /**
14869     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14870     *
14871     * @see #setOutlineProvider(ViewOutlineProvider)
14872     */
14873    public void invalidateOutline() {
14874        rebuildOutline();
14875
14876        notifySubtreeAccessibilityStateChangedIfNeeded();
14877        invalidateViewProperty(false, false);
14878    }
14879
14880    /**
14881     * Internal version of {@link #invalidateOutline()} which invalidates the
14882     * outline without invalidating the view itself. This is intended to be called from
14883     * within methods in the View class itself which are the result of the view being
14884     * invalidated already. For example, when we are drawing the background of a View,
14885     * we invalidate the outline in case it changed in the meantime, but we do not
14886     * need to invalidate the view because we're already drawing the background as part
14887     * of drawing the view in response to an earlier invalidation of the view.
14888     */
14889    private void rebuildOutline() {
14890        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14891        if (mAttachInfo == null) return;
14892
14893        if (mOutlineProvider == null) {
14894            // no provider, remove outline
14895            mRenderNode.setOutline(null);
14896        } else {
14897            final Outline outline = mAttachInfo.mTmpOutline;
14898            outline.setEmpty();
14899            outline.setAlpha(1.0f);
14900
14901            mOutlineProvider.getOutline(this, outline);
14902            mRenderNode.setOutline(outline);
14903        }
14904    }
14905
14906    /**
14907     * HierarchyViewer only
14908     *
14909     * @hide
14910     */
14911    @ViewDebug.ExportedProperty(category = "drawing")
14912    public boolean hasShadow() {
14913        return mRenderNode.hasShadow();
14914    }
14915
14916
14917    /** @hide */
14918    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14919        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14920        invalidateViewProperty(false, false);
14921    }
14922
14923    /**
14924     * Hit rectangle in parent's coordinates
14925     *
14926     * @param outRect The hit rectangle of the view.
14927     */
14928    public void getHitRect(Rect outRect) {
14929        if (hasIdentityMatrix() || mAttachInfo == null) {
14930            outRect.set(mLeft, mTop, mRight, mBottom);
14931        } else {
14932            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14933            tmpRect.set(0, 0, getWidth(), getHeight());
14934            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14935            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14936                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14937        }
14938    }
14939
14940    /**
14941     * Determines whether the given point, in local coordinates is inside the view.
14942     */
14943    /*package*/ final boolean pointInView(float localX, float localY) {
14944        return pointInView(localX, localY, 0);
14945    }
14946
14947    /**
14948     * Utility method to determine whether the given point, in local coordinates,
14949     * is inside the view, where the area of the view is expanded by the slop factor.
14950     * This method is called while processing touch-move events to determine if the event
14951     * is still within the view.
14952     *
14953     * @hide
14954     */
14955    public boolean pointInView(float localX, float localY, float slop) {
14956        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14957                localY < ((mBottom - mTop) + slop);
14958    }
14959
14960    /**
14961     * When a view has focus and the user navigates away from it, the next view is searched for
14962     * starting from the rectangle filled in by this method.
14963     *
14964     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14965     * of the view.  However, if your view maintains some idea of internal selection,
14966     * such as a cursor, or a selected row or column, you should override this method and
14967     * fill in a more specific rectangle.
14968     *
14969     * @param r The rectangle to fill in, in this view's coordinates.
14970     */
14971    public void getFocusedRect(Rect r) {
14972        getDrawingRect(r);
14973    }
14974
14975    /**
14976     * If some part of this view is not clipped by any of its parents, then
14977     * return that area in r in global (root) coordinates. To convert r to local
14978     * coordinates (without taking possible View rotations into account), offset
14979     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14980     * If the view is completely clipped or translated out, return false.
14981     *
14982     * @param r If true is returned, r holds the global coordinates of the
14983     *        visible portion of this view.
14984     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14985     *        between this view and its root. globalOffet may be null.
14986     * @return true if r is non-empty (i.e. part of the view is visible at the
14987     *         root level.
14988     */
14989    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14990        int width = mRight - mLeft;
14991        int height = mBottom - mTop;
14992        if (width > 0 && height > 0) {
14993            r.set(0, 0, width, height);
14994            if (globalOffset != null) {
14995                globalOffset.set(-mScrollX, -mScrollY);
14996            }
14997            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14998        }
14999        return false;
15000    }
15001
15002    public final boolean getGlobalVisibleRect(Rect r) {
15003        return getGlobalVisibleRect(r, null);
15004    }
15005
15006    public final boolean getLocalVisibleRect(Rect r) {
15007        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
15008        if (getGlobalVisibleRect(r, offset)) {
15009            r.offset(-offset.x, -offset.y); // make r local
15010            return true;
15011        }
15012        return false;
15013    }
15014
15015    /**
15016     * Offset this view's vertical location by the specified number of pixels.
15017     *
15018     * @param offset the number of pixels to offset the view by
15019     */
15020    public void offsetTopAndBottom(int offset) {
15021        if (offset != 0) {
15022            final boolean matrixIsIdentity = hasIdentityMatrix();
15023            if (matrixIsIdentity) {
15024                if (isHardwareAccelerated()) {
15025                    invalidateViewProperty(false, false);
15026                } else {
15027                    final ViewParent p = mParent;
15028                    if (p != null && mAttachInfo != null) {
15029                        final Rect r = mAttachInfo.mTmpInvalRect;
15030                        int minTop;
15031                        int maxBottom;
15032                        int yLoc;
15033                        if (offset < 0) {
15034                            minTop = mTop + offset;
15035                            maxBottom = mBottom;
15036                            yLoc = offset;
15037                        } else {
15038                            minTop = mTop;
15039                            maxBottom = mBottom + offset;
15040                            yLoc = 0;
15041                        }
15042                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
15043                        p.invalidateChild(this, r);
15044                    }
15045                }
15046            } else {
15047                invalidateViewProperty(false, false);
15048            }
15049
15050            mTop += offset;
15051            mBottom += offset;
15052            mRenderNode.offsetTopAndBottom(offset);
15053            if (isHardwareAccelerated()) {
15054                invalidateViewProperty(false, false);
15055                invalidateParentIfNeededAndWasQuickRejected();
15056            } else {
15057                if (!matrixIsIdentity) {
15058                    invalidateViewProperty(false, true);
15059                }
15060                invalidateParentIfNeeded();
15061            }
15062            notifySubtreeAccessibilityStateChangedIfNeeded();
15063        }
15064    }
15065
15066    /**
15067     * Offset this view's horizontal location by the specified amount of pixels.
15068     *
15069     * @param offset the number of pixels to offset the view by
15070     */
15071    public void offsetLeftAndRight(int offset) {
15072        if (offset != 0) {
15073            final boolean matrixIsIdentity = hasIdentityMatrix();
15074            if (matrixIsIdentity) {
15075                if (isHardwareAccelerated()) {
15076                    invalidateViewProperty(false, false);
15077                } else {
15078                    final ViewParent p = mParent;
15079                    if (p != null && mAttachInfo != null) {
15080                        final Rect r = mAttachInfo.mTmpInvalRect;
15081                        int minLeft;
15082                        int maxRight;
15083                        if (offset < 0) {
15084                            minLeft = mLeft + offset;
15085                            maxRight = mRight;
15086                        } else {
15087                            minLeft = mLeft;
15088                            maxRight = mRight + offset;
15089                        }
15090                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
15091                        p.invalidateChild(this, r);
15092                    }
15093                }
15094            } else {
15095                invalidateViewProperty(false, false);
15096            }
15097
15098            mLeft += offset;
15099            mRight += offset;
15100            mRenderNode.offsetLeftAndRight(offset);
15101            if (isHardwareAccelerated()) {
15102                invalidateViewProperty(false, false);
15103                invalidateParentIfNeededAndWasQuickRejected();
15104            } else {
15105                if (!matrixIsIdentity) {
15106                    invalidateViewProperty(false, true);
15107                }
15108                invalidateParentIfNeeded();
15109            }
15110            notifySubtreeAccessibilityStateChangedIfNeeded();
15111        }
15112    }
15113
15114    /**
15115     * Get the LayoutParams associated with this view. All views should have
15116     * layout parameters. These supply parameters to the <i>parent</i> of this
15117     * view specifying how it should be arranged. There are many subclasses of
15118     * ViewGroup.LayoutParams, and these correspond to the different subclasses
15119     * of ViewGroup that are responsible for arranging their children.
15120     *
15121     * This method may return null if this View is not attached to a parent
15122     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
15123     * was not invoked successfully. When a View is attached to a parent
15124     * ViewGroup, this method must not return null.
15125     *
15126     * @return The LayoutParams associated with this view, or null if no
15127     *         parameters have been set yet
15128     */
15129    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
15130    public ViewGroup.LayoutParams getLayoutParams() {
15131        return mLayoutParams;
15132    }
15133
15134    /**
15135     * Set the layout parameters associated with this view. These supply
15136     * parameters to the <i>parent</i> of this view specifying how it should be
15137     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
15138     * correspond to the different subclasses of ViewGroup that are responsible
15139     * for arranging their children.
15140     *
15141     * @param params The layout parameters for this view, cannot be null
15142     */
15143    public void setLayoutParams(ViewGroup.LayoutParams params) {
15144        if (params == null) {
15145            throw new NullPointerException("Layout parameters cannot be null");
15146        }
15147        mLayoutParams = params;
15148        resolveLayoutParams();
15149        if (mParent instanceof ViewGroup) {
15150            ((ViewGroup) mParent).onSetLayoutParams(this, params);
15151        }
15152        requestLayout();
15153    }
15154
15155    /**
15156     * Resolve the layout parameters depending on the resolved layout direction
15157     *
15158     * @hide
15159     */
15160    public void resolveLayoutParams() {
15161        if (mLayoutParams != null) {
15162            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
15163        }
15164    }
15165
15166    /**
15167     * Set the scrolled position of your view. This will cause a call to
15168     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15169     * invalidated.
15170     * @param x the x position to scroll to
15171     * @param y the y position to scroll to
15172     */
15173    public void scrollTo(int x, int y) {
15174        if (mScrollX != x || mScrollY != y) {
15175            int oldX = mScrollX;
15176            int oldY = mScrollY;
15177            mScrollX = x;
15178            mScrollY = y;
15179            invalidateParentCaches();
15180            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
15181            if (!awakenScrollBars()) {
15182                postInvalidateOnAnimation();
15183            }
15184        }
15185    }
15186
15187    /**
15188     * Move the scrolled position of your view. This will cause a call to
15189     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15190     * invalidated.
15191     * @param x the amount of pixels to scroll by horizontally
15192     * @param y the amount of pixels to scroll by vertically
15193     */
15194    public void scrollBy(int x, int y) {
15195        scrollTo(mScrollX + x, mScrollY + y);
15196    }
15197
15198    /**
15199     * <p>Trigger the scrollbars to draw. When invoked this method starts an
15200     * animation to fade the scrollbars out after a default delay. If a subclass
15201     * provides animated scrolling, the start delay should equal the duration
15202     * of the scrolling animation.</p>
15203     *
15204     * <p>The animation starts only if at least one of the scrollbars is
15205     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
15206     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15207     * this method returns true, and false otherwise. If the animation is
15208     * started, this method calls {@link #invalidate()}; in that case the
15209     * caller should not call {@link #invalidate()}.</p>
15210     *
15211     * <p>This method should be invoked every time a subclass directly updates
15212     * the scroll parameters.</p>
15213     *
15214     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
15215     * and {@link #scrollTo(int, int)}.</p>
15216     *
15217     * @return true if the animation is played, false otherwise
15218     *
15219     * @see #awakenScrollBars(int)
15220     * @see #scrollBy(int, int)
15221     * @see #scrollTo(int, int)
15222     * @see #isHorizontalScrollBarEnabled()
15223     * @see #isVerticalScrollBarEnabled()
15224     * @see #setHorizontalScrollBarEnabled(boolean)
15225     * @see #setVerticalScrollBarEnabled(boolean)
15226     */
15227    protected boolean awakenScrollBars() {
15228        return mScrollCache != null &&
15229                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
15230    }
15231
15232    /**
15233     * Trigger the scrollbars to draw.
15234     * This method differs from awakenScrollBars() only in its default duration.
15235     * initialAwakenScrollBars() will show the scroll bars for longer than
15236     * usual to give the user more of a chance to notice them.
15237     *
15238     * @return true if the animation is played, false otherwise.
15239     */
15240    private boolean initialAwakenScrollBars() {
15241        return mScrollCache != null &&
15242                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
15243    }
15244
15245    /**
15246     * <p>
15247     * Trigger the scrollbars to draw. When invoked this method starts an
15248     * animation to fade the scrollbars out after a fixed delay. If a subclass
15249     * provides animated scrolling, the start delay should equal the duration of
15250     * the scrolling animation.
15251     * </p>
15252     *
15253     * <p>
15254     * The animation starts only if at least one of the scrollbars is enabled,
15255     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15256     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15257     * this method returns true, and false otherwise. If the animation is
15258     * started, this method calls {@link #invalidate()}; in that case the caller
15259     * should not call {@link #invalidate()}.
15260     * </p>
15261     *
15262     * <p>
15263     * This method should be invoked every time a subclass directly updates the
15264     * scroll parameters.
15265     * </p>
15266     *
15267     * @param startDelay the delay, in milliseconds, after which the animation
15268     *        should start; when the delay is 0, the animation starts
15269     *        immediately
15270     * @return true if the animation is played, false otherwise
15271     *
15272     * @see #scrollBy(int, int)
15273     * @see #scrollTo(int, int)
15274     * @see #isHorizontalScrollBarEnabled()
15275     * @see #isVerticalScrollBarEnabled()
15276     * @see #setHorizontalScrollBarEnabled(boolean)
15277     * @see #setVerticalScrollBarEnabled(boolean)
15278     */
15279    protected boolean awakenScrollBars(int startDelay) {
15280        return awakenScrollBars(startDelay, true);
15281    }
15282
15283    /**
15284     * <p>
15285     * Trigger the scrollbars to draw. When invoked this method starts an
15286     * animation to fade the scrollbars out after a fixed delay. If a subclass
15287     * provides animated scrolling, the start delay should equal the duration of
15288     * the scrolling animation.
15289     * </p>
15290     *
15291     * <p>
15292     * The animation starts only if at least one of the scrollbars is enabled,
15293     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15294     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15295     * this method returns true, and false otherwise. If the animation is
15296     * started, this method calls {@link #invalidate()} if the invalidate parameter
15297     * is set to true; in that case the caller
15298     * should not call {@link #invalidate()}.
15299     * </p>
15300     *
15301     * <p>
15302     * This method should be invoked every time a subclass directly updates the
15303     * scroll parameters.
15304     * </p>
15305     *
15306     * @param startDelay the delay, in milliseconds, after which the animation
15307     *        should start; when the delay is 0, the animation starts
15308     *        immediately
15309     *
15310     * @param invalidate Whether this method should call invalidate
15311     *
15312     * @return true if the animation is played, false otherwise
15313     *
15314     * @see #scrollBy(int, int)
15315     * @see #scrollTo(int, int)
15316     * @see #isHorizontalScrollBarEnabled()
15317     * @see #isVerticalScrollBarEnabled()
15318     * @see #setHorizontalScrollBarEnabled(boolean)
15319     * @see #setVerticalScrollBarEnabled(boolean)
15320     */
15321    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
15322        final ScrollabilityCache scrollCache = mScrollCache;
15323
15324        if (scrollCache == null || !scrollCache.fadeScrollBars) {
15325            return false;
15326        }
15327
15328        if (scrollCache.scrollBar == null) {
15329            scrollCache.scrollBar = new ScrollBarDrawable();
15330            scrollCache.scrollBar.setState(getDrawableState());
15331            scrollCache.scrollBar.setCallback(this);
15332        }
15333
15334        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
15335
15336            if (invalidate) {
15337                // Invalidate to show the scrollbars
15338                postInvalidateOnAnimation();
15339            }
15340
15341            if (scrollCache.state == ScrollabilityCache.OFF) {
15342                // FIXME: this is copied from WindowManagerService.
15343                // We should get this value from the system when it
15344                // is possible to do so.
15345                final int KEY_REPEAT_FIRST_DELAY = 750;
15346                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15347            }
15348
15349            // Tell mScrollCache when we should start fading. This may
15350            // extend the fade start time if one was already scheduled
15351            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15352            scrollCache.fadeStartTime = fadeStartTime;
15353            scrollCache.state = ScrollabilityCache.ON;
15354
15355            // Schedule our fader to run, unscheduling any old ones first
15356            if (mAttachInfo != null) {
15357                mAttachInfo.mHandler.removeCallbacks(scrollCache);
15358                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15359            }
15360
15361            return true;
15362        }
15363
15364        return false;
15365    }
15366
15367    /**
15368     * Do not invalidate views which are not visible and which are not running an animation. They
15369     * will not get drawn and they should not set dirty flags as if they will be drawn
15370     */
15371    private boolean skipInvalidate() {
15372        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15373                (!(mParent instanceof ViewGroup) ||
15374                        !((ViewGroup) mParent).isViewTransitioning(this));
15375    }
15376
15377    /**
15378     * Mark the area defined by dirty as needing to be drawn. If the view is
15379     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15380     * point in the future.
15381     * <p>
15382     * This must be called from a UI thread. To call from a non-UI thread, call
15383     * {@link #postInvalidate()}.
15384     * <p>
15385     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15386     * {@code dirty}.
15387     *
15388     * @param dirty the rectangle representing the bounds of the dirty region
15389     */
15390    public void invalidate(Rect dirty) {
15391        final int scrollX = mScrollX;
15392        final int scrollY = mScrollY;
15393        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15394                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15395    }
15396
15397    /**
15398     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15399     * coordinates of the dirty rect are relative to the view. If the view is
15400     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15401     * point in the future.
15402     * <p>
15403     * This must be called from a UI thread. To call from a non-UI thread, call
15404     * {@link #postInvalidate()}.
15405     *
15406     * @param l the left position of the dirty region
15407     * @param t the top position of the dirty region
15408     * @param r the right position of the dirty region
15409     * @param b the bottom position of the dirty region
15410     */
15411    public void invalidate(int l, int t, int r, int b) {
15412        final int scrollX = mScrollX;
15413        final int scrollY = mScrollY;
15414        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15415    }
15416
15417    /**
15418     * Invalidate the whole view. If the view is visible,
15419     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15420     * the future.
15421     * <p>
15422     * This must be called from a UI thread. To call from a non-UI thread, call
15423     * {@link #postInvalidate()}.
15424     */
15425    public void invalidate() {
15426        invalidate(true);
15427    }
15428
15429    /**
15430     * This is where the invalidate() work actually happens. A full invalidate()
15431     * causes the drawing cache to be invalidated, but this function can be
15432     * called with invalidateCache set to false to skip that invalidation step
15433     * for cases that do not need it (for example, a component that remains at
15434     * the same dimensions with the same content).
15435     *
15436     * @param invalidateCache Whether the drawing cache for this view should be
15437     *            invalidated as well. This is usually true for a full
15438     *            invalidate, but may be set to false if the View's contents or
15439     *            dimensions have not changed.
15440     * @hide
15441     */
15442    public void invalidate(boolean invalidateCache) {
15443        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15444    }
15445
15446    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15447            boolean fullInvalidate) {
15448        if (mGhostView != null) {
15449            mGhostView.invalidate(true);
15450            return;
15451        }
15452
15453        if (skipInvalidate()) {
15454            return;
15455        }
15456
15457        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15458                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15459                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15460                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15461            if (fullInvalidate) {
15462                mLastIsOpaque = isOpaque();
15463                mPrivateFlags &= ~PFLAG_DRAWN;
15464            }
15465
15466            mPrivateFlags |= PFLAG_DIRTY;
15467
15468            if (invalidateCache) {
15469                mPrivateFlags |= PFLAG_INVALIDATED;
15470                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15471            }
15472
15473            // Propagate the damage rectangle to the parent view.
15474            final AttachInfo ai = mAttachInfo;
15475            final ViewParent p = mParent;
15476            if (p != null && ai != null && l < r && t < b) {
15477                final Rect damage = ai.mTmpInvalRect;
15478                damage.set(l, t, r, b);
15479                p.invalidateChild(this, damage);
15480            }
15481
15482            // Damage the entire projection receiver, if necessary.
15483            if (mBackground != null && mBackground.isProjected()) {
15484                final View receiver = getProjectionReceiver();
15485                if (receiver != null) {
15486                    receiver.damageInParent();
15487                }
15488            }
15489        }
15490    }
15491
15492    /**
15493     * @return this view's projection receiver, or {@code null} if none exists
15494     */
15495    private View getProjectionReceiver() {
15496        ViewParent p = getParent();
15497        while (p != null && p instanceof View) {
15498            final View v = (View) p;
15499            if (v.isProjectionReceiver()) {
15500                return v;
15501            }
15502            p = p.getParent();
15503        }
15504
15505        return null;
15506    }
15507
15508    /**
15509     * @return whether the view is a projection receiver
15510     */
15511    private boolean isProjectionReceiver() {
15512        return mBackground != null;
15513    }
15514
15515    /**
15516     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15517     * set any flags or handle all of the cases handled by the default invalidation methods.
15518     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15519     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15520     * walk up the hierarchy, transforming the dirty rect as necessary.
15521     *
15522     * The method also handles normal invalidation logic if display list properties are not
15523     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15524     * backup approach, to handle these cases used in the various property-setting methods.
15525     *
15526     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15527     * are not being used in this view
15528     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15529     * list properties are not being used in this view
15530     */
15531    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15532        if (!isHardwareAccelerated()
15533                || !mRenderNode.isValid()
15534                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15535            if (invalidateParent) {
15536                invalidateParentCaches();
15537            }
15538            if (forceRedraw) {
15539                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15540            }
15541            invalidate(false);
15542        } else {
15543            damageInParent();
15544        }
15545    }
15546
15547    /**
15548     * Tells the parent view to damage this view's bounds.
15549     *
15550     * @hide
15551     */
15552    protected void damageInParent() {
15553        if (mParent != null && mAttachInfo != null) {
15554            mParent.onDescendantInvalidated(this, this);
15555        }
15556    }
15557
15558    /**
15559     * Utility method to transform a given Rect by the current matrix of this view.
15560     */
15561    void transformRect(final Rect rect) {
15562        if (!getMatrix().isIdentity()) {
15563            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15564            boundingRect.set(rect);
15565            getMatrix().mapRect(boundingRect);
15566            rect.set((int) Math.floor(boundingRect.left),
15567                    (int) Math.floor(boundingRect.top),
15568                    (int) Math.ceil(boundingRect.right),
15569                    (int) Math.ceil(boundingRect.bottom));
15570        }
15571    }
15572
15573    /**
15574     * Used to indicate that the parent of this view should clear its caches. This functionality
15575     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15576     * which is necessary when various parent-managed properties of the view change, such as
15577     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15578     * clears the parent caches and does not causes an invalidate event.
15579     *
15580     * @hide
15581     */
15582    protected void invalidateParentCaches() {
15583        if (mParent instanceof View) {
15584            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15585        }
15586    }
15587
15588    /**
15589     * Used to indicate that the parent of this view should be invalidated. This functionality
15590     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15591     * which is necessary when various parent-managed properties of the view change, such as
15592     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15593     * an invalidation event to the parent.
15594     *
15595     * @hide
15596     */
15597    protected void invalidateParentIfNeeded() {
15598        if (isHardwareAccelerated() && mParent instanceof View) {
15599            ((View) mParent).invalidate(true);
15600        }
15601    }
15602
15603    /**
15604     * @hide
15605     */
15606    protected void invalidateParentIfNeededAndWasQuickRejected() {
15607        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15608            // View was rejected last time it was drawn by its parent; this may have changed
15609            invalidateParentIfNeeded();
15610        }
15611    }
15612
15613    /**
15614     * Indicates whether this View is opaque. An opaque View guarantees that it will
15615     * draw all the pixels overlapping its bounds using a fully opaque color.
15616     *
15617     * Subclasses of View should override this method whenever possible to indicate
15618     * whether an instance is opaque. Opaque Views are treated in a special way by
15619     * the View hierarchy, possibly allowing it to perform optimizations during
15620     * invalidate/draw passes.
15621     *
15622     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15623     */
15624    @ViewDebug.ExportedProperty(category = "drawing")
15625    public boolean isOpaque() {
15626        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15627                getFinalAlpha() >= 1.0f;
15628    }
15629
15630    /**
15631     * @hide
15632     */
15633    protected void computeOpaqueFlags() {
15634        // Opaque if:
15635        //   - Has a background
15636        //   - Background is opaque
15637        //   - Doesn't have scrollbars or scrollbars overlay
15638
15639        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15640            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15641        } else {
15642            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15643        }
15644
15645        final int flags = mViewFlags;
15646        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15647                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15648                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15649            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15650        } else {
15651            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15652        }
15653    }
15654
15655    /**
15656     * @hide
15657     */
15658    protected boolean hasOpaqueScrollbars() {
15659        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15660    }
15661
15662    /**
15663     * @return A handler associated with the thread running the View. This
15664     * handler can be used to pump events in the UI events queue.
15665     */
15666    public Handler getHandler() {
15667        final AttachInfo attachInfo = mAttachInfo;
15668        if (attachInfo != null) {
15669            return attachInfo.mHandler;
15670        }
15671        return null;
15672    }
15673
15674    /**
15675     * Returns the queue of runnable for this view.
15676     *
15677     * @return the queue of runnables for this view
15678     */
15679    private HandlerActionQueue getRunQueue() {
15680        if (mRunQueue == null) {
15681            mRunQueue = new HandlerActionQueue();
15682        }
15683        return mRunQueue;
15684    }
15685
15686    /**
15687     * Gets the view root associated with the View.
15688     * @return The view root, or null if none.
15689     * @hide
15690     */
15691    public ViewRootImpl getViewRootImpl() {
15692        if (mAttachInfo != null) {
15693            return mAttachInfo.mViewRootImpl;
15694        }
15695        return null;
15696    }
15697
15698    /**
15699     * @hide
15700     */
15701    public ThreadedRenderer getThreadedRenderer() {
15702        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15703    }
15704
15705    /**
15706     * <p>Causes the Runnable to be added to the message queue.
15707     * The runnable will be run on the user interface thread.</p>
15708     *
15709     * @param action The Runnable that will be executed.
15710     *
15711     * @return Returns true if the Runnable was successfully placed in to the
15712     *         message queue.  Returns false on failure, usually because the
15713     *         looper processing the message queue is exiting.
15714     *
15715     * @see #postDelayed
15716     * @see #removeCallbacks
15717     */
15718    public boolean post(Runnable action) {
15719        final AttachInfo attachInfo = mAttachInfo;
15720        if (attachInfo != null) {
15721            return attachInfo.mHandler.post(action);
15722        }
15723
15724        // Postpone the runnable until we know on which thread it needs to run.
15725        // Assume that the runnable will be successfully placed after attach.
15726        getRunQueue().post(action);
15727        return true;
15728    }
15729
15730    /**
15731     * <p>Causes the Runnable to be added to the message queue, to be run
15732     * after the specified amount of time elapses.
15733     * The runnable will be run on the user interface thread.</p>
15734     *
15735     * @param action The Runnable that will be executed.
15736     * @param delayMillis The delay (in milliseconds) until the Runnable
15737     *        will be executed.
15738     *
15739     * @return true if the Runnable was successfully placed in to the
15740     *         message queue.  Returns false on failure, usually because the
15741     *         looper processing the message queue is exiting.  Note that a
15742     *         result of true does not mean the Runnable will be processed --
15743     *         if the looper is quit before the delivery time of the message
15744     *         occurs then the message will be dropped.
15745     *
15746     * @see #post
15747     * @see #removeCallbacks
15748     */
15749    public boolean postDelayed(Runnable action, long delayMillis) {
15750        final AttachInfo attachInfo = mAttachInfo;
15751        if (attachInfo != null) {
15752            return attachInfo.mHandler.postDelayed(action, delayMillis);
15753        }
15754
15755        // Postpone the runnable until we know on which thread it needs to run.
15756        // Assume that the runnable will be successfully placed after attach.
15757        getRunQueue().postDelayed(action, delayMillis);
15758        return true;
15759    }
15760
15761    /**
15762     * <p>Causes the Runnable to execute on the next animation time step.
15763     * The runnable will be run on the user interface thread.</p>
15764     *
15765     * @param action The Runnable that will be executed.
15766     *
15767     * @see #postOnAnimationDelayed
15768     * @see #removeCallbacks
15769     */
15770    public void postOnAnimation(Runnable action) {
15771        final AttachInfo attachInfo = mAttachInfo;
15772        if (attachInfo != null) {
15773            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15774                    Choreographer.CALLBACK_ANIMATION, action, null);
15775        } else {
15776            // Postpone the runnable until we know
15777            // on which thread it needs to run.
15778            getRunQueue().post(action);
15779        }
15780    }
15781
15782    /**
15783     * <p>Causes the Runnable to execute on the next animation time step,
15784     * after the specified amount of time elapses.
15785     * The runnable will be run on the user interface thread.</p>
15786     *
15787     * @param action The Runnable that will be executed.
15788     * @param delayMillis The delay (in milliseconds) until the Runnable
15789     *        will be executed.
15790     *
15791     * @see #postOnAnimation
15792     * @see #removeCallbacks
15793     */
15794    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15795        final AttachInfo attachInfo = mAttachInfo;
15796        if (attachInfo != null) {
15797            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15798                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15799        } else {
15800            // Postpone the runnable until we know
15801            // on which thread it needs to run.
15802            getRunQueue().postDelayed(action, delayMillis);
15803        }
15804    }
15805
15806    /**
15807     * <p>Removes the specified Runnable from the message queue.</p>
15808     *
15809     * @param action The Runnable to remove from the message handling queue
15810     *
15811     * @return true if this view could ask the Handler to remove the Runnable,
15812     *         false otherwise. When the returned value is true, the Runnable
15813     *         may or may not have been actually removed from the message queue
15814     *         (for instance, if the Runnable was not in the queue already.)
15815     *
15816     * @see #post
15817     * @see #postDelayed
15818     * @see #postOnAnimation
15819     * @see #postOnAnimationDelayed
15820     */
15821    public boolean removeCallbacks(Runnable action) {
15822        if (action != null) {
15823            final AttachInfo attachInfo = mAttachInfo;
15824            if (attachInfo != null) {
15825                attachInfo.mHandler.removeCallbacks(action);
15826                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15827                        Choreographer.CALLBACK_ANIMATION, action, null);
15828            }
15829            getRunQueue().removeCallbacks(action);
15830        }
15831        return true;
15832    }
15833
15834    /**
15835     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15836     * Use this to invalidate the View from a non-UI thread.</p>
15837     *
15838     * <p>This method can be invoked from outside of the UI thread
15839     * only when this View is attached to a window.</p>
15840     *
15841     * @see #invalidate()
15842     * @see #postInvalidateDelayed(long)
15843     */
15844    public void postInvalidate() {
15845        postInvalidateDelayed(0);
15846    }
15847
15848    /**
15849     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15850     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15851     *
15852     * <p>This method can be invoked from outside of the UI thread
15853     * only when this View is attached to a window.</p>
15854     *
15855     * @param left The left coordinate of the rectangle to invalidate.
15856     * @param top The top coordinate of the rectangle to invalidate.
15857     * @param right The right coordinate of the rectangle to invalidate.
15858     * @param bottom The bottom coordinate of the rectangle to invalidate.
15859     *
15860     * @see #invalidate(int, int, int, int)
15861     * @see #invalidate(Rect)
15862     * @see #postInvalidateDelayed(long, int, int, int, int)
15863     */
15864    public void postInvalidate(int left, int top, int right, int bottom) {
15865        postInvalidateDelayed(0, left, top, right, bottom);
15866    }
15867
15868    /**
15869     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15870     * loop. Waits for the specified amount of time.</p>
15871     *
15872     * <p>This method can be invoked from outside of the UI thread
15873     * only when this View is attached to a window.</p>
15874     *
15875     * @param delayMilliseconds the duration in milliseconds to delay the
15876     *         invalidation by
15877     *
15878     * @see #invalidate()
15879     * @see #postInvalidate()
15880     */
15881    public void postInvalidateDelayed(long delayMilliseconds) {
15882        // We try only with the AttachInfo because there's no point in invalidating
15883        // if we are not attached to our window
15884        final AttachInfo attachInfo = mAttachInfo;
15885        if (attachInfo != null) {
15886            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15887        }
15888    }
15889
15890    /**
15891     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15892     * through the event loop. Waits for the specified amount of time.</p>
15893     *
15894     * <p>This method can be invoked from outside of the UI thread
15895     * only when this View is attached to a window.</p>
15896     *
15897     * @param delayMilliseconds the duration in milliseconds to delay the
15898     *         invalidation by
15899     * @param left The left coordinate of the rectangle to invalidate.
15900     * @param top The top coordinate of the rectangle to invalidate.
15901     * @param right The right coordinate of the rectangle to invalidate.
15902     * @param bottom The bottom coordinate of the rectangle to invalidate.
15903     *
15904     * @see #invalidate(int, int, int, int)
15905     * @see #invalidate(Rect)
15906     * @see #postInvalidate(int, int, int, int)
15907     */
15908    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15909            int right, int bottom) {
15910
15911        // We try only with the AttachInfo because there's no point in invalidating
15912        // if we are not attached to our window
15913        final AttachInfo attachInfo = mAttachInfo;
15914        if (attachInfo != null) {
15915            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15916            info.target = this;
15917            info.left = left;
15918            info.top = top;
15919            info.right = right;
15920            info.bottom = bottom;
15921
15922            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15923        }
15924    }
15925
15926    /**
15927     * <p>Cause an invalidate to happen on the next animation time step, typically the
15928     * next display frame.</p>
15929     *
15930     * <p>This method can be invoked from outside of the UI thread
15931     * only when this View is attached to a window.</p>
15932     *
15933     * @see #invalidate()
15934     */
15935    public void postInvalidateOnAnimation() {
15936        // We try only with the AttachInfo because there's no point in invalidating
15937        // if we are not attached to our window
15938        final AttachInfo attachInfo = mAttachInfo;
15939        if (attachInfo != null) {
15940            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15941        }
15942    }
15943
15944    /**
15945     * <p>Cause an invalidate of the specified area to happen on the next animation
15946     * time step, typically the next display frame.</p>
15947     *
15948     * <p>This method can be invoked from outside of the UI thread
15949     * only when this View is attached to a window.</p>
15950     *
15951     * @param left The left coordinate of the rectangle to invalidate.
15952     * @param top The top coordinate of the rectangle to invalidate.
15953     * @param right The right coordinate of the rectangle to invalidate.
15954     * @param bottom The bottom coordinate of the rectangle to invalidate.
15955     *
15956     * @see #invalidate(int, int, int, int)
15957     * @see #invalidate(Rect)
15958     */
15959    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15960        // We try only with the AttachInfo because there's no point in invalidating
15961        // if we are not attached to our window
15962        final AttachInfo attachInfo = mAttachInfo;
15963        if (attachInfo != null) {
15964            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15965            info.target = this;
15966            info.left = left;
15967            info.top = top;
15968            info.right = right;
15969            info.bottom = bottom;
15970
15971            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15972        }
15973    }
15974
15975    /**
15976     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15977     * This event is sent at most once every
15978     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15979     */
15980    private void postSendViewScrolledAccessibilityEventCallback() {
15981        if (mSendViewScrolledAccessibilityEvent == null) {
15982            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15983        }
15984        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15985            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15986            postDelayed(mSendViewScrolledAccessibilityEvent,
15987                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15988        }
15989    }
15990
15991    /**
15992     * Called by a parent to request that a child update its values for mScrollX
15993     * and mScrollY if necessary. This will typically be done if the child is
15994     * animating a scroll using a {@link android.widget.Scroller Scroller}
15995     * object.
15996     */
15997    public void computeScroll() {
15998    }
15999
16000    /**
16001     * <p>Indicate whether the horizontal edges are faded when the view is
16002     * scrolled horizontally.</p>
16003     *
16004     * @return true if the horizontal edges should are faded on scroll, false
16005     *         otherwise
16006     *
16007     * @see #setHorizontalFadingEdgeEnabled(boolean)
16008     *
16009     * @attr ref android.R.styleable#View_requiresFadingEdge
16010     */
16011    public boolean isHorizontalFadingEdgeEnabled() {
16012        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
16013    }
16014
16015    /**
16016     * <p>Define whether the horizontal edges should be faded when this view
16017     * is scrolled horizontally.</p>
16018     *
16019     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
16020     *                                    be faded when the view is scrolled
16021     *                                    horizontally
16022     *
16023     * @see #isHorizontalFadingEdgeEnabled()
16024     *
16025     * @attr ref android.R.styleable#View_requiresFadingEdge
16026     */
16027    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
16028        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
16029            if (horizontalFadingEdgeEnabled) {
16030                initScrollCache();
16031            }
16032
16033            mViewFlags ^= FADING_EDGE_HORIZONTAL;
16034        }
16035    }
16036
16037    /**
16038     * <p>Indicate whether the vertical edges are faded when the view is
16039     * scrolled horizontally.</p>
16040     *
16041     * @return true if the vertical edges should are faded on scroll, false
16042     *         otherwise
16043     *
16044     * @see #setVerticalFadingEdgeEnabled(boolean)
16045     *
16046     * @attr ref android.R.styleable#View_requiresFadingEdge
16047     */
16048    public boolean isVerticalFadingEdgeEnabled() {
16049        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
16050    }
16051
16052    /**
16053     * <p>Define whether the vertical edges should be faded when this view
16054     * is scrolled vertically.</p>
16055     *
16056     * @param verticalFadingEdgeEnabled true if the vertical edges should
16057     *                                  be faded when the view is scrolled
16058     *                                  vertically
16059     *
16060     * @see #isVerticalFadingEdgeEnabled()
16061     *
16062     * @attr ref android.R.styleable#View_requiresFadingEdge
16063     */
16064    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
16065        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
16066            if (verticalFadingEdgeEnabled) {
16067                initScrollCache();
16068            }
16069
16070            mViewFlags ^= FADING_EDGE_VERTICAL;
16071        }
16072    }
16073
16074    /**
16075     * Returns the strength, or intensity, of the top faded edge. The strength is
16076     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16077     * returns 0.0 or 1.0 but no value in between.
16078     *
16079     * Subclasses should override this method to provide a smoother fade transition
16080     * when scrolling occurs.
16081     *
16082     * @return the intensity of the top fade as a float between 0.0f and 1.0f
16083     */
16084    protected float getTopFadingEdgeStrength() {
16085        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
16086    }
16087
16088    /**
16089     * Returns the strength, or intensity, of the bottom faded edge. The strength is
16090     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16091     * returns 0.0 or 1.0 but no value in between.
16092     *
16093     * Subclasses should override this method to provide a smoother fade transition
16094     * when scrolling occurs.
16095     *
16096     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
16097     */
16098    protected float getBottomFadingEdgeStrength() {
16099        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
16100                computeVerticalScrollRange() ? 1.0f : 0.0f;
16101    }
16102
16103    /**
16104     * Returns the strength, or intensity, of the left faded edge. The strength is
16105     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16106     * returns 0.0 or 1.0 but no value in between.
16107     *
16108     * Subclasses should override this method to provide a smoother fade transition
16109     * when scrolling occurs.
16110     *
16111     * @return the intensity of the left fade as a float between 0.0f and 1.0f
16112     */
16113    protected float getLeftFadingEdgeStrength() {
16114        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
16115    }
16116
16117    /**
16118     * Returns the strength, or intensity, of the right faded edge. The strength is
16119     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16120     * returns 0.0 or 1.0 but no value in between.
16121     *
16122     * Subclasses should override this method to provide a smoother fade transition
16123     * when scrolling occurs.
16124     *
16125     * @return the intensity of the right fade as a float between 0.0f and 1.0f
16126     */
16127    protected float getRightFadingEdgeStrength() {
16128        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
16129                computeHorizontalScrollRange() ? 1.0f : 0.0f;
16130    }
16131
16132    /**
16133     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
16134     * scrollbar is not drawn by default.</p>
16135     *
16136     * @return true if the horizontal scrollbar should be painted, false
16137     *         otherwise
16138     *
16139     * @see #setHorizontalScrollBarEnabled(boolean)
16140     */
16141    public boolean isHorizontalScrollBarEnabled() {
16142        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
16143    }
16144
16145    /**
16146     * <p>Define whether the horizontal scrollbar should be drawn or not. The
16147     * scrollbar is not drawn by default.</p>
16148     *
16149     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
16150     *                                   be painted
16151     *
16152     * @see #isHorizontalScrollBarEnabled()
16153     */
16154    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
16155        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
16156            mViewFlags ^= SCROLLBARS_HORIZONTAL;
16157            computeOpaqueFlags();
16158            resolvePadding();
16159        }
16160    }
16161
16162    /**
16163     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
16164     * scrollbar is not drawn by default.</p>
16165     *
16166     * @return true if the vertical scrollbar should be painted, false
16167     *         otherwise
16168     *
16169     * @see #setVerticalScrollBarEnabled(boolean)
16170     */
16171    public boolean isVerticalScrollBarEnabled() {
16172        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
16173    }
16174
16175    /**
16176     * <p>Define whether the vertical scrollbar should be drawn or not. The
16177     * scrollbar is not drawn by default.</p>
16178     *
16179     * @param verticalScrollBarEnabled true if the vertical scrollbar should
16180     *                                 be painted
16181     *
16182     * @see #isVerticalScrollBarEnabled()
16183     */
16184    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
16185        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
16186            mViewFlags ^= SCROLLBARS_VERTICAL;
16187            computeOpaqueFlags();
16188            resolvePadding();
16189        }
16190    }
16191
16192    /**
16193     * @hide
16194     */
16195    protected void recomputePadding() {
16196        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16197    }
16198
16199    /**
16200     * Define whether scrollbars will fade when the view is not scrolling.
16201     *
16202     * @param fadeScrollbars whether to enable fading
16203     *
16204     * @attr ref android.R.styleable#View_fadeScrollbars
16205     */
16206    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
16207        initScrollCache();
16208        final ScrollabilityCache scrollabilityCache = mScrollCache;
16209        scrollabilityCache.fadeScrollBars = fadeScrollbars;
16210        if (fadeScrollbars) {
16211            scrollabilityCache.state = ScrollabilityCache.OFF;
16212        } else {
16213            scrollabilityCache.state = ScrollabilityCache.ON;
16214        }
16215    }
16216
16217    /**
16218     *
16219     * Returns true if scrollbars will fade when this view is not scrolling
16220     *
16221     * @return true if scrollbar fading is enabled
16222     *
16223     * @attr ref android.R.styleable#View_fadeScrollbars
16224     */
16225    public boolean isScrollbarFadingEnabled() {
16226        return mScrollCache != null && mScrollCache.fadeScrollBars;
16227    }
16228
16229    /**
16230     *
16231     * Returns the delay before scrollbars fade.
16232     *
16233     * @return the delay before scrollbars fade
16234     *
16235     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16236     */
16237    public int getScrollBarDefaultDelayBeforeFade() {
16238        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
16239                mScrollCache.scrollBarDefaultDelayBeforeFade;
16240    }
16241
16242    /**
16243     * Define the delay before scrollbars fade.
16244     *
16245     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
16246     *
16247     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16248     */
16249    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
16250        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
16251    }
16252
16253    /**
16254     *
16255     * Returns the scrollbar fade duration.
16256     *
16257     * @return the scrollbar fade duration, in milliseconds
16258     *
16259     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16260     */
16261    public int getScrollBarFadeDuration() {
16262        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
16263                mScrollCache.scrollBarFadeDuration;
16264    }
16265
16266    /**
16267     * Define the scrollbar fade duration.
16268     *
16269     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
16270     *
16271     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16272     */
16273    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
16274        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
16275    }
16276
16277    /**
16278     *
16279     * Returns the scrollbar size.
16280     *
16281     * @return the scrollbar size
16282     *
16283     * @attr ref android.R.styleable#View_scrollbarSize
16284     */
16285    public int getScrollBarSize() {
16286        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
16287                mScrollCache.scrollBarSize;
16288    }
16289
16290    /**
16291     * Define the scrollbar size.
16292     *
16293     * @param scrollBarSize - the scrollbar size
16294     *
16295     * @attr ref android.R.styleable#View_scrollbarSize
16296     */
16297    public void setScrollBarSize(int scrollBarSize) {
16298        getScrollCache().scrollBarSize = scrollBarSize;
16299    }
16300
16301    /**
16302     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
16303     * inset. When inset, they add to the padding of the view. And the scrollbars
16304     * can be drawn inside the padding area or on the edge of the view. For example,
16305     * if a view has a background drawable and you want to draw the scrollbars
16306     * inside the padding specified by the drawable, you can use
16307     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
16308     * appear at the edge of the view, ignoring the padding, then you can use
16309     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
16310     * @param style the style of the scrollbars. Should be one of
16311     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
16312     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
16313     * @see #SCROLLBARS_INSIDE_OVERLAY
16314     * @see #SCROLLBARS_INSIDE_INSET
16315     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16316     * @see #SCROLLBARS_OUTSIDE_INSET
16317     *
16318     * @attr ref android.R.styleable#View_scrollbarStyle
16319     */
16320    public void setScrollBarStyle(@ScrollBarStyle int style) {
16321        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
16322            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
16323            computeOpaqueFlags();
16324            resolvePadding();
16325        }
16326    }
16327
16328    /**
16329     * <p>Returns the current scrollbar style.</p>
16330     * @return the current scrollbar style
16331     * @see #SCROLLBARS_INSIDE_OVERLAY
16332     * @see #SCROLLBARS_INSIDE_INSET
16333     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16334     * @see #SCROLLBARS_OUTSIDE_INSET
16335     *
16336     * @attr ref android.R.styleable#View_scrollbarStyle
16337     */
16338    @ViewDebug.ExportedProperty(mapping = {
16339            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
16340            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
16341            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
16342            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
16343    })
16344    @ScrollBarStyle
16345    public int getScrollBarStyle() {
16346        return mViewFlags & SCROLLBARS_STYLE_MASK;
16347    }
16348
16349    /**
16350     * <p>Compute the horizontal range that the horizontal scrollbar
16351     * represents.</p>
16352     *
16353     * <p>The range is expressed in arbitrary units that must be the same as the
16354     * units used by {@link #computeHorizontalScrollExtent()} and
16355     * {@link #computeHorizontalScrollOffset()}.</p>
16356     *
16357     * <p>The default range is the drawing width of this view.</p>
16358     *
16359     * @return the total horizontal range represented by the horizontal
16360     *         scrollbar
16361     *
16362     * @see #computeHorizontalScrollExtent()
16363     * @see #computeHorizontalScrollOffset()
16364     * @see android.widget.ScrollBarDrawable
16365     */
16366    protected int computeHorizontalScrollRange() {
16367        return getWidth();
16368    }
16369
16370    /**
16371     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16372     * within the horizontal range. This value is used to compute the position
16373     * of the thumb within the scrollbar's track.</p>
16374     *
16375     * <p>The range is expressed in arbitrary units that must be the same as the
16376     * units used by {@link #computeHorizontalScrollRange()} and
16377     * {@link #computeHorizontalScrollExtent()}.</p>
16378     *
16379     * <p>The default offset is the scroll offset of this view.</p>
16380     *
16381     * @return the horizontal offset of the scrollbar's thumb
16382     *
16383     * @see #computeHorizontalScrollRange()
16384     * @see #computeHorizontalScrollExtent()
16385     * @see android.widget.ScrollBarDrawable
16386     */
16387    protected int computeHorizontalScrollOffset() {
16388        return mScrollX;
16389    }
16390
16391    /**
16392     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16393     * within the horizontal range. This value is used to compute the length
16394     * of the thumb within the scrollbar's track.</p>
16395     *
16396     * <p>The range is expressed in arbitrary units that must be the same as the
16397     * units used by {@link #computeHorizontalScrollRange()} and
16398     * {@link #computeHorizontalScrollOffset()}.</p>
16399     *
16400     * <p>The default extent is the drawing width of this view.</p>
16401     *
16402     * @return the horizontal extent of the scrollbar's thumb
16403     *
16404     * @see #computeHorizontalScrollRange()
16405     * @see #computeHorizontalScrollOffset()
16406     * @see android.widget.ScrollBarDrawable
16407     */
16408    protected int computeHorizontalScrollExtent() {
16409        return getWidth();
16410    }
16411
16412    /**
16413     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16414     *
16415     * <p>The range is expressed in arbitrary units that must be the same as the
16416     * units used by {@link #computeVerticalScrollExtent()} and
16417     * {@link #computeVerticalScrollOffset()}.</p>
16418     *
16419     * @return the total vertical range represented by the vertical scrollbar
16420     *
16421     * <p>The default range is the drawing height of this view.</p>
16422     *
16423     * @see #computeVerticalScrollExtent()
16424     * @see #computeVerticalScrollOffset()
16425     * @see android.widget.ScrollBarDrawable
16426     */
16427    protected int computeVerticalScrollRange() {
16428        return getHeight();
16429    }
16430
16431    /**
16432     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16433     * within the horizontal range. This value is used to compute the position
16434     * of the thumb within the scrollbar's track.</p>
16435     *
16436     * <p>The range is expressed in arbitrary units that must be the same as the
16437     * units used by {@link #computeVerticalScrollRange()} and
16438     * {@link #computeVerticalScrollExtent()}.</p>
16439     *
16440     * <p>The default offset is the scroll offset of this view.</p>
16441     *
16442     * @return the vertical offset of the scrollbar's thumb
16443     *
16444     * @see #computeVerticalScrollRange()
16445     * @see #computeVerticalScrollExtent()
16446     * @see android.widget.ScrollBarDrawable
16447     */
16448    protected int computeVerticalScrollOffset() {
16449        return mScrollY;
16450    }
16451
16452    /**
16453     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16454     * within the vertical range. This value is used to compute the length
16455     * of the thumb within the scrollbar's track.</p>
16456     *
16457     * <p>The range is expressed in arbitrary units that must be the same as the
16458     * units used by {@link #computeVerticalScrollRange()} and
16459     * {@link #computeVerticalScrollOffset()}.</p>
16460     *
16461     * <p>The default extent is the drawing height of this view.</p>
16462     *
16463     * @return the vertical extent of the scrollbar's thumb
16464     *
16465     * @see #computeVerticalScrollRange()
16466     * @see #computeVerticalScrollOffset()
16467     * @see android.widget.ScrollBarDrawable
16468     */
16469    protected int computeVerticalScrollExtent() {
16470        return getHeight();
16471    }
16472
16473    /**
16474     * Check if this view can be scrolled horizontally in a certain direction.
16475     *
16476     * @param direction Negative to check scrolling left, positive to check scrolling right.
16477     * @return true if this view can be scrolled in the specified direction, false otherwise.
16478     */
16479    public boolean canScrollHorizontally(int direction) {
16480        final int offset = computeHorizontalScrollOffset();
16481        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16482        if (range == 0) return false;
16483        if (direction < 0) {
16484            return offset > 0;
16485        } else {
16486            return offset < range - 1;
16487        }
16488    }
16489
16490    /**
16491     * Check if this view can be scrolled vertically in a certain direction.
16492     *
16493     * @param direction Negative to check scrolling up, positive to check scrolling down.
16494     * @return true if this view can be scrolled in the specified direction, false otherwise.
16495     */
16496    public boolean canScrollVertically(int direction) {
16497        final int offset = computeVerticalScrollOffset();
16498        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16499        if (range == 0) return false;
16500        if (direction < 0) {
16501            return offset > 0;
16502        } else {
16503            return offset < range - 1;
16504        }
16505    }
16506
16507    void getScrollIndicatorBounds(@NonNull Rect out) {
16508        out.left = mScrollX;
16509        out.right = mScrollX + mRight - mLeft;
16510        out.top = mScrollY;
16511        out.bottom = mScrollY + mBottom - mTop;
16512    }
16513
16514    private void onDrawScrollIndicators(Canvas c) {
16515        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16516            // No scroll indicators enabled.
16517            return;
16518        }
16519
16520        final Drawable dr = mScrollIndicatorDrawable;
16521        if (dr == null) {
16522            // Scroll indicators aren't supported here.
16523            return;
16524        }
16525
16526        final int h = dr.getIntrinsicHeight();
16527        final int w = dr.getIntrinsicWidth();
16528        final Rect rect = mAttachInfo.mTmpInvalRect;
16529        getScrollIndicatorBounds(rect);
16530
16531        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16532            final boolean canScrollUp = canScrollVertically(-1);
16533            if (canScrollUp) {
16534                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16535                dr.draw(c);
16536            }
16537        }
16538
16539        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16540            final boolean canScrollDown = canScrollVertically(1);
16541            if (canScrollDown) {
16542                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16543                dr.draw(c);
16544            }
16545        }
16546
16547        final int leftRtl;
16548        final int rightRtl;
16549        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16550            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16551            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16552        } else {
16553            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16554            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16555        }
16556
16557        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16558        if ((mPrivateFlags3 & leftMask) != 0) {
16559            final boolean canScrollLeft = canScrollHorizontally(-1);
16560            if (canScrollLeft) {
16561                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16562                dr.draw(c);
16563            }
16564        }
16565
16566        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16567        if ((mPrivateFlags3 & rightMask) != 0) {
16568            final boolean canScrollRight = canScrollHorizontally(1);
16569            if (canScrollRight) {
16570                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16571                dr.draw(c);
16572            }
16573        }
16574    }
16575
16576    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16577            @Nullable Rect touchBounds) {
16578        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16579        if (bounds == null) {
16580            return;
16581        }
16582        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16583        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16584                && !isVerticalScrollBarHidden();
16585        final int size = getHorizontalScrollbarHeight();
16586        final int verticalScrollBarGap = drawVerticalScrollBar ?
16587                getVerticalScrollbarWidth() : 0;
16588        final int width = mRight - mLeft;
16589        final int height = mBottom - mTop;
16590        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16591        bounds.left = mScrollX + (mPaddingLeft & inside);
16592        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16593        bounds.bottom = bounds.top + size;
16594
16595        if (touchBounds == null) {
16596            return;
16597        }
16598        if (touchBounds != bounds) {
16599            touchBounds.set(bounds);
16600        }
16601        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16602        if (touchBounds.height() < minTouchTarget) {
16603            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16604            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16605            touchBounds.top = touchBounds.bottom - minTouchTarget;
16606        }
16607        if (touchBounds.width() < minTouchTarget) {
16608            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16609            touchBounds.left -= adjust;
16610            touchBounds.right = touchBounds.left + minTouchTarget;
16611        }
16612    }
16613
16614    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16615        if (mRoundScrollbarRenderer == null) {
16616            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16617        } else {
16618            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16619        }
16620    }
16621
16622    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16623        final int width = mRight - mLeft;
16624        final int height = mBottom - mTop;
16625        // Do not take padding into account as we always want the scrollbars
16626        // to hug the screen for round wearable devices.
16627        bounds.left = mScrollX;
16628        bounds.top = mScrollY;
16629        bounds.right = bounds.left + width;
16630        bounds.bottom = mScrollY + height;
16631    }
16632
16633    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16634            @Nullable Rect touchBounds) {
16635        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16636        if (bounds == null) {
16637            return;
16638        }
16639        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16640        final int size = getVerticalScrollbarWidth();
16641        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16642        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16643            verticalScrollbarPosition = isLayoutRtl() ?
16644                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16645        }
16646        final int width = mRight - mLeft;
16647        final int height = mBottom - mTop;
16648        switch (verticalScrollbarPosition) {
16649            default:
16650            case SCROLLBAR_POSITION_RIGHT:
16651                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16652                break;
16653            case SCROLLBAR_POSITION_LEFT:
16654                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16655                break;
16656        }
16657        bounds.top = mScrollY + (mPaddingTop & inside);
16658        bounds.right = bounds.left + size;
16659        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16660
16661        if (touchBounds == null) {
16662            return;
16663        }
16664        if (touchBounds != bounds) {
16665            touchBounds.set(bounds);
16666        }
16667        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16668        if (touchBounds.width() < minTouchTarget) {
16669            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16670            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16671                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16672                touchBounds.left = touchBounds.right - minTouchTarget;
16673            } else {
16674                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16675                touchBounds.right = touchBounds.left + minTouchTarget;
16676            }
16677        }
16678        if (touchBounds.height() < minTouchTarget) {
16679            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16680            touchBounds.top -= adjust;
16681            touchBounds.bottom = touchBounds.top + minTouchTarget;
16682        }
16683    }
16684
16685    /**
16686     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16687     * scrollbars are painted only if they have been awakened first.</p>
16688     *
16689     * @param canvas the canvas on which to draw the scrollbars
16690     *
16691     * @see #awakenScrollBars(int)
16692     */
16693    protected final void onDrawScrollBars(Canvas canvas) {
16694        // scrollbars are drawn only when the animation is running
16695        final ScrollabilityCache cache = mScrollCache;
16696
16697        if (cache != null) {
16698
16699            int state = cache.state;
16700
16701            if (state == ScrollabilityCache.OFF) {
16702                return;
16703            }
16704
16705            boolean invalidate = false;
16706
16707            if (state == ScrollabilityCache.FADING) {
16708                // We're fading -- get our fade interpolation
16709                if (cache.interpolatorValues == null) {
16710                    cache.interpolatorValues = new float[1];
16711                }
16712
16713                float[] values = cache.interpolatorValues;
16714
16715                // Stops the animation if we're done
16716                if (cache.scrollBarInterpolator.timeToValues(values) ==
16717                        Interpolator.Result.FREEZE_END) {
16718                    cache.state = ScrollabilityCache.OFF;
16719                } else {
16720                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16721                }
16722
16723                // This will make the scroll bars inval themselves after
16724                // drawing. We only want this when we're fading so that
16725                // we prevent excessive redraws
16726                invalidate = true;
16727            } else {
16728                // We're just on -- but we may have been fading before so
16729                // reset alpha
16730                cache.scrollBar.mutate().setAlpha(255);
16731            }
16732
16733            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16734            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16735                    && !isVerticalScrollBarHidden();
16736
16737            // Fork out the scroll bar drawing for round wearable devices.
16738            if (mRoundScrollbarRenderer != null) {
16739                if (drawVerticalScrollBar) {
16740                    final Rect bounds = cache.mScrollBarBounds;
16741                    getVerticalScrollBarBounds(bounds, null);
16742                    mRoundScrollbarRenderer.drawRoundScrollbars(
16743                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16744                    if (invalidate) {
16745                        invalidate();
16746                    }
16747                }
16748                // Do not draw horizontal scroll bars for round wearable devices.
16749            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16750                final ScrollBarDrawable scrollBar = cache.scrollBar;
16751
16752                if (drawHorizontalScrollBar) {
16753                    scrollBar.setParameters(computeHorizontalScrollRange(),
16754                            computeHorizontalScrollOffset(),
16755                            computeHorizontalScrollExtent(), false);
16756                    final Rect bounds = cache.mScrollBarBounds;
16757                    getHorizontalScrollBarBounds(bounds, null);
16758                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16759                            bounds.right, bounds.bottom);
16760                    if (invalidate) {
16761                        invalidate(bounds);
16762                    }
16763                }
16764
16765                if (drawVerticalScrollBar) {
16766                    scrollBar.setParameters(computeVerticalScrollRange(),
16767                            computeVerticalScrollOffset(),
16768                            computeVerticalScrollExtent(), true);
16769                    final Rect bounds = cache.mScrollBarBounds;
16770                    getVerticalScrollBarBounds(bounds, null);
16771                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16772                            bounds.right, bounds.bottom);
16773                    if (invalidate) {
16774                        invalidate(bounds);
16775                    }
16776                }
16777            }
16778        }
16779    }
16780
16781    /**
16782     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16783     * FastScroller is visible.
16784     * @return whether to temporarily hide the vertical scrollbar
16785     * @hide
16786     */
16787    protected boolean isVerticalScrollBarHidden() {
16788        return false;
16789    }
16790
16791    /**
16792     * <p>Draw the horizontal scrollbar if
16793     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16794     *
16795     * @param canvas the canvas on which to draw the scrollbar
16796     * @param scrollBar the scrollbar's drawable
16797     *
16798     * @see #isHorizontalScrollBarEnabled()
16799     * @see #computeHorizontalScrollRange()
16800     * @see #computeHorizontalScrollExtent()
16801     * @see #computeHorizontalScrollOffset()
16802     * @see android.widget.ScrollBarDrawable
16803     * @hide
16804     */
16805    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16806            int l, int t, int r, int b) {
16807        scrollBar.setBounds(l, t, r, b);
16808        scrollBar.draw(canvas);
16809    }
16810
16811    /**
16812     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16813     * returns true.</p>
16814     *
16815     * @param canvas the canvas on which to draw the scrollbar
16816     * @param scrollBar the scrollbar's drawable
16817     *
16818     * @see #isVerticalScrollBarEnabled()
16819     * @see #computeVerticalScrollRange()
16820     * @see #computeVerticalScrollExtent()
16821     * @see #computeVerticalScrollOffset()
16822     * @see android.widget.ScrollBarDrawable
16823     * @hide
16824     */
16825    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16826            int l, int t, int r, int b) {
16827        scrollBar.setBounds(l, t, r, b);
16828        scrollBar.draw(canvas);
16829    }
16830
16831    /**
16832     * Implement this to do your drawing.
16833     *
16834     * @param canvas the canvas on which the background will be drawn
16835     */
16836    protected void onDraw(Canvas canvas) {
16837    }
16838
16839    /*
16840     * Caller is responsible for calling requestLayout if necessary.
16841     * (This allows addViewInLayout to not request a new layout.)
16842     */
16843    void assignParent(ViewParent parent) {
16844        if (mParent == null) {
16845            mParent = parent;
16846        } else if (parent == null) {
16847            mParent = null;
16848        } else {
16849            throw new RuntimeException("view " + this + " being added, but"
16850                    + " it already has a parent");
16851        }
16852    }
16853
16854    /**
16855     * This is called when the view is attached to a window.  At this point it
16856     * has a Surface and will start drawing.  Note that this function is
16857     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16858     * however it may be called any time before the first onDraw -- including
16859     * before or after {@link #onMeasure(int, int)}.
16860     *
16861     * @see #onDetachedFromWindow()
16862     */
16863    @CallSuper
16864    protected void onAttachedToWindow() {
16865        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16866            mParent.requestTransparentRegion(this);
16867        }
16868
16869        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16870
16871        jumpDrawablesToCurrentState();
16872
16873        resetSubtreeAccessibilityStateChanged();
16874
16875        // rebuild, since Outline not maintained while View is detached
16876        rebuildOutline();
16877
16878        if (isFocused()) {
16879            InputMethodManager imm = InputMethodManager.peekInstance();
16880            if (imm != null) {
16881                imm.focusIn(this);
16882            }
16883        }
16884    }
16885
16886    /**
16887     * Resolve all RTL related properties.
16888     *
16889     * @return true if resolution of RTL properties has been done
16890     *
16891     * @hide
16892     */
16893    public boolean resolveRtlPropertiesIfNeeded() {
16894        if (!needRtlPropertiesResolution()) return false;
16895
16896        // Order is important here: LayoutDirection MUST be resolved first
16897        if (!isLayoutDirectionResolved()) {
16898            resolveLayoutDirection();
16899            resolveLayoutParams();
16900        }
16901        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16902        if (!isTextDirectionResolved()) {
16903            resolveTextDirection();
16904        }
16905        if (!isTextAlignmentResolved()) {
16906            resolveTextAlignment();
16907        }
16908        // Should resolve Drawables before Padding because we need the layout direction of the
16909        // Drawable to correctly resolve Padding.
16910        if (!areDrawablesResolved()) {
16911            resolveDrawables();
16912        }
16913        if (!isPaddingResolved()) {
16914            resolvePadding();
16915        }
16916        onRtlPropertiesChanged(getLayoutDirection());
16917        return true;
16918    }
16919
16920    /**
16921     * Reset resolution of all RTL related properties.
16922     *
16923     * @hide
16924     */
16925    public void resetRtlProperties() {
16926        resetResolvedLayoutDirection();
16927        resetResolvedTextDirection();
16928        resetResolvedTextAlignment();
16929        resetResolvedPadding();
16930        resetResolvedDrawables();
16931    }
16932
16933    /**
16934     * @see #onScreenStateChanged(int)
16935     */
16936    void dispatchScreenStateChanged(int screenState) {
16937        onScreenStateChanged(screenState);
16938    }
16939
16940    /**
16941     * This method is called whenever the state of the screen this view is
16942     * attached to changes. A state change will usually occurs when the screen
16943     * turns on or off (whether it happens automatically or the user does it
16944     * manually.)
16945     *
16946     * @param screenState The new state of the screen. Can be either
16947     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16948     */
16949    public void onScreenStateChanged(int screenState) {
16950    }
16951
16952    /**
16953     * @see #onMovedToDisplay(int, Configuration)
16954     */
16955    void dispatchMovedToDisplay(Display display, Configuration config) {
16956        mAttachInfo.mDisplay = display;
16957        mAttachInfo.mDisplayState = display.getState();
16958        onMovedToDisplay(display.getDisplayId(), config);
16959    }
16960
16961    /**
16962     * Called by the system when the hosting activity is moved from one display to another without
16963     * recreation. This means that the activity is declared to handle all changes to configuration
16964     * that happened when it was switched to another display, so it wasn't destroyed and created
16965     * again.
16966     *
16967     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16968     * applied configuration actually changed. It is up to app developer to choose whether to handle
16969     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16970     * call.
16971     *
16972     * <p>Use this callback to track changes to the displays if some functionality relies on an
16973     * association with some display properties.
16974     *
16975     * @param displayId The id of the display to which the view was moved.
16976     * @param config Configuration of the resources on new display after move.
16977     *
16978     * @see #onConfigurationChanged(Configuration)
16979     * @hide
16980     */
16981    public void onMovedToDisplay(int displayId, Configuration config) {
16982    }
16983
16984    /**
16985     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16986     */
16987    private boolean hasRtlSupport() {
16988        return mContext.getApplicationInfo().hasRtlSupport();
16989    }
16990
16991    /**
16992     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16993     * RTL not supported)
16994     */
16995    private boolean isRtlCompatibilityMode() {
16996        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16997        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16998    }
16999
17000    /**
17001     * @return true if RTL properties need resolution.
17002     *
17003     */
17004    private boolean needRtlPropertiesResolution() {
17005        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
17006    }
17007
17008    /**
17009     * Called when any RTL property (layout direction or text direction or text alignment) has
17010     * been changed.
17011     *
17012     * Subclasses need to override this method to take care of cached information that depends on the
17013     * resolved layout direction, or to inform child views that inherit their layout direction.
17014     *
17015     * The default implementation does nothing.
17016     *
17017     * @param layoutDirection the direction of the layout
17018     *
17019     * @see #LAYOUT_DIRECTION_LTR
17020     * @see #LAYOUT_DIRECTION_RTL
17021     */
17022    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
17023    }
17024
17025    /**
17026     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
17027     * that the parent directionality can and will be resolved before its children.
17028     *
17029     * @return true if resolution has been done, false otherwise.
17030     *
17031     * @hide
17032     */
17033    public boolean resolveLayoutDirection() {
17034        // Clear any previous layout direction resolution
17035        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17036
17037        if (hasRtlSupport()) {
17038            // Set resolved depending on layout direction
17039            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
17040                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
17041                case LAYOUT_DIRECTION_INHERIT:
17042                    // We cannot resolve yet. LTR is by default and let the resolution happen again
17043                    // later to get the correct resolved value
17044                    if (!canResolveLayoutDirection()) return false;
17045
17046                    // Parent has not yet resolved, LTR is still the default
17047                    try {
17048                        if (!mParent.isLayoutDirectionResolved()) return false;
17049
17050                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
17051                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17052                        }
17053                    } catch (AbstractMethodError e) {
17054                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17055                                " does not fully implement ViewParent", e);
17056                    }
17057                    break;
17058                case LAYOUT_DIRECTION_RTL:
17059                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17060                    break;
17061                case LAYOUT_DIRECTION_LOCALE:
17062                    if((LAYOUT_DIRECTION_RTL ==
17063                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
17064                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17065                    }
17066                    break;
17067                default:
17068                    // Nothing to do, LTR by default
17069            }
17070        }
17071
17072        // Set to resolved
17073        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17074        return true;
17075    }
17076
17077    /**
17078     * Check if layout direction resolution can be done.
17079     *
17080     * @return true if layout direction resolution can be done otherwise return false.
17081     */
17082    public boolean canResolveLayoutDirection() {
17083        switch (getRawLayoutDirection()) {
17084            case LAYOUT_DIRECTION_INHERIT:
17085                if (mParent != null) {
17086                    try {
17087                        return mParent.canResolveLayoutDirection();
17088                    } catch (AbstractMethodError e) {
17089                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17090                                " does not fully implement ViewParent", e);
17091                    }
17092                }
17093                return false;
17094
17095            default:
17096                return true;
17097        }
17098    }
17099
17100    /**
17101     * Reset the resolved layout direction. Layout direction will be resolved during a call to
17102     * {@link #onMeasure(int, int)}.
17103     *
17104     * @hide
17105     */
17106    public void resetResolvedLayoutDirection() {
17107        // Reset the current resolved bits
17108        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17109    }
17110
17111    /**
17112     * @return true if the layout direction is inherited.
17113     *
17114     * @hide
17115     */
17116    public boolean isLayoutDirectionInherited() {
17117        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
17118    }
17119
17120    /**
17121     * @return true if layout direction has been resolved.
17122     */
17123    public boolean isLayoutDirectionResolved() {
17124        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17125    }
17126
17127    /**
17128     * Return if padding has been resolved
17129     *
17130     * @hide
17131     */
17132    boolean isPaddingResolved() {
17133        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
17134    }
17135
17136    /**
17137     * Resolves padding depending on layout direction, if applicable, and
17138     * recomputes internal padding values to adjust for scroll bars.
17139     *
17140     * @hide
17141     */
17142    public void resolvePadding() {
17143        final int resolvedLayoutDirection = getLayoutDirection();
17144
17145        if (!isRtlCompatibilityMode()) {
17146            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
17147            // If start / end padding are defined, they will be resolved (hence overriding) to
17148            // left / right or right / left depending on the resolved layout direction.
17149            // If start / end padding are not defined, use the left / right ones.
17150            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
17151                Rect padding = sThreadLocal.get();
17152                if (padding == null) {
17153                    padding = new Rect();
17154                    sThreadLocal.set(padding);
17155                }
17156                mBackground.getPadding(padding);
17157                if (!mLeftPaddingDefined) {
17158                    mUserPaddingLeftInitial = padding.left;
17159                }
17160                if (!mRightPaddingDefined) {
17161                    mUserPaddingRightInitial = padding.right;
17162                }
17163            }
17164            switch (resolvedLayoutDirection) {
17165                case LAYOUT_DIRECTION_RTL:
17166                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17167                        mUserPaddingRight = mUserPaddingStart;
17168                    } else {
17169                        mUserPaddingRight = mUserPaddingRightInitial;
17170                    }
17171                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17172                        mUserPaddingLeft = mUserPaddingEnd;
17173                    } else {
17174                        mUserPaddingLeft = mUserPaddingLeftInitial;
17175                    }
17176                    break;
17177                case LAYOUT_DIRECTION_LTR:
17178                default:
17179                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17180                        mUserPaddingLeft = mUserPaddingStart;
17181                    } else {
17182                        mUserPaddingLeft = mUserPaddingLeftInitial;
17183                    }
17184                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17185                        mUserPaddingRight = mUserPaddingEnd;
17186                    } else {
17187                        mUserPaddingRight = mUserPaddingRightInitial;
17188                    }
17189            }
17190
17191            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
17192        }
17193
17194        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17195        onRtlPropertiesChanged(resolvedLayoutDirection);
17196
17197        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
17198    }
17199
17200    /**
17201     * Reset the resolved layout direction.
17202     *
17203     * @hide
17204     */
17205    public void resetResolvedPadding() {
17206        resetResolvedPaddingInternal();
17207    }
17208
17209    /**
17210     * Used when we only want to reset *this* view's padding and not trigger overrides
17211     * in ViewGroup that reset children too.
17212     */
17213    void resetResolvedPaddingInternal() {
17214        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
17215    }
17216
17217    /**
17218     * This is called when the view is detached from a window.  At this point it
17219     * no longer has a surface for drawing.
17220     *
17221     * @see #onAttachedToWindow()
17222     */
17223    @CallSuper
17224    protected void onDetachedFromWindow() {
17225    }
17226
17227    /**
17228     * This is a framework-internal mirror of onDetachedFromWindow() that's called
17229     * after onDetachedFromWindow().
17230     *
17231     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
17232     * The super method should be called at the end of the overridden method to ensure
17233     * subclasses are destroyed first
17234     *
17235     * @hide
17236     */
17237    @CallSuper
17238    protected void onDetachedFromWindowInternal() {
17239        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
17240        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17241        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
17242
17243        removeUnsetPressCallback();
17244        removeLongPressCallback();
17245        removePerformClickCallback();
17246        removeSendViewScrolledAccessibilityEventCallback();
17247        stopNestedScroll();
17248
17249        // Anything that started animating right before detach should already
17250        // be in its final state when re-attached.
17251        jumpDrawablesToCurrentState();
17252
17253        destroyDrawingCache();
17254
17255        cleanupDraw();
17256        mCurrentAnimation = null;
17257
17258        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
17259            hideTooltip();
17260        }
17261    }
17262
17263    private void cleanupDraw() {
17264        resetDisplayList();
17265        if (mAttachInfo != null) {
17266            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
17267        }
17268    }
17269
17270    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
17271    }
17272
17273    /**
17274     * @return The number of times this view has been attached to a window
17275     */
17276    protected int getWindowAttachCount() {
17277        return mWindowAttachCount;
17278    }
17279
17280    /**
17281     * Retrieve a unique token identifying the window this view is attached to.
17282     * @return Return the window's token for use in
17283     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
17284     */
17285    public IBinder getWindowToken() {
17286        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
17287    }
17288
17289    /**
17290     * Retrieve the {@link WindowId} for the window this view is
17291     * currently attached to.
17292     */
17293    public WindowId getWindowId() {
17294        if (mAttachInfo == null) {
17295            return null;
17296        }
17297        if (mAttachInfo.mWindowId == null) {
17298            try {
17299                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
17300                        mAttachInfo.mWindowToken);
17301                mAttachInfo.mWindowId = new WindowId(
17302                        mAttachInfo.mIWindowId);
17303            } catch (RemoteException e) {
17304            }
17305        }
17306        return mAttachInfo.mWindowId;
17307    }
17308
17309    /**
17310     * Retrieve a unique token identifying the top-level "real" window of
17311     * the window that this view is attached to.  That is, this is like
17312     * {@link #getWindowToken}, except if the window this view in is a panel
17313     * window (attached to another containing window), then the token of
17314     * the containing window is returned instead.
17315     *
17316     * @return Returns the associated window token, either
17317     * {@link #getWindowToken()} or the containing window's token.
17318     */
17319    public IBinder getApplicationWindowToken() {
17320        AttachInfo ai = mAttachInfo;
17321        if (ai != null) {
17322            IBinder appWindowToken = ai.mPanelParentWindowToken;
17323            if (appWindowToken == null) {
17324                appWindowToken = ai.mWindowToken;
17325            }
17326            return appWindowToken;
17327        }
17328        return null;
17329    }
17330
17331    /**
17332     * Gets the logical display to which the view's window has been attached.
17333     *
17334     * @return The logical display, or null if the view is not currently attached to a window.
17335     */
17336    public Display getDisplay() {
17337        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
17338    }
17339
17340    /**
17341     * Retrieve private session object this view hierarchy is using to
17342     * communicate with the window manager.
17343     * @return the session object to communicate with the window manager
17344     */
17345    /*package*/ IWindowSession getWindowSession() {
17346        return mAttachInfo != null ? mAttachInfo.mSession : null;
17347    }
17348
17349    /**
17350     * Return the visibility value of the least visible component passed.
17351     */
17352    int combineVisibility(int vis1, int vis2) {
17353        // This works because VISIBLE < INVISIBLE < GONE.
17354        return Math.max(vis1, vis2);
17355    }
17356
17357    /**
17358     * @param info the {@link android.view.View.AttachInfo} to associated with
17359     *        this view
17360     */
17361    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17362        mAttachInfo = info;
17363        if (mOverlay != null) {
17364            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17365        }
17366        mWindowAttachCount++;
17367        // We will need to evaluate the drawable state at least once.
17368        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17369        if (mFloatingTreeObserver != null) {
17370            info.mTreeObserver.merge(mFloatingTreeObserver);
17371            mFloatingTreeObserver = null;
17372        }
17373
17374        registerPendingFrameMetricsObservers();
17375
17376        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17377            mAttachInfo.mScrollContainers.add(this);
17378            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17379        }
17380        // Transfer all pending runnables.
17381        if (mRunQueue != null) {
17382            mRunQueue.executeActions(info.mHandler);
17383            mRunQueue = null;
17384        }
17385        performCollectViewAttributes(mAttachInfo, visibility);
17386        onAttachedToWindow();
17387
17388        ListenerInfo li = mListenerInfo;
17389        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17390                li != null ? li.mOnAttachStateChangeListeners : null;
17391        if (listeners != null && listeners.size() > 0) {
17392            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17393            // perform the dispatching. The iterator is a safe guard against listeners that
17394            // could mutate the list by calling the various add/remove methods. This prevents
17395            // the array from being modified while we iterate it.
17396            for (OnAttachStateChangeListener listener : listeners) {
17397                listener.onViewAttachedToWindow(this);
17398            }
17399        }
17400
17401        int vis = info.mWindowVisibility;
17402        if (vis != GONE) {
17403            onWindowVisibilityChanged(vis);
17404            if (isShown()) {
17405                // Calling onVisibilityAggregated directly here since the subtree will also
17406                // receive dispatchAttachedToWindow and this same call
17407                onVisibilityAggregated(vis == VISIBLE);
17408            }
17409        }
17410
17411        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17412        // As all views in the subtree will already receive dispatchAttachedToWindow
17413        // traversing the subtree again here is not desired.
17414        onVisibilityChanged(this, visibility);
17415
17416        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17417            // If nobody has evaluated the drawable state yet, then do it now.
17418            refreshDrawableState();
17419        }
17420        needGlobalAttributesUpdate(false);
17421
17422        notifyEnterOrExitForAutoFillIfNeeded(true);
17423    }
17424
17425    void dispatchDetachedFromWindow() {
17426        AttachInfo info = mAttachInfo;
17427        if (info != null) {
17428            int vis = info.mWindowVisibility;
17429            if (vis != GONE) {
17430                onWindowVisibilityChanged(GONE);
17431                if (isShown()) {
17432                    // Invoking onVisibilityAggregated directly here since the subtree
17433                    // will also receive detached from window
17434                    onVisibilityAggregated(false);
17435                }
17436            }
17437        }
17438
17439        onDetachedFromWindow();
17440        onDetachedFromWindowInternal();
17441
17442        InputMethodManager imm = InputMethodManager.peekInstance();
17443        if (imm != null) {
17444            imm.onViewDetachedFromWindow(this);
17445        }
17446
17447        ListenerInfo li = mListenerInfo;
17448        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17449                li != null ? li.mOnAttachStateChangeListeners : null;
17450        if (listeners != null && listeners.size() > 0) {
17451            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17452            // perform the dispatching. The iterator is a safe guard against listeners that
17453            // could mutate the list by calling the various add/remove methods. This prevents
17454            // the array from being modified while we iterate it.
17455            for (OnAttachStateChangeListener listener : listeners) {
17456                listener.onViewDetachedFromWindow(this);
17457            }
17458        }
17459
17460        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17461            mAttachInfo.mScrollContainers.remove(this);
17462            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17463        }
17464
17465        mAttachInfo = null;
17466        if (mOverlay != null) {
17467            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17468        }
17469
17470        notifyEnterOrExitForAutoFillIfNeeded(false);
17471    }
17472
17473    /**
17474     * Cancel any deferred high-level input events that were previously posted to the event queue.
17475     *
17476     * <p>Many views post high-level events such as click handlers to the event queue
17477     * to run deferred in order to preserve a desired user experience - clearing visible
17478     * pressed states before executing, etc. This method will abort any events of this nature
17479     * that are currently in flight.</p>
17480     *
17481     * <p>Custom views that generate their own high-level deferred input events should override
17482     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17483     *
17484     * <p>This will also cancel pending input events for any child views.</p>
17485     *
17486     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17487     * This will not impact newer events posted after this call that may occur as a result of
17488     * lower-level input events still waiting in the queue. If you are trying to prevent
17489     * double-submitted  events for the duration of some sort of asynchronous transaction
17490     * you should also take other steps to protect against unexpected double inputs e.g. calling
17491     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17492     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17493     */
17494    public final void cancelPendingInputEvents() {
17495        dispatchCancelPendingInputEvents();
17496    }
17497
17498    /**
17499     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17500     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17501     */
17502    void dispatchCancelPendingInputEvents() {
17503        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17504        onCancelPendingInputEvents();
17505        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17506            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17507                    " did not call through to super.onCancelPendingInputEvents()");
17508        }
17509    }
17510
17511    /**
17512     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17513     * a parent view.
17514     *
17515     * <p>This method is responsible for removing any pending high-level input events that were
17516     * posted to the event queue to run later. Custom view classes that post their own deferred
17517     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17518     * {@link android.os.Handler} should override this method, call
17519     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17520     * </p>
17521     */
17522    public void onCancelPendingInputEvents() {
17523        removePerformClickCallback();
17524        cancelLongPress();
17525        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17526    }
17527
17528    /**
17529     * Store this view hierarchy's frozen state into the given container.
17530     *
17531     * @param container The SparseArray in which to save the view's state.
17532     *
17533     * @see #restoreHierarchyState(android.util.SparseArray)
17534     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17535     * @see #onSaveInstanceState()
17536     */
17537    public void saveHierarchyState(SparseArray<Parcelable> container) {
17538        dispatchSaveInstanceState(container);
17539    }
17540
17541    /**
17542     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17543     * this view and its children. May be overridden to modify how freezing happens to a
17544     * view's children; for example, some views may want to not store state for their children.
17545     *
17546     * @param container The SparseArray in which to save the view's state.
17547     *
17548     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17549     * @see #saveHierarchyState(android.util.SparseArray)
17550     * @see #onSaveInstanceState()
17551     */
17552    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17553        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17554            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17555            Parcelable state = onSaveInstanceState();
17556            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17557                throw new IllegalStateException(
17558                        "Derived class did not call super.onSaveInstanceState()");
17559            }
17560            if (state != null) {
17561                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17562                // + ": " + state);
17563                container.put(mID, state);
17564            }
17565        }
17566    }
17567
17568    /**
17569     * Hook allowing a view to generate a representation of its internal state
17570     * that can later be used to create a new instance with that same state.
17571     * This state should only contain information that is not persistent or can
17572     * not be reconstructed later. For example, you will never store your
17573     * current position on screen because that will be computed again when a
17574     * new instance of the view is placed in its view hierarchy.
17575     * <p>
17576     * Some examples of things you may store here: the current cursor position
17577     * in a text view (but usually not the text itself since that is stored in a
17578     * content provider or other persistent storage), the currently selected
17579     * item in a list view.
17580     *
17581     * @return Returns a Parcelable object containing the view's current dynamic
17582     *         state, or null if there is nothing interesting to save.
17583     * @see #onRestoreInstanceState(Parcelable)
17584     * @see #saveHierarchyState(SparseArray)
17585     * @see #dispatchSaveInstanceState(SparseArray)
17586     * @see #setSaveEnabled(boolean)
17587     */
17588    @CallSuper
17589    @Nullable protected Parcelable onSaveInstanceState() {
17590        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17591        if (mStartActivityRequestWho != null || isAutofilled()
17592                || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17593            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17594
17595            if (mStartActivityRequestWho != null) {
17596                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17597            }
17598
17599            if (isAutofilled()) {
17600                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17601            }
17602
17603            if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17604                state.mSavedData |= BaseSavedState.AUTOFILL_ID;
17605            }
17606
17607            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17608            state.mIsAutofilled = isAutofilled();
17609            state.mAutofillViewId = mAutofillViewId;
17610            return state;
17611        }
17612        return BaseSavedState.EMPTY_STATE;
17613    }
17614
17615    /**
17616     * Restore this view hierarchy's frozen state from the given container.
17617     *
17618     * @param container The SparseArray which holds previously frozen states.
17619     *
17620     * @see #saveHierarchyState(android.util.SparseArray)
17621     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17622     * @see #onRestoreInstanceState(android.os.Parcelable)
17623     */
17624    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17625        dispatchRestoreInstanceState(container);
17626    }
17627
17628    /**
17629     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17630     * state for this view and its children. May be overridden to modify how restoring
17631     * happens to a view's children; for example, some views may want to not store state
17632     * for their children.
17633     *
17634     * @param container The SparseArray which holds previously saved state.
17635     *
17636     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17637     * @see #restoreHierarchyState(android.util.SparseArray)
17638     * @see #onRestoreInstanceState(android.os.Parcelable)
17639     */
17640    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17641        if (mID != NO_ID) {
17642            Parcelable state = container.get(mID);
17643            if (state != null) {
17644                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17645                // + ": " + state);
17646                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17647                onRestoreInstanceState(state);
17648                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17649                    throw new IllegalStateException(
17650                            "Derived class did not call super.onRestoreInstanceState()");
17651                }
17652            }
17653        }
17654    }
17655
17656    /**
17657     * Hook allowing a view to re-apply a representation of its internal state that had previously
17658     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17659     * null state.
17660     *
17661     * @param state The frozen state that had previously been returned by
17662     *        {@link #onSaveInstanceState}.
17663     *
17664     * @see #onSaveInstanceState()
17665     * @see #restoreHierarchyState(android.util.SparseArray)
17666     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17667     */
17668    @CallSuper
17669    protected void onRestoreInstanceState(Parcelable state) {
17670        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17671        if (state != null && !(state instanceof AbsSavedState)) {
17672            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17673                    + "received " + state.getClass().toString() + " instead. This usually happens "
17674                    + "when two views of different type have the same id in the same hierarchy. "
17675                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17676                    + "other views do not use the same id.");
17677        }
17678        if (state != null && state instanceof BaseSavedState) {
17679            BaseSavedState baseState = (BaseSavedState) state;
17680
17681            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17682                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17683            }
17684            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17685                setAutofilled(baseState.mIsAutofilled);
17686            }
17687            if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
17688                // It can happen that views have the same view id and the restoration path will not
17689                // be able to distinguish between them. The autofill id needs to be unique though.
17690                // Hence prevent the same autofill view id from being restored multiple times.
17691                ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
17692
17693                mAutofillViewId = baseState.mAutofillViewId;
17694            }
17695        }
17696    }
17697
17698    /**
17699     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17700     *
17701     * @return the drawing start time in milliseconds
17702     */
17703    public long getDrawingTime() {
17704        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17705    }
17706
17707    /**
17708     * <p>Enables or disables the duplication of the parent's state into this view. When
17709     * duplication is enabled, this view gets its drawable state from its parent rather
17710     * than from its own internal properties.</p>
17711     *
17712     * <p>Note: in the current implementation, setting this property to true after the
17713     * view was added to a ViewGroup might have no effect at all. This property should
17714     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17715     *
17716     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17717     * property is enabled, an exception will be thrown.</p>
17718     *
17719     * <p>Note: if the child view uses and updates additional states which are unknown to the
17720     * parent, these states should not be affected by this method.</p>
17721     *
17722     * @param enabled True to enable duplication of the parent's drawable state, false
17723     *                to disable it.
17724     *
17725     * @see #getDrawableState()
17726     * @see #isDuplicateParentStateEnabled()
17727     */
17728    public void setDuplicateParentStateEnabled(boolean enabled) {
17729        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17730    }
17731
17732    /**
17733     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17734     *
17735     * @return True if this view's drawable state is duplicated from the parent,
17736     *         false otherwise
17737     *
17738     * @see #getDrawableState()
17739     * @see #setDuplicateParentStateEnabled(boolean)
17740     */
17741    public boolean isDuplicateParentStateEnabled() {
17742        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17743    }
17744
17745    /**
17746     * <p>Specifies the type of layer backing this view. The layer can be
17747     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17748     * {@link #LAYER_TYPE_HARDWARE}.</p>
17749     *
17750     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17751     * instance that controls how the layer is composed on screen. The following
17752     * properties of the paint are taken into account when composing the layer:</p>
17753     * <ul>
17754     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17755     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17756     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17757     * </ul>
17758     *
17759     * <p>If this view has an alpha value set to < 1.0 by calling
17760     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17761     * by this view's alpha value.</p>
17762     *
17763     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17764     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17765     * for more information on when and how to use layers.</p>
17766     *
17767     * @param layerType The type of layer to use with this view, must be one of
17768     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17769     *        {@link #LAYER_TYPE_HARDWARE}
17770     * @param paint The paint used to compose the layer. This argument is optional
17771     *        and can be null. It is ignored when the layer type is
17772     *        {@link #LAYER_TYPE_NONE}
17773     *
17774     * @see #getLayerType()
17775     * @see #LAYER_TYPE_NONE
17776     * @see #LAYER_TYPE_SOFTWARE
17777     * @see #LAYER_TYPE_HARDWARE
17778     * @see #setAlpha(float)
17779     *
17780     * @attr ref android.R.styleable#View_layerType
17781     */
17782    public void setLayerType(int layerType, @Nullable Paint paint) {
17783        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17784            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17785                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17786        }
17787
17788        boolean typeChanged = mRenderNode.setLayerType(layerType);
17789
17790        if (!typeChanged) {
17791            setLayerPaint(paint);
17792            return;
17793        }
17794
17795        if (layerType != LAYER_TYPE_SOFTWARE) {
17796            // Destroy any previous software drawing cache if present
17797            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17798            // drawing cache created in View#draw when drawing to a SW canvas.
17799            destroyDrawingCache();
17800        }
17801
17802        mLayerType = layerType;
17803        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17804        mRenderNode.setLayerPaint(mLayerPaint);
17805
17806        // draw() behaves differently if we are on a layer, so we need to
17807        // invalidate() here
17808        invalidateParentCaches();
17809        invalidate(true);
17810    }
17811
17812    /**
17813     * Updates the {@link Paint} object used with the current layer (used only if the current
17814     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17815     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17816     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17817     * ensure that the view gets redrawn immediately.
17818     *
17819     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17820     * instance that controls how the layer is composed on screen. The following
17821     * properties of the paint are taken into account when composing the layer:</p>
17822     * <ul>
17823     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17824     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17825     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17826     * </ul>
17827     *
17828     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17829     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17830     *
17831     * @param paint The paint used to compose the layer. This argument is optional
17832     *        and can be null. It is ignored when the layer type is
17833     *        {@link #LAYER_TYPE_NONE}
17834     *
17835     * @see #setLayerType(int, android.graphics.Paint)
17836     */
17837    public void setLayerPaint(@Nullable Paint paint) {
17838        int layerType = getLayerType();
17839        if (layerType != LAYER_TYPE_NONE) {
17840            mLayerPaint = paint;
17841            if (layerType == LAYER_TYPE_HARDWARE) {
17842                if (mRenderNode.setLayerPaint(paint)) {
17843                    invalidateViewProperty(false, false);
17844                }
17845            } else {
17846                invalidate();
17847            }
17848        }
17849    }
17850
17851    /**
17852     * Indicates what type of layer is currently associated with this view. By default
17853     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17854     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17855     * for more information on the different types of layers.
17856     *
17857     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17858     *         {@link #LAYER_TYPE_HARDWARE}
17859     *
17860     * @see #setLayerType(int, android.graphics.Paint)
17861     * @see #buildLayer()
17862     * @see #LAYER_TYPE_NONE
17863     * @see #LAYER_TYPE_SOFTWARE
17864     * @see #LAYER_TYPE_HARDWARE
17865     */
17866    public int getLayerType() {
17867        return mLayerType;
17868    }
17869
17870    /**
17871     * Forces this view's layer to be created and this view to be rendered
17872     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17873     * invoking this method will have no effect.
17874     *
17875     * This method can for instance be used to render a view into its layer before
17876     * starting an animation. If this view is complex, rendering into the layer
17877     * before starting the animation will avoid skipping frames.
17878     *
17879     * @throws IllegalStateException If this view is not attached to a window
17880     *
17881     * @see #setLayerType(int, android.graphics.Paint)
17882     */
17883    public void buildLayer() {
17884        if (mLayerType == LAYER_TYPE_NONE) return;
17885
17886        final AttachInfo attachInfo = mAttachInfo;
17887        if (attachInfo == null) {
17888            throw new IllegalStateException("This view must be attached to a window first");
17889        }
17890
17891        if (getWidth() == 0 || getHeight() == 0) {
17892            return;
17893        }
17894
17895        switch (mLayerType) {
17896            case LAYER_TYPE_HARDWARE:
17897                updateDisplayListIfDirty();
17898                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17899                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17900                }
17901                break;
17902            case LAYER_TYPE_SOFTWARE:
17903                buildDrawingCache(true);
17904                break;
17905        }
17906    }
17907
17908    /**
17909     * Destroys all hardware rendering resources. This method is invoked
17910     * when the system needs to reclaim resources. Upon execution of this
17911     * method, you should free any OpenGL resources created by the view.
17912     *
17913     * Note: you <strong>must</strong> call
17914     * <code>super.destroyHardwareResources()</code> when overriding
17915     * this method.
17916     *
17917     * @hide
17918     */
17919    @CallSuper
17920    protected void destroyHardwareResources() {
17921        if (mOverlay != null) {
17922            mOverlay.getOverlayView().destroyHardwareResources();
17923        }
17924        if (mGhostView != null) {
17925            mGhostView.destroyHardwareResources();
17926        }
17927    }
17928
17929    /**
17930     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17931     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17932     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17933     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17934     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17935     * null.</p>
17936     *
17937     * <p>Enabling the drawing cache is similar to
17938     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17939     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17940     * drawing cache has no effect on rendering because the system uses a different mechanism
17941     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17942     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17943     * for information on how to enable software and hardware layers.</p>
17944     *
17945     * <p>This API can be used to manually generate
17946     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17947     * {@link #getDrawingCache()}.</p>
17948     *
17949     * @param enabled true to enable the drawing cache, false otherwise
17950     *
17951     * @see #isDrawingCacheEnabled()
17952     * @see #getDrawingCache()
17953     * @see #buildDrawingCache()
17954     * @see #setLayerType(int, android.graphics.Paint)
17955     */
17956    public void setDrawingCacheEnabled(boolean enabled) {
17957        mCachingFailed = false;
17958        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17959    }
17960
17961    /**
17962     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17963     *
17964     * @return true if the drawing cache is enabled
17965     *
17966     * @see #setDrawingCacheEnabled(boolean)
17967     * @see #getDrawingCache()
17968     */
17969    @ViewDebug.ExportedProperty(category = "drawing")
17970    public boolean isDrawingCacheEnabled() {
17971        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17972    }
17973
17974    /**
17975     * Debugging utility which recursively outputs the dirty state of a view and its
17976     * descendants.
17977     *
17978     * @hide
17979     */
17980    @SuppressWarnings({"UnusedDeclaration"})
17981    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17982        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17983                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17984                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17985                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17986        if (clear) {
17987            mPrivateFlags &= clearMask;
17988        }
17989        if (this instanceof ViewGroup) {
17990            ViewGroup parent = (ViewGroup) this;
17991            final int count = parent.getChildCount();
17992            for (int i = 0; i < count; i++) {
17993                final View child = parent.getChildAt(i);
17994                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17995            }
17996        }
17997    }
17998
17999    /**
18000     * This method is used by ViewGroup to cause its children to restore or recreate their
18001     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
18002     * to recreate its own display list, which would happen if it went through the normal
18003     * draw/dispatchDraw mechanisms.
18004     *
18005     * @hide
18006     */
18007    protected void dispatchGetDisplayList() {}
18008
18009    /**
18010     * A view that is not attached or hardware accelerated cannot create a display list.
18011     * This method checks these conditions and returns the appropriate result.
18012     *
18013     * @return true if view has the ability to create a display list, false otherwise.
18014     *
18015     * @hide
18016     */
18017    public boolean canHaveDisplayList() {
18018        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
18019    }
18020
18021    /**
18022     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
18023     * @hide
18024     */
18025    @NonNull
18026    public RenderNode updateDisplayListIfDirty() {
18027        final RenderNode renderNode = mRenderNode;
18028        if (!canHaveDisplayList()) {
18029            // can't populate RenderNode, don't try
18030            return renderNode;
18031        }
18032
18033        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
18034                || !renderNode.isValid()
18035                || (mRecreateDisplayList)) {
18036            // Don't need to recreate the display list, just need to tell our
18037            // children to restore/recreate theirs
18038            if (renderNode.isValid()
18039                    && !mRecreateDisplayList) {
18040                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18041                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18042                dispatchGetDisplayList();
18043
18044                return renderNode; // no work needed
18045            }
18046
18047            // If we got here, we're recreating it. Mark it as such to ensure that
18048            // we copy in child display lists into ours in drawChild()
18049            mRecreateDisplayList = true;
18050
18051            int width = mRight - mLeft;
18052            int height = mBottom - mTop;
18053            int layerType = getLayerType();
18054
18055            final DisplayListCanvas canvas = renderNode.start(width, height);
18056            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
18057
18058            try {
18059                if (layerType == LAYER_TYPE_SOFTWARE) {
18060                    buildDrawingCache(true);
18061                    Bitmap cache = getDrawingCache(true);
18062                    if (cache != null) {
18063                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
18064                    }
18065                } else {
18066                    computeScroll();
18067
18068                    canvas.translate(-mScrollX, -mScrollY);
18069                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18070                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18071
18072                    // Fast path for layouts with no backgrounds
18073                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18074                        dispatchDraw(canvas);
18075                        drawAutofilledHighlight(canvas);
18076                        if (mOverlay != null && !mOverlay.isEmpty()) {
18077                            mOverlay.getOverlayView().draw(canvas);
18078                        }
18079                        if (debugDraw()) {
18080                            debugDrawFocus(canvas);
18081                        }
18082                    } else {
18083                        draw(canvas);
18084                    }
18085                }
18086            } finally {
18087                renderNode.end(canvas);
18088                setDisplayListProperties(renderNode);
18089            }
18090        } else {
18091            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18092            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18093        }
18094        return renderNode;
18095    }
18096
18097    private void resetDisplayList() {
18098        mRenderNode.discardDisplayList();
18099        if (mBackgroundRenderNode != null) {
18100            mBackgroundRenderNode.discardDisplayList();
18101        }
18102    }
18103
18104    /**
18105     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
18106     *
18107     * @return A non-scaled bitmap representing this view or null if cache is disabled.
18108     *
18109     * @see #getDrawingCache(boolean)
18110     */
18111    public Bitmap getDrawingCache() {
18112        return getDrawingCache(false);
18113    }
18114
18115    /**
18116     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
18117     * is null when caching is disabled. If caching is enabled and the cache is not ready,
18118     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
18119     * draw from the cache when the cache is enabled. To benefit from the cache, you must
18120     * request the drawing cache by calling this method and draw it on screen if the
18121     * returned bitmap is not null.</p>
18122     *
18123     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18124     * this method will create a bitmap of the same size as this view. Because this bitmap
18125     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18126     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18127     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18128     * size than the view. This implies that your application must be able to handle this
18129     * size.</p>
18130     *
18131     * @param autoScale Indicates whether the generated bitmap should be scaled based on
18132     *        the current density of the screen when the application is in compatibility
18133     *        mode.
18134     *
18135     * @return A bitmap representing this view or null if cache is disabled.
18136     *
18137     * @see #setDrawingCacheEnabled(boolean)
18138     * @see #isDrawingCacheEnabled()
18139     * @see #buildDrawingCache(boolean)
18140     * @see #destroyDrawingCache()
18141     */
18142    public Bitmap getDrawingCache(boolean autoScale) {
18143        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
18144            return null;
18145        }
18146        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
18147            buildDrawingCache(autoScale);
18148        }
18149        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
18150    }
18151
18152    /**
18153     * <p>Frees the resources used by the drawing cache. If you call
18154     * {@link #buildDrawingCache()} manually without calling
18155     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18156     * should cleanup the cache with this method afterwards.</p>
18157     *
18158     * @see #setDrawingCacheEnabled(boolean)
18159     * @see #buildDrawingCache()
18160     * @see #getDrawingCache()
18161     */
18162    public void destroyDrawingCache() {
18163        if (mDrawingCache != null) {
18164            mDrawingCache.recycle();
18165            mDrawingCache = null;
18166        }
18167        if (mUnscaledDrawingCache != null) {
18168            mUnscaledDrawingCache.recycle();
18169            mUnscaledDrawingCache = null;
18170        }
18171    }
18172
18173    /**
18174     * Setting a solid background color for the drawing cache's bitmaps will improve
18175     * performance and memory usage. Note, though that this should only be used if this
18176     * view will always be drawn on top of a solid color.
18177     *
18178     * @param color The background color to use for the drawing cache's bitmap
18179     *
18180     * @see #setDrawingCacheEnabled(boolean)
18181     * @see #buildDrawingCache()
18182     * @see #getDrawingCache()
18183     */
18184    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
18185        if (color != mDrawingCacheBackgroundColor) {
18186            mDrawingCacheBackgroundColor = color;
18187            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18188        }
18189    }
18190
18191    /**
18192     * @see #setDrawingCacheBackgroundColor(int)
18193     *
18194     * @return The background color to used for the drawing cache's bitmap
18195     */
18196    @ColorInt
18197    public int getDrawingCacheBackgroundColor() {
18198        return mDrawingCacheBackgroundColor;
18199    }
18200
18201    /**
18202     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
18203     *
18204     * @see #buildDrawingCache(boolean)
18205     */
18206    public void buildDrawingCache() {
18207        buildDrawingCache(false);
18208    }
18209
18210    /**
18211     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
18212     *
18213     * <p>If you call {@link #buildDrawingCache()} manually without calling
18214     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18215     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
18216     *
18217     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18218     * this method will create a bitmap of the same size as this view. Because this bitmap
18219     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18220     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18221     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18222     * size than the view. This implies that your application must be able to handle this
18223     * size.</p>
18224     *
18225     * <p>You should avoid calling this method when hardware acceleration is enabled. If
18226     * you do not need the drawing cache bitmap, calling this method will increase memory
18227     * usage and cause the view to be rendered in software once, thus negatively impacting
18228     * performance.</p>
18229     *
18230     * @see #getDrawingCache()
18231     * @see #destroyDrawingCache()
18232     */
18233    public void buildDrawingCache(boolean autoScale) {
18234        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
18235                mDrawingCache == null : mUnscaledDrawingCache == null)) {
18236            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
18237                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
18238                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
18239            }
18240            try {
18241                buildDrawingCacheImpl(autoScale);
18242            } finally {
18243                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
18244            }
18245        }
18246    }
18247
18248    /**
18249     * private, internal implementation of buildDrawingCache, used to enable tracing
18250     */
18251    private void buildDrawingCacheImpl(boolean autoScale) {
18252        mCachingFailed = false;
18253
18254        int width = mRight - mLeft;
18255        int height = mBottom - mTop;
18256
18257        final AttachInfo attachInfo = mAttachInfo;
18258        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
18259
18260        if (autoScale && scalingRequired) {
18261            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
18262            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
18263        }
18264
18265        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
18266        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
18267        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
18268
18269        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
18270        final long drawingCacheSize =
18271                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
18272        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
18273            if (width > 0 && height > 0) {
18274                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
18275                        + " too large to fit into a software layer (or drawing cache), needs "
18276                        + projectedBitmapSize + " bytes, only "
18277                        + drawingCacheSize + " available");
18278            }
18279            destroyDrawingCache();
18280            mCachingFailed = true;
18281            return;
18282        }
18283
18284        boolean clear = true;
18285        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
18286
18287        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
18288            Bitmap.Config quality;
18289            if (!opaque) {
18290                // Never pick ARGB_4444 because it looks awful
18291                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
18292                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
18293                    case DRAWING_CACHE_QUALITY_AUTO:
18294                    case DRAWING_CACHE_QUALITY_LOW:
18295                    case DRAWING_CACHE_QUALITY_HIGH:
18296                    default:
18297                        quality = Bitmap.Config.ARGB_8888;
18298                        break;
18299                }
18300            } else {
18301                // Optimization for translucent windows
18302                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
18303                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
18304            }
18305
18306            // Try to cleanup memory
18307            if (bitmap != null) bitmap.recycle();
18308
18309            try {
18310                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18311                        width, height, quality);
18312                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
18313                if (autoScale) {
18314                    mDrawingCache = bitmap;
18315                } else {
18316                    mUnscaledDrawingCache = bitmap;
18317                }
18318                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
18319            } catch (OutOfMemoryError e) {
18320                // If there is not enough memory to create the bitmap cache, just
18321                // ignore the issue as bitmap caches are not required to draw the
18322                // view hierarchy
18323                if (autoScale) {
18324                    mDrawingCache = null;
18325                } else {
18326                    mUnscaledDrawingCache = null;
18327                }
18328                mCachingFailed = true;
18329                return;
18330            }
18331
18332            clear = drawingCacheBackgroundColor != 0;
18333        }
18334
18335        Canvas canvas;
18336        if (attachInfo != null) {
18337            canvas = attachInfo.mCanvas;
18338            if (canvas == null) {
18339                canvas = new Canvas();
18340            }
18341            canvas.setBitmap(bitmap);
18342            // Temporarily clobber the cached Canvas in case one of our children
18343            // is also using a drawing cache. Without this, the children would
18344            // steal the canvas by attaching their own bitmap to it and bad, bad
18345            // thing would happen (invisible views, corrupted drawings, etc.)
18346            attachInfo.mCanvas = null;
18347        } else {
18348            // This case should hopefully never or seldom happen
18349            canvas = new Canvas(bitmap);
18350        }
18351
18352        if (clear) {
18353            bitmap.eraseColor(drawingCacheBackgroundColor);
18354        }
18355
18356        computeScroll();
18357        final int restoreCount = canvas.save();
18358
18359        if (autoScale && scalingRequired) {
18360            final float scale = attachInfo.mApplicationScale;
18361            canvas.scale(scale, scale);
18362        }
18363
18364        canvas.translate(-mScrollX, -mScrollY);
18365
18366        mPrivateFlags |= PFLAG_DRAWN;
18367        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18368                mLayerType != LAYER_TYPE_NONE) {
18369            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18370        }
18371
18372        // Fast path for layouts with no backgrounds
18373        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18374            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18375            dispatchDraw(canvas);
18376            drawAutofilledHighlight(canvas);
18377            if (mOverlay != null && !mOverlay.isEmpty()) {
18378                mOverlay.getOverlayView().draw(canvas);
18379            }
18380        } else {
18381            draw(canvas);
18382        }
18383
18384        canvas.restoreToCount(restoreCount);
18385        canvas.setBitmap(null);
18386
18387        if (attachInfo != null) {
18388            // Restore the cached Canvas for our siblings
18389            attachInfo.mCanvas = canvas;
18390        }
18391    }
18392
18393    /**
18394     * Create a snapshot of the view into a bitmap.  We should probably make
18395     * some form of this public, but should think about the API.
18396     *
18397     * @hide
18398     */
18399    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18400        int width = mRight - mLeft;
18401        int height = mBottom - mTop;
18402
18403        final AttachInfo attachInfo = mAttachInfo;
18404        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18405        width = (int) ((width * scale) + 0.5f);
18406        height = (int) ((height * scale) + 0.5f);
18407
18408        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18409                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18410        if (bitmap == null) {
18411            throw new OutOfMemoryError();
18412        }
18413
18414        Resources resources = getResources();
18415        if (resources != null) {
18416            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18417        }
18418
18419        Canvas canvas;
18420        if (attachInfo != null) {
18421            canvas = attachInfo.mCanvas;
18422            if (canvas == null) {
18423                canvas = new Canvas();
18424            }
18425            canvas.setBitmap(bitmap);
18426            // Temporarily clobber the cached Canvas in case one of our children
18427            // is also using a drawing cache. Without this, the children would
18428            // steal the canvas by attaching their own bitmap to it and bad, bad
18429            // things would happen (invisible views, corrupted drawings, etc.)
18430            attachInfo.mCanvas = null;
18431        } else {
18432            // This case should hopefully never or seldom happen
18433            canvas = new Canvas(bitmap);
18434        }
18435        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18436        canvas.setHwBitmapsInSwModeEnabled(true);
18437        if ((backgroundColor & 0xff000000) != 0) {
18438            bitmap.eraseColor(backgroundColor);
18439        }
18440
18441        computeScroll();
18442        final int restoreCount = canvas.save();
18443        canvas.scale(scale, scale);
18444        canvas.translate(-mScrollX, -mScrollY);
18445
18446        // Temporarily remove the dirty mask
18447        int flags = mPrivateFlags;
18448        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18449
18450        // Fast path for layouts with no backgrounds
18451        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18452            dispatchDraw(canvas);
18453            drawAutofilledHighlight(canvas);
18454            if (mOverlay != null && !mOverlay.isEmpty()) {
18455                mOverlay.getOverlayView().draw(canvas);
18456            }
18457        } else {
18458            draw(canvas);
18459        }
18460
18461        mPrivateFlags = flags;
18462
18463        canvas.restoreToCount(restoreCount);
18464        canvas.setBitmap(null);
18465        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18466
18467        if (attachInfo != null) {
18468            // Restore the cached Canvas for our siblings
18469            attachInfo.mCanvas = canvas;
18470        }
18471
18472        return bitmap;
18473    }
18474
18475    /**
18476     * Indicates whether this View is currently in edit mode. A View is usually
18477     * in edit mode when displayed within a developer tool. For instance, if
18478     * this View is being drawn by a visual user interface builder, this method
18479     * should return true.
18480     *
18481     * Subclasses should check the return value of this method to provide
18482     * different behaviors if their normal behavior might interfere with the
18483     * host environment. For instance: the class spawns a thread in its
18484     * constructor, the drawing code relies on device-specific features, etc.
18485     *
18486     * This method is usually checked in the drawing code of custom widgets.
18487     *
18488     * @return True if this View is in edit mode, false otherwise.
18489     */
18490    public boolean isInEditMode() {
18491        return false;
18492    }
18493
18494    /**
18495     * If the View draws content inside its padding and enables fading edges,
18496     * it needs to support padding offsets. Padding offsets are added to the
18497     * fading edges to extend the length of the fade so that it covers pixels
18498     * drawn inside the padding.
18499     *
18500     * Subclasses of this class should override this method if they need
18501     * to draw content inside the padding.
18502     *
18503     * @return True if padding offset must be applied, false otherwise.
18504     *
18505     * @see #getLeftPaddingOffset()
18506     * @see #getRightPaddingOffset()
18507     * @see #getTopPaddingOffset()
18508     * @see #getBottomPaddingOffset()
18509     *
18510     * @since CURRENT
18511     */
18512    protected boolean isPaddingOffsetRequired() {
18513        return false;
18514    }
18515
18516    /**
18517     * Amount by which to extend the left fading region. Called only when
18518     * {@link #isPaddingOffsetRequired()} returns true.
18519     *
18520     * @return The left padding offset in pixels.
18521     *
18522     * @see #isPaddingOffsetRequired()
18523     *
18524     * @since CURRENT
18525     */
18526    protected int getLeftPaddingOffset() {
18527        return 0;
18528    }
18529
18530    /**
18531     * Amount by which to extend the right fading region. Called only when
18532     * {@link #isPaddingOffsetRequired()} returns true.
18533     *
18534     * @return The right padding offset in pixels.
18535     *
18536     * @see #isPaddingOffsetRequired()
18537     *
18538     * @since CURRENT
18539     */
18540    protected int getRightPaddingOffset() {
18541        return 0;
18542    }
18543
18544    /**
18545     * Amount by which to extend the top fading region. Called only when
18546     * {@link #isPaddingOffsetRequired()} returns true.
18547     *
18548     * @return The top padding offset in pixels.
18549     *
18550     * @see #isPaddingOffsetRequired()
18551     *
18552     * @since CURRENT
18553     */
18554    protected int getTopPaddingOffset() {
18555        return 0;
18556    }
18557
18558    /**
18559     * Amount by which to extend the bottom fading region. Called only when
18560     * {@link #isPaddingOffsetRequired()} returns true.
18561     *
18562     * @return The bottom padding offset in pixels.
18563     *
18564     * @see #isPaddingOffsetRequired()
18565     *
18566     * @since CURRENT
18567     */
18568    protected int getBottomPaddingOffset() {
18569        return 0;
18570    }
18571
18572    /**
18573     * @hide
18574     * @param offsetRequired
18575     */
18576    protected int getFadeTop(boolean offsetRequired) {
18577        int top = mPaddingTop;
18578        if (offsetRequired) top += getTopPaddingOffset();
18579        return top;
18580    }
18581
18582    /**
18583     * @hide
18584     * @param offsetRequired
18585     */
18586    protected int getFadeHeight(boolean offsetRequired) {
18587        int padding = mPaddingTop;
18588        if (offsetRequired) padding += getTopPaddingOffset();
18589        return mBottom - mTop - mPaddingBottom - padding;
18590    }
18591
18592    /**
18593     * <p>Indicates whether this view is attached to a hardware accelerated
18594     * window or not.</p>
18595     *
18596     * <p>Even if this method returns true, it does not mean that every call
18597     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18598     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18599     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18600     * window is hardware accelerated,
18601     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18602     * return false, and this method will return true.</p>
18603     *
18604     * @return True if the view is attached to a window and the window is
18605     *         hardware accelerated; false in any other case.
18606     */
18607    @ViewDebug.ExportedProperty(category = "drawing")
18608    public boolean isHardwareAccelerated() {
18609        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18610    }
18611
18612    /**
18613     * Sets a rectangular area on this view to which the view will be clipped
18614     * when it is drawn. Setting the value to null will remove the clip bounds
18615     * and the view will draw normally, using its full bounds.
18616     *
18617     * @param clipBounds The rectangular area, in the local coordinates of
18618     * this view, to which future drawing operations will be clipped.
18619     */
18620    public void setClipBounds(Rect clipBounds) {
18621        if (clipBounds == mClipBounds
18622                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18623            return;
18624        }
18625        if (clipBounds != null) {
18626            if (mClipBounds == null) {
18627                mClipBounds = new Rect(clipBounds);
18628            } else {
18629                mClipBounds.set(clipBounds);
18630            }
18631        } else {
18632            mClipBounds = null;
18633        }
18634        mRenderNode.setClipBounds(mClipBounds);
18635        invalidateViewProperty(false, false);
18636    }
18637
18638    /**
18639     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18640     *
18641     * @return A copy of the current clip bounds if clip bounds are set,
18642     * otherwise null.
18643     */
18644    public Rect getClipBounds() {
18645        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18646    }
18647
18648
18649    /**
18650     * Populates an output rectangle with the clip bounds of the view,
18651     * returning {@code true} if successful or {@code false} if the view's
18652     * clip bounds are {@code null}.
18653     *
18654     * @param outRect rectangle in which to place the clip bounds of the view
18655     * @return {@code true} if successful or {@code false} if the view's
18656     *         clip bounds are {@code null}
18657     */
18658    public boolean getClipBounds(Rect outRect) {
18659        if (mClipBounds != null) {
18660            outRect.set(mClipBounds);
18661            return true;
18662        }
18663        return false;
18664    }
18665
18666    /**
18667     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18668     * case of an active Animation being run on the view.
18669     */
18670    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18671            Animation a, boolean scalingRequired) {
18672        Transformation invalidationTransform;
18673        final int flags = parent.mGroupFlags;
18674        final boolean initialized = a.isInitialized();
18675        if (!initialized) {
18676            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18677            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18678            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18679            onAnimationStart();
18680        }
18681
18682        final Transformation t = parent.getChildTransformation();
18683        boolean more = a.getTransformation(drawingTime, t, 1f);
18684        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18685            if (parent.mInvalidationTransformation == null) {
18686                parent.mInvalidationTransformation = new Transformation();
18687            }
18688            invalidationTransform = parent.mInvalidationTransformation;
18689            a.getTransformation(drawingTime, invalidationTransform, 1f);
18690        } else {
18691            invalidationTransform = t;
18692        }
18693
18694        if (more) {
18695            if (!a.willChangeBounds()) {
18696                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18697                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18698                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18699                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18700                    // The child need to draw an animation, potentially offscreen, so
18701                    // make sure we do not cancel invalidate requests
18702                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18703                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18704                }
18705            } else {
18706                if (parent.mInvalidateRegion == null) {
18707                    parent.mInvalidateRegion = new RectF();
18708                }
18709                final RectF region = parent.mInvalidateRegion;
18710                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18711                        invalidationTransform);
18712
18713                // The child need to draw an animation, potentially offscreen, so
18714                // make sure we do not cancel invalidate requests
18715                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18716
18717                final int left = mLeft + (int) region.left;
18718                final int top = mTop + (int) region.top;
18719                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18720                        top + (int) (region.height() + .5f));
18721            }
18722        }
18723        return more;
18724    }
18725
18726    /**
18727     * This method is called by getDisplayList() when a display list is recorded for a View.
18728     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18729     */
18730    void setDisplayListProperties(RenderNode renderNode) {
18731        if (renderNode != null) {
18732            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18733            renderNode.setClipToBounds(mParent instanceof ViewGroup
18734                    && ((ViewGroup) mParent).getClipChildren());
18735
18736            float alpha = 1;
18737            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18738                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18739                ViewGroup parentVG = (ViewGroup) mParent;
18740                final Transformation t = parentVG.getChildTransformation();
18741                if (parentVG.getChildStaticTransformation(this, t)) {
18742                    final int transformType = t.getTransformationType();
18743                    if (transformType != Transformation.TYPE_IDENTITY) {
18744                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18745                            alpha = t.getAlpha();
18746                        }
18747                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18748                            renderNode.setStaticMatrix(t.getMatrix());
18749                        }
18750                    }
18751                }
18752            }
18753            if (mTransformationInfo != null) {
18754                alpha *= getFinalAlpha();
18755                if (alpha < 1) {
18756                    final int multipliedAlpha = (int) (255 * alpha);
18757                    if (onSetAlpha(multipliedAlpha)) {
18758                        alpha = 1;
18759                    }
18760                }
18761                renderNode.setAlpha(alpha);
18762            } else if (alpha < 1) {
18763                renderNode.setAlpha(alpha);
18764            }
18765        }
18766    }
18767
18768    /**
18769     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18770     *
18771     * This is where the View specializes rendering behavior based on layer type,
18772     * and hardware acceleration.
18773     */
18774    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18775        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18776        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18777         *
18778         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18779         * HW accelerated, it can't handle drawing RenderNodes.
18780         */
18781        boolean drawingWithRenderNode = mAttachInfo != null
18782                && mAttachInfo.mHardwareAccelerated
18783                && hardwareAcceleratedCanvas;
18784
18785        boolean more = false;
18786        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18787        final int parentFlags = parent.mGroupFlags;
18788
18789        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18790            parent.getChildTransformation().clear();
18791            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18792        }
18793
18794        Transformation transformToApply = null;
18795        boolean concatMatrix = false;
18796        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18797        final Animation a = getAnimation();
18798        if (a != null) {
18799            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18800            concatMatrix = a.willChangeTransformationMatrix();
18801            if (concatMatrix) {
18802                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18803            }
18804            transformToApply = parent.getChildTransformation();
18805        } else {
18806            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18807                // No longer animating: clear out old animation matrix
18808                mRenderNode.setAnimationMatrix(null);
18809                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18810            }
18811            if (!drawingWithRenderNode
18812                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18813                final Transformation t = parent.getChildTransformation();
18814                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18815                if (hasTransform) {
18816                    final int transformType = t.getTransformationType();
18817                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18818                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18819                }
18820            }
18821        }
18822
18823        concatMatrix |= !childHasIdentityMatrix;
18824
18825        // Sets the flag as early as possible to allow draw() implementations
18826        // to call invalidate() successfully when doing animations
18827        mPrivateFlags |= PFLAG_DRAWN;
18828
18829        if (!concatMatrix &&
18830                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18831                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18832                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18833                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18834            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18835            return more;
18836        }
18837        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18838
18839        if (hardwareAcceleratedCanvas) {
18840            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18841            // retain the flag's value temporarily in the mRecreateDisplayList flag
18842            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18843            mPrivateFlags &= ~PFLAG_INVALIDATED;
18844        }
18845
18846        RenderNode renderNode = null;
18847        Bitmap cache = null;
18848        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18849        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18850             if (layerType != LAYER_TYPE_NONE) {
18851                 // If not drawing with RenderNode, treat HW layers as SW
18852                 layerType = LAYER_TYPE_SOFTWARE;
18853                 buildDrawingCache(true);
18854            }
18855            cache = getDrawingCache(true);
18856        }
18857
18858        if (drawingWithRenderNode) {
18859            // Delay getting the display list until animation-driven alpha values are
18860            // set up and possibly passed on to the view
18861            renderNode = updateDisplayListIfDirty();
18862            if (!renderNode.isValid()) {
18863                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18864                // to getDisplayList(), the display list will be marked invalid and we should not
18865                // try to use it again.
18866                renderNode = null;
18867                drawingWithRenderNode = false;
18868            }
18869        }
18870
18871        int sx = 0;
18872        int sy = 0;
18873        if (!drawingWithRenderNode) {
18874            computeScroll();
18875            sx = mScrollX;
18876            sy = mScrollY;
18877        }
18878
18879        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18880        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18881
18882        int restoreTo = -1;
18883        if (!drawingWithRenderNode || transformToApply != null) {
18884            restoreTo = canvas.save();
18885        }
18886        if (offsetForScroll) {
18887            canvas.translate(mLeft - sx, mTop - sy);
18888        } else {
18889            if (!drawingWithRenderNode) {
18890                canvas.translate(mLeft, mTop);
18891            }
18892            if (scalingRequired) {
18893                if (drawingWithRenderNode) {
18894                    // TODO: Might not need this if we put everything inside the DL
18895                    restoreTo = canvas.save();
18896                }
18897                // mAttachInfo cannot be null, otherwise scalingRequired == false
18898                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18899                canvas.scale(scale, scale);
18900            }
18901        }
18902
18903        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18904        if (transformToApply != null
18905                || alpha < 1
18906                || !hasIdentityMatrix()
18907                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18908            if (transformToApply != null || !childHasIdentityMatrix) {
18909                int transX = 0;
18910                int transY = 0;
18911
18912                if (offsetForScroll) {
18913                    transX = -sx;
18914                    transY = -sy;
18915                }
18916
18917                if (transformToApply != null) {
18918                    if (concatMatrix) {
18919                        if (drawingWithRenderNode) {
18920                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18921                        } else {
18922                            // Undo the scroll translation, apply the transformation matrix,
18923                            // then redo the scroll translate to get the correct result.
18924                            canvas.translate(-transX, -transY);
18925                            canvas.concat(transformToApply.getMatrix());
18926                            canvas.translate(transX, transY);
18927                        }
18928                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18929                    }
18930
18931                    float transformAlpha = transformToApply.getAlpha();
18932                    if (transformAlpha < 1) {
18933                        alpha *= transformAlpha;
18934                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18935                    }
18936                }
18937
18938                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18939                    canvas.translate(-transX, -transY);
18940                    canvas.concat(getMatrix());
18941                    canvas.translate(transX, transY);
18942                }
18943            }
18944
18945            // Deal with alpha if it is or used to be <1
18946            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18947                if (alpha < 1) {
18948                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18949                } else {
18950                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18951                }
18952                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18953                if (!drawingWithDrawingCache) {
18954                    final int multipliedAlpha = (int) (255 * alpha);
18955                    if (!onSetAlpha(multipliedAlpha)) {
18956                        if (drawingWithRenderNode) {
18957                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18958                        } else if (layerType == LAYER_TYPE_NONE) {
18959                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18960                                    multipliedAlpha);
18961                        }
18962                    } else {
18963                        // Alpha is handled by the child directly, clobber the layer's alpha
18964                        mPrivateFlags |= PFLAG_ALPHA_SET;
18965                    }
18966                }
18967            }
18968        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18969            onSetAlpha(255);
18970            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18971        }
18972
18973        if (!drawingWithRenderNode) {
18974            // apply clips directly, since RenderNode won't do it for this draw
18975            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18976                if (offsetForScroll) {
18977                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18978                } else {
18979                    if (!scalingRequired || cache == null) {
18980                        canvas.clipRect(0, 0, getWidth(), getHeight());
18981                    } else {
18982                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18983                    }
18984                }
18985            }
18986
18987            if (mClipBounds != null) {
18988                // clip bounds ignore scroll
18989                canvas.clipRect(mClipBounds);
18990            }
18991        }
18992
18993        if (!drawingWithDrawingCache) {
18994            if (drawingWithRenderNode) {
18995                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18996                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18997            } else {
18998                // Fast path for layouts with no backgrounds
18999                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
19000                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19001                    dispatchDraw(canvas);
19002                } else {
19003                    draw(canvas);
19004                }
19005            }
19006        } else if (cache != null) {
19007            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19008            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
19009                // no layer paint, use temporary paint to draw bitmap
19010                Paint cachePaint = parent.mCachePaint;
19011                if (cachePaint == null) {
19012                    cachePaint = new Paint();
19013                    cachePaint.setDither(false);
19014                    parent.mCachePaint = cachePaint;
19015                }
19016                cachePaint.setAlpha((int) (alpha * 255));
19017                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
19018            } else {
19019                // use layer paint to draw the bitmap, merging the two alphas, but also restore
19020                int layerPaintAlpha = mLayerPaint.getAlpha();
19021                if (alpha < 1) {
19022                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
19023                }
19024                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
19025                if (alpha < 1) {
19026                    mLayerPaint.setAlpha(layerPaintAlpha);
19027                }
19028            }
19029        }
19030
19031        if (restoreTo >= 0) {
19032            canvas.restoreToCount(restoreTo);
19033        }
19034
19035        if (a != null && !more) {
19036            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
19037                onSetAlpha(255);
19038            }
19039            parent.finishAnimatingView(this, a);
19040        }
19041
19042        if (more && hardwareAcceleratedCanvas) {
19043            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
19044                // alpha animations should cause the child to recreate its display list
19045                invalidate(true);
19046            }
19047        }
19048
19049        mRecreateDisplayList = false;
19050
19051        return more;
19052    }
19053
19054    static Paint getDebugPaint() {
19055        if (sDebugPaint == null) {
19056            sDebugPaint = new Paint();
19057            sDebugPaint.setAntiAlias(false);
19058        }
19059        return sDebugPaint;
19060    }
19061
19062    final int dipsToPixels(int dips) {
19063        float scale = getContext().getResources().getDisplayMetrics().density;
19064        return (int) (dips * scale + 0.5f);
19065    }
19066
19067    final private void debugDrawFocus(Canvas canvas) {
19068        if (isFocused()) {
19069            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
19070            final int l = mScrollX;
19071            final int r = l + mRight - mLeft;
19072            final int t = mScrollY;
19073            final int b = t + mBottom - mTop;
19074
19075            final Paint paint = getDebugPaint();
19076            paint.setColor(DEBUG_CORNERS_COLOR);
19077
19078            // Draw squares in corners.
19079            paint.setStyle(Paint.Style.FILL);
19080            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
19081            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
19082            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
19083            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
19084
19085            // Draw big X across the view.
19086            paint.setStyle(Paint.Style.STROKE);
19087            canvas.drawLine(l, t, r, b, paint);
19088            canvas.drawLine(l, b, r, t, paint);
19089        }
19090    }
19091
19092    /**
19093     * Manually render this view (and all of its children) to the given Canvas.
19094     * The view must have already done a full layout before this function is
19095     * called.  When implementing a view, implement
19096     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
19097     * If you do need to override this method, call the superclass version.
19098     *
19099     * @param canvas The Canvas to which the View is rendered.
19100     */
19101    @CallSuper
19102    public void draw(Canvas canvas) {
19103        final int privateFlags = mPrivateFlags;
19104        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
19105                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
19106        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
19107
19108        /*
19109         * Draw traversal performs several drawing steps which must be executed
19110         * in the appropriate order:
19111         *
19112         *      1. Draw the background
19113         *      2. If necessary, save the canvas' layers to prepare for fading
19114         *      3. Draw view's content
19115         *      4. Draw children
19116         *      5. If necessary, draw the fading edges and restore layers
19117         *      6. Draw decorations (scrollbars for instance)
19118         */
19119
19120        // Step 1, draw the background, if needed
19121        int saveCount;
19122
19123        if (!dirtyOpaque) {
19124            drawBackground(canvas);
19125        }
19126
19127        // skip step 2 & 5 if possible (common case)
19128        final int viewFlags = mViewFlags;
19129        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
19130        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
19131        if (!verticalEdges && !horizontalEdges) {
19132            // Step 3, draw the content
19133            if (!dirtyOpaque) onDraw(canvas);
19134
19135            // Step 4, draw the children
19136            dispatchDraw(canvas);
19137
19138            drawAutofilledHighlight(canvas);
19139
19140            // Overlay is part of the content and draws beneath Foreground
19141            if (mOverlay != null && !mOverlay.isEmpty()) {
19142                mOverlay.getOverlayView().dispatchDraw(canvas);
19143            }
19144
19145            // Step 6, draw decorations (foreground, scrollbars)
19146            onDrawForeground(canvas);
19147
19148            // Step 7, draw the default focus highlight
19149            drawDefaultFocusHighlight(canvas);
19150
19151            if (debugDraw()) {
19152                debugDrawFocus(canvas);
19153            }
19154
19155            // we're done...
19156            return;
19157        }
19158
19159        /*
19160         * Here we do the full fledged routine...
19161         * (this is an uncommon case where speed matters less,
19162         * this is why we repeat some of the tests that have been
19163         * done above)
19164         */
19165
19166        boolean drawTop = false;
19167        boolean drawBottom = false;
19168        boolean drawLeft = false;
19169        boolean drawRight = false;
19170
19171        float topFadeStrength = 0.0f;
19172        float bottomFadeStrength = 0.0f;
19173        float leftFadeStrength = 0.0f;
19174        float rightFadeStrength = 0.0f;
19175
19176        // Step 2, save the canvas' layers
19177        int paddingLeft = mPaddingLeft;
19178
19179        final boolean offsetRequired = isPaddingOffsetRequired();
19180        if (offsetRequired) {
19181            paddingLeft += getLeftPaddingOffset();
19182        }
19183
19184        int left = mScrollX + paddingLeft;
19185        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
19186        int top = mScrollY + getFadeTop(offsetRequired);
19187        int bottom = top + getFadeHeight(offsetRequired);
19188
19189        if (offsetRequired) {
19190            right += getRightPaddingOffset();
19191            bottom += getBottomPaddingOffset();
19192        }
19193
19194        final ScrollabilityCache scrollabilityCache = mScrollCache;
19195        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
19196        int length = (int) fadeHeight;
19197
19198        // clip the fade length if top and bottom fades overlap
19199        // overlapping fades produce odd-looking artifacts
19200        if (verticalEdges && (top + length > bottom - length)) {
19201            length = (bottom - top) / 2;
19202        }
19203
19204        // also clip horizontal fades if necessary
19205        if (horizontalEdges && (left + length > right - length)) {
19206            length = (right - left) / 2;
19207        }
19208
19209        if (verticalEdges) {
19210            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
19211            drawTop = topFadeStrength * fadeHeight > 1.0f;
19212            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
19213            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
19214        }
19215
19216        if (horizontalEdges) {
19217            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
19218            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
19219            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
19220            drawRight = rightFadeStrength * fadeHeight > 1.0f;
19221        }
19222
19223        saveCount = canvas.getSaveCount();
19224
19225        int solidColor = getSolidColor();
19226        if (solidColor == 0) {
19227            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
19228
19229            if (drawTop) {
19230                canvas.saveLayer(left, top, right, top + length, null, flags);
19231            }
19232
19233            if (drawBottom) {
19234                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
19235            }
19236
19237            if (drawLeft) {
19238                canvas.saveLayer(left, top, left + length, bottom, null, flags);
19239            }
19240
19241            if (drawRight) {
19242                canvas.saveLayer(right - length, top, right, bottom, null, flags);
19243            }
19244        } else {
19245            scrollabilityCache.setFadeColor(solidColor);
19246        }
19247
19248        // Step 3, draw the content
19249        if (!dirtyOpaque) onDraw(canvas);
19250
19251        // Step 4, draw the children
19252        dispatchDraw(canvas);
19253
19254        // Step 5, draw the fade effect and restore layers
19255        final Paint p = scrollabilityCache.paint;
19256        final Matrix matrix = scrollabilityCache.matrix;
19257        final Shader fade = scrollabilityCache.shader;
19258
19259        if (drawTop) {
19260            matrix.setScale(1, fadeHeight * topFadeStrength);
19261            matrix.postTranslate(left, top);
19262            fade.setLocalMatrix(matrix);
19263            p.setShader(fade);
19264            canvas.drawRect(left, top, right, top + length, p);
19265        }
19266
19267        if (drawBottom) {
19268            matrix.setScale(1, fadeHeight * bottomFadeStrength);
19269            matrix.postRotate(180);
19270            matrix.postTranslate(left, bottom);
19271            fade.setLocalMatrix(matrix);
19272            p.setShader(fade);
19273            canvas.drawRect(left, bottom - length, right, bottom, p);
19274        }
19275
19276        if (drawLeft) {
19277            matrix.setScale(1, fadeHeight * leftFadeStrength);
19278            matrix.postRotate(-90);
19279            matrix.postTranslate(left, top);
19280            fade.setLocalMatrix(matrix);
19281            p.setShader(fade);
19282            canvas.drawRect(left, top, left + length, bottom, p);
19283        }
19284
19285        if (drawRight) {
19286            matrix.setScale(1, fadeHeight * rightFadeStrength);
19287            matrix.postRotate(90);
19288            matrix.postTranslate(right, top);
19289            fade.setLocalMatrix(matrix);
19290            p.setShader(fade);
19291            canvas.drawRect(right - length, top, right, bottom, p);
19292        }
19293
19294        canvas.restoreToCount(saveCount);
19295
19296        drawAutofilledHighlight(canvas);
19297
19298        // Overlay is part of the content and draws beneath Foreground
19299        if (mOverlay != null && !mOverlay.isEmpty()) {
19300            mOverlay.getOverlayView().dispatchDraw(canvas);
19301        }
19302
19303        // Step 6, draw decorations (foreground, scrollbars)
19304        onDrawForeground(canvas);
19305
19306        if (debugDraw()) {
19307            debugDrawFocus(canvas);
19308        }
19309    }
19310
19311    /**
19312     * Draws the background onto the specified canvas.
19313     *
19314     * @param canvas Canvas on which to draw the background
19315     */
19316    private void drawBackground(Canvas canvas) {
19317        final Drawable background = mBackground;
19318        if (background == null) {
19319            return;
19320        }
19321
19322        setBackgroundBounds();
19323
19324        // Attempt to use a display list if requested.
19325        if (canvas.isHardwareAccelerated() && mAttachInfo != null
19326                && mAttachInfo.mThreadedRenderer != null) {
19327            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
19328
19329            final RenderNode renderNode = mBackgroundRenderNode;
19330            if (renderNode != null && renderNode.isValid()) {
19331                setBackgroundRenderNodeProperties(renderNode);
19332                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19333                return;
19334            }
19335        }
19336
19337        final int scrollX = mScrollX;
19338        final int scrollY = mScrollY;
19339        if ((scrollX | scrollY) == 0) {
19340            background.draw(canvas);
19341        } else {
19342            canvas.translate(scrollX, scrollY);
19343            background.draw(canvas);
19344            canvas.translate(-scrollX, -scrollY);
19345        }
19346    }
19347
19348    /**
19349     * Sets the correct background bounds and rebuilds the outline, if needed.
19350     * <p/>
19351     * This is called by LayoutLib.
19352     */
19353    void setBackgroundBounds() {
19354        if (mBackgroundSizeChanged && mBackground != null) {
19355            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19356            mBackgroundSizeChanged = false;
19357            rebuildOutline();
19358        }
19359    }
19360
19361    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19362        renderNode.setTranslationX(mScrollX);
19363        renderNode.setTranslationY(mScrollY);
19364    }
19365
19366    /**
19367     * Creates a new display list or updates the existing display list for the
19368     * specified Drawable.
19369     *
19370     * @param drawable Drawable for which to create a display list
19371     * @param renderNode Existing RenderNode, or {@code null}
19372     * @return A valid display list for the specified drawable
19373     */
19374    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19375        if (renderNode == null) {
19376            renderNode = RenderNode.create(drawable.getClass().getName(), this);
19377        }
19378
19379        final Rect bounds = drawable.getBounds();
19380        final int width = bounds.width();
19381        final int height = bounds.height();
19382        final DisplayListCanvas canvas = renderNode.start(width, height);
19383
19384        // Reverse left/top translation done by drawable canvas, which will
19385        // instead be applied by rendernode's LTRB bounds below. This way, the
19386        // drawable's bounds match with its rendernode bounds and its content
19387        // will lie within those bounds in the rendernode tree.
19388        canvas.translate(-bounds.left, -bounds.top);
19389
19390        try {
19391            drawable.draw(canvas);
19392        } finally {
19393            renderNode.end(canvas);
19394        }
19395
19396        // Set up drawable properties that are view-independent.
19397        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19398        renderNode.setProjectBackwards(drawable.isProjected());
19399        renderNode.setProjectionReceiver(true);
19400        renderNode.setClipToBounds(false);
19401        return renderNode;
19402    }
19403
19404    /**
19405     * Returns the overlay for this view, creating it if it does not yet exist.
19406     * Adding drawables to the overlay will cause them to be displayed whenever
19407     * the view itself is redrawn. Objects in the overlay should be actively
19408     * managed: remove them when they should not be displayed anymore. The
19409     * overlay will always have the same size as its host view.
19410     *
19411     * <p>Note: Overlays do not currently work correctly with {@link
19412     * SurfaceView} or {@link TextureView}; contents in overlays for these
19413     * types of views may not display correctly.</p>
19414     *
19415     * @return The ViewOverlay object for this view.
19416     * @see ViewOverlay
19417     */
19418    public ViewOverlay getOverlay() {
19419        if (mOverlay == null) {
19420            mOverlay = new ViewOverlay(mContext, this);
19421        }
19422        return mOverlay;
19423    }
19424
19425    /**
19426     * Override this if your view is known to always be drawn on top of a solid color background,
19427     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19428     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19429     * should be set to 0xFF.
19430     *
19431     * @see #setVerticalFadingEdgeEnabled(boolean)
19432     * @see #setHorizontalFadingEdgeEnabled(boolean)
19433     *
19434     * @return The known solid color background for this view, or 0 if the color may vary
19435     */
19436    @ViewDebug.ExportedProperty(category = "drawing")
19437    @ColorInt
19438    public int getSolidColor() {
19439        return 0;
19440    }
19441
19442    /**
19443     * Build a human readable string representation of the specified view flags.
19444     *
19445     * @param flags the view flags to convert to a string
19446     * @return a String representing the supplied flags
19447     */
19448    private static String printFlags(int flags) {
19449        String output = "";
19450        int numFlags = 0;
19451        if ((flags & FOCUSABLE) == FOCUSABLE) {
19452            output += "TAKES_FOCUS";
19453            numFlags++;
19454        }
19455
19456        switch (flags & VISIBILITY_MASK) {
19457        case INVISIBLE:
19458            if (numFlags > 0) {
19459                output += " ";
19460            }
19461            output += "INVISIBLE";
19462            // USELESS HERE numFlags++;
19463            break;
19464        case GONE:
19465            if (numFlags > 0) {
19466                output += " ";
19467            }
19468            output += "GONE";
19469            // USELESS HERE numFlags++;
19470            break;
19471        default:
19472            break;
19473        }
19474        return output;
19475    }
19476
19477    /**
19478     * Build a human readable string representation of the specified private
19479     * view flags.
19480     *
19481     * @param privateFlags the private view flags to convert to a string
19482     * @return a String representing the supplied flags
19483     */
19484    private static String printPrivateFlags(int privateFlags) {
19485        String output = "";
19486        int numFlags = 0;
19487
19488        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19489            output += "WANTS_FOCUS";
19490            numFlags++;
19491        }
19492
19493        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19494            if (numFlags > 0) {
19495                output += " ";
19496            }
19497            output += "FOCUSED";
19498            numFlags++;
19499        }
19500
19501        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19502            if (numFlags > 0) {
19503                output += " ";
19504            }
19505            output += "SELECTED";
19506            numFlags++;
19507        }
19508
19509        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19510            if (numFlags > 0) {
19511                output += " ";
19512            }
19513            output += "IS_ROOT_NAMESPACE";
19514            numFlags++;
19515        }
19516
19517        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19518            if (numFlags > 0) {
19519                output += " ";
19520            }
19521            output += "HAS_BOUNDS";
19522            numFlags++;
19523        }
19524
19525        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19526            if (numFlags > 0) {
19527                output += " ";
19528            }
19529            output += "DRAWN";
19530            // USELESS HERE numFlags++;
19531        }
19532        return output;
19533    }
19534
19535    /**
19536     * <p>Indicates whether or not this view's layout will be requested during
19537     * the next hierarchy layout pass.</p>
19538     *
19539     * @return true if the layout will be forced during next layout pass
19540     */
19541    public boolean isLayoutRequested() {
19542        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19543    }
19544
19545    /**
19546     * Return true if o is a ViewGroup that is laying out using optical bounds.
19547     * @hide
19548     */
19549    public static boolean isLayoutModeOptical(Object o) {
19550        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19551    }
19552
19553    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19554        Insets parentInsets = mParent instanceof View ?
19555                ((View) mParent).getOpticalInsets() : Insets.NONE;
19556        Insets childInsets = getOpticalInsets();
19557        return setFrame(
19558                left   + parentInsets.left - childInsets.left,
19559                top    + parentInsets.top  - childInsets.top,
19560                right  + parentInsets.left + childInsets.right,
19561                bottom + parentInsets.top  + childInsets.bottom);
19562    }
19563
19564    /**
19565     * Assign a size and position to a view and all of its
19566     * descendants
19567     *
19568     * <p>This is the second phase of the layout mechanism.
19569     * (The first is measuring). In this phase, each parent calls
19570     * layout on all of its children to position them.
19571     * This is typically done using the child measurements
19572     * that were stored in the measure pass().</p>
19573     *
19574     * <p>Derived classes should not override this method.
19575     * Derived classes with children should override
19576     * onLayout. In that method, they should
19577     * call layout on each of their children.</p>
19578     *
19579     * @param l Left position, relative to parent
19580     * @param t Top position, relative to parent
19581     * @param r Right position, relative to parent
19582     * @param b Bottom position, relative to parent
19583     */
19584    @SuppressWarnings({"unchecked"})
19585    public void layout(int l, int t, int r, int b) {
19586        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19587            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19588            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19589        }
19590
19591        int oldL = mLeft;
19592        int oldT = mTop;
19593        int oldB = mBottom;
19594        int oldR = mRight;
19595
19596        boolean changed = isLayoutModeOptical(mParent) ?
19597                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19598
19599        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19600            onLayout(changed, l, t, r, b);
19601
19602            if (shouldDrawRoundScrollbar()) {
19603                if(mRoundScrollbarRenderer == null) {
19604                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19605                }
19606            } else {
19607                mRoundScrollbarRenderer = null;
19608            }
19609
19610            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19611
19612            ListenerInfo li = mListenerInfo;
19613            if (li != null && li.mOnLayoutChangeListeners != null) {
19614                ArrayList<OnLayoutChangeListener> listenersCopy =
19615                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19616                int numListeners = listenersCopy.size();
19617                for (int i = 0; i < numListeners; ++i) {
19618                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19619                }
19620            }
19621        }
19622
19623        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19624        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19625
19626        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
19627            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
19628            notifyEnterOrExitForAutoFillIfNeeded(true);
19629        }
19630    }
19631
19632    /**
19633     * Called from layout when this view should
19634     * assign a size and position to each of its children.
19635     *
19636     * Derived classes with children should override
19637     * this method and call layout on each of
19638     * their children.
19639     * @param changed This is a new size or position for this view
19640     * @param left Left position, relative to parent
19641     * @param top Top position, relative to parent
19642     * @param right Right position, relative to parent
19643     * @param bottom Bottom position, relative to parent
19644     */
19645    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19646    }
19647
19648    /**
19649     * Assign a size and position to this view.
19650     *
19651     * This is called from layout.
19652     *
19653     * @param left Left position, relative to parent
19654     * @param top Top position, relative to parent
19655     * @param right Right position, relative to parent
19656     * @param bottom Bottom position, relative to parent
19657     * @return true if the new size and position are different than the
19658     *         previous ones
19659     * {@hide}
19660     */
19661    protected boolean setFrame(int left, int top, int right, int bottom) {
19662        boolean changed = false;
19663
19664        if (DBG) {
19665            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19666                    + right + "," + bottom + ")");
19667        }
19668
19669        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19670            changed = true;
19671
19672            // Remember our drawn bit
19673            int drawn = mPrivateFlags & PFLAG_DRAWN;
19674
19675            int oldWidth = mRight - mLeft;
19676            int oldHeight = mBottom - mTop;
19677            int newWidth = right - left;
19678            int newHeight = bottom - top;
19679            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19680
19681            // Invalidate our old position
19682            invalidate(sizeChanged);
19683
19684            mLeft = left;
19685            mTop = top;
19686            mRight = right;
19687            mBottom = bottom;
19688            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19689
19690            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19691
19692
19693            if (sizeChanged) {
19694                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19695            }
19696
19697            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19698                // If we are visible, force the DRAWN bit to on so that
19699                // this invalidate will go through (at least to our parent).
19700                // This is because someone may have invalidated this view
19701                // before this call to setFrame came in, thereby clearing
19702                // the DRAWN bit.
19703                mPrivateFlags |= PFLAG_DRAWN;
19704                invalidate(sizeChanged);
19705                // parent display list may need to be recreated based on a change in the bounds
19706                // of any child
19707                invalidateParentCaches();
19708            }
19709
19710            // Reset drawn bit to original value (invalidate turns it off)
19711            mPrivateFlags |= drawn;
19712
19713            mBackgroundSizeChanged = true;
19714            mDefaultFocusHighlightSizeChanged = true;
19715            if (mForegroundInfo != null) {
19716                mForegroundInfo.mBoundsChanged = true;
19717            }
19718
19719            notifySubtreeAccessibilityStateChangedIfNeeded();
19720        }
19721        return changed;
19722    }
19723
19724    /**
19725     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19726     * @hide
19727     */
19728    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19729        setFrame(left, top, right, bottom);
19730    }
19731
19732    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19733        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19734        if (mOverlay != null) {
19735            mOverlay.getOverlayView().setRight(newWidth);
19736            mOverlay.getOverlayView().setBottom(newHeight);
19737        }
19738        rebuildOutline();
19739    }
19740
19741    /**
19742     * Finalize inflating a view from XML.  This is called as the last phase
19743     * of inflation, after all child views have been added.
19744     *
19745     * <p>Even if the subclass overrides onFinishInflate, they should always be
19746     * sure to call the super method, so that we get called.
19747     */
19748    @CallSuper
19749    protected void onFinishInflate() {
19750    }
19751
19752    /**
19753     * Returns the resources associated with this view.
19754     *
19755     * @return Resources object.
19756     */
19757    public Resources getResources() {
19758        return mResources;
19759    }
19760
19761    /**
19762     * Invalidates the specified Drawable.
19763     *
19764     * @param drawable the drawable to invalidate
19765     */
19766    @Override
19767    public void invalidateDrawable(@NonNull Drawable drawable) {
19768        if (verifyDrawable(drawable)) {
19769            final Rect dirty = drawable.getDirtyBounds();
19770            final int scrollX = mScrollX;
19771            final int scrollY = mScrollY;
19772
19773            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19774                    dirty.right + scrollX, dirty.bottom + scrollY);
19775            rebuildOutline();
19776        }
19777    }
19778
19779    /**
19780     * Schedules an action on a drawable to occur at a specified time.
19781     *
19782     * @param who the recipient of the action
19783     * @param what the action to run on the drawable
19784     * @param when the time at which the action must occur. Uses the
19785     *        {@link SystemClock#uptimeMillis} timebase.
19786     */
19787    @Override
19788    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19789        if (verifyDrawable(who) && what != null) {
19790            final long delay = when - SystemClock.uptimeMillis();
19791            if (mAttachInfo != null) {
19792                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19793                        Choreographer.CALLBACK_ANIMATION, what, who,
19794                        Choreographer.subtractFrameDelay(delay));
19795            } else {
19796                // Postpone the runnable until we know
19797                // on which thread it needs to run.
19798                getRunQueue().postDelayed(what, delay);
19799            }
19800        }
19801    }
19802
19803    /**
19804     * Cancels a scheduled action on a drawable.
19805     *
19806     * @param who the recipient of the action
19807     * @param what the action to cancel
19808     */
19809    @Override
19810    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19811        if (verifyDrawable(who) && what != null) {
19812            if (mAttachInfo != null) {
19813                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19814                        Choreographer.CALLBACK_ANIMATION, what, who);
19815            }
19816            getRunQueue().removeCallbacks(what);
19817        }
19818    }
19819
19820    /**
19821     * Unschedule any events associated with the given Drawable.  This can be
19822     * used when selecting a new Drawable into a view, so that the previous
19823     * one is completely unscheduled.
19824     *
19825     * @param who The Drawable to unschedule.
19826     *
19827     * @see #drawableStateChanged
19828     */
19829    public void unscheduleDrawable(Drawable who) {
19830        if (mAttachInfo != null && who != null) {
19831            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19832                    Choreographer.CALLBACK_ANIMATION, null, who);
19833        }
19834    }
19835
19836    /**
19837     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19838     * that the View directionality can and will be resolved before its Drawables.
19839     *
19840     * Will call {@link View#onResolveDrawables} when resolution is done.
19841     *
19842     * @hide
19843     */
19844    protected void resolveDrawables() {
19845        // Drawables resolution may need to happen before resolving the layout direction (which is
19846        // done only during the measure() call).
19847        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19848        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19849        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19850        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19851        // direction to be resolved as its resolved value will be the same as its raw value.
19852        if (!isLayoutDirectionResolved() &&
19853                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19854            return;
19855        }
19856
19857        final int layoutDirection = isLayoutDirectionResolved() ?
19858                getLayoutDirection() : getRawLayoutDirection();
19859
19860        if (mBackground != null) {
19861            mBackground.setLayoutDirection(layoutDirection);
19862        }
19863        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19864            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19865        }
19866        if (mDefaultFocusHighlight != null) {
19867            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19868        }
19869        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19870        onResolveDrawables(layoutDirection);
19871    }
19872
19873    boolean areDrawablesResolved() {
19874        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19875    }
19876
19877    /**
19878     * Called when layout direction has been resolved.
19879     *
19880     * The default implementation does nothing.
19881     *
19882     * @param layoutDirection The resolved layout direction.
19883     *
19884     * @see #LAYOUT_DIRECTION_LTR
19885     * @see #LAYOUT_DIRECTION_RTL
19886     *
19887     * @hide
19888     */
19889    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19890    }
19891
19892    /**
19893     * @hide
19894     */
19895    protected void resetResolvedDrawables() {
19896        resetResolvedDrawablesInternal();
19897    }
19898
19899    void resetResolvedDrawablesInternal() {
19900        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19901    }
19902
19903    /**
19904     * If your view subclass is displaying its own Drawable objects, it should
19905     * override this function and return true for any Drawable it is
19906     * displaying.  This allows animations for those drawables to be
19907     * scheduled.
19908     *
19909     * <p>Be sure to call through to the super class when overriding this
19910     * function.
19911     *
19912     * @param who The Drawable to verify.  Return true if it is one you are
19913     *            displaying, else return the result of calling through to the
19914     *            super class.
19915     *
19916     * @return boolean If true than the Drawable is being displayed in the
19917     *         view; else false and it is not allowed to animate.
19918     *
19919     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19920     * @see #drawableStateChanged()
19921     */
19922    @CallSuper
19923    protected boolean verifyDrawable(@NonNull Drawable who) {
19924        // Avoid verifying the scroll bar drawable so that we don't end up in
19925        // an invalidation loop. This effectively prevents the scroll bar
19926        // drawable from triggering invalidations and scheduling runnables.
19927        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19928                || (mDefaultFocusHighlight == who);
19929    }
19930
19931    /**
19932     * This function is called whenever the state of the view changes in such
19933     * a way that it impacts the state of drawables being shown.
19934     * <p>
19935     * If the View has a StateListAnimator, it will also be called to run necessary state
19936     * change animations.
19937     * <p>
19938     * Be sure to call through to the superclass when overriding this function.
19939     *
19940     * @see Drawable#setState(int[])
19941     */
19942    @CallSuper
19943    protected void drawableStateChanged() {
19944        final int[] state = getDrawableState();
19945        boolean changed = false;
19946
19947        final Drawable bg = mBackground;
19948        if (bg != null && bg.isStateful()) {
19949            changed |= bg.setState(state);
19950        }
19951
19952        final Drawable hl = mDefaultFocusHighlight;
19953        if (hl != null && hl.isStateful()) {
19954            changed |= hl.setState(state);
19955        }
19956
19957        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19958        if (fg != null && fg.isStateful()) {
19959            changed |= fg.setState(state);
19960        }
19961
19962        if (mScrollCache != null) {
19963            final Drawable scrollBar = mScrollCache.scrollBar;
19964            if (scrollBar != null && scrollBar.isStateful()) {
19965                changed |= scrollBar.setState(state)
19966                        && mScrollCache.state != ScrollabilityCache.OFF;
19967            }
19968        }
19969
19970        if (mStateListAnimator != null) {
19971            mStateListAnimator.setState(state);
19972        }
19973
19974        if (changed) {
19975            invalidate();
19976        }
19977    }
19978
19979    /**
19980     * This function is called whenever the view hotspot changes and needs to
19981     * be propagated to drawables or child views managed by the view.
19982     * <p>
19983     * Dispatching to child views is handled by
19984     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19985     * <p>
19986     * Be sure to call through to the superclass when overriding this function.
19987     *
19988     * @param x hotspot x coordinate
19989     * @param y hotspot y coordinate
19990     */
19991    @CallSuper
19992    public void drawableHotspotChanged(float x, float y) {
19993        if (mBackground != null) {
19994            mBackground.setHotspot(x, y);
19995        }
19996        if (mDefaultFocusHighlight != null) {
19997            mDefaultFocusHighlight.setHotspot(x, y);
19998        }
19999        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20000            mForegroundInfo.mDrawable.setHotspot(x, y);
20001        }
20002
20003        dispatchDrawableHotspotChanged(x, y);
20004    }
20005
20006    /**
20007     * Dispatches drawableHotspotChanged to all of this View's children.
20008     *
20009     * @param x hotspot x coordinate
20010     * @param y hotspot y coordinate
20011     * @see #drawableHotspotChanged(float, float)
20012     */
20013    public void dispatchDrawableHotspotChanged(float x, float y) {
20014    }
20015
20016    /**
20017     * Call this to force a view to update its drawable state. This will cause
20018     * drawableStateChanged to be called on this view. Views that are interested
20019     * in the new state should call getDrawableState.
20020     *
20021     * @see #drawableStateChanged
20022     * @see #getDrawableState
20023     */
20024    public void refreshDrawableState() {
20025        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20026        drawableStateChanged();
20027
20028        ViewParent parent = mParent;
20029        if (parent != null) {
20030            parent.childDrawableStateChanged(this);
20031        }
20032    }
20033
20034    /**
20035     * Create a default focus highlight if it doesn't exist.
20036     * @return a default focus highlight.
20037     */
20038    private Drawable getDefaultFocusHighlightDrawable() {
20039        if (mDefaultFocusHighlightCache == null) {
20040            if (mContext != null) {
20041                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
20042                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
20043                mDefaultFocusHighlightCache = ta.getDrawable(0);
20044                ta.recycle();
20045            }
20046        }
20047        return mDefaultFocusHighlightCache;
20048    }
20049
20050    /**
20051     * Set the current default focus highlight.
20052     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
20053     */
20054    private void setDefaultFocusHighlight(Drawable highlight) {
20055        mDefaultFocusHighlight = highlight;
20056        mDefaultFocusHighlightSizeChanged = true;
20057        if (highlight != null) {
20058            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20059                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20060            }
20061            highlight.setLayoutDirection(getLayoutDirection());
20062            if (highlight.isStateful()) {
20063                highlight.setState(getDrawableState());
20064            }
20065            if (isAttachedToWindow()) {
20066                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20067            }
20068            // Set callback last, since the view may still be initializing.
20069            highlight.setCallback(this);
20070        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20071                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20072            mPrivateFlags |= PFLAG_SKIP_DRAW;
20073        }
20074        invalidate();
20075    }
20076
20077    /**
20078     * Check whether we need to draw a default focus highlight when this view gets focused,
20079     * which requires:
20080     * <ul>
20081     *     <li>In both background and foreground, {@link android.R.attr#state_focused}
20082     *         is not defined.</li>
20083     *     <li>This view is not in touch mode.</li>
20084     *     <li>This view doesn't opt out for a default focus highlight, via
20085     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
20086     *     <li>This view is attached to window.</li>
20087     * </ul>
20088     * @return {@code true} if a default focus highlight is needed.
20089     * @hide
20090     */
20091    @TestApi
20092    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
20093        final boolean lackFocusState = (background == null || !background.isStateful()
20094                || !background.hasFocusStateSpecified())
20095                && (foreground == null || !foreground.isStateful()
20096                || !foreground.hasFocusStateSpecified());
20097        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
20098                && isAttachedToWindow() && sUseDefaultFocusHighlight;
20099    }
20100
20101    /**
20102     * When this view is focused, switches on/off the default focused highlight.
20103     * <p>
20104     * This always happens when this view is focused, and only at this moment the default focus
20105     * highlight can be visible.
20106     */
20107    private void switchDefaultFocusHighlight() {
20108        if (isFocused()) {
20109            final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
20110                    mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
20111            final boolean active = mDefaultFocusHighlight != null;
20112            if (needed && !active) {
20113                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
20114            } else if (!needed && active) {
20115                // The highlight is no longer needed, so tear it down.
20116                setDefaultFocusHighlight(null);
20117            }
20118        }
20119    }
20120
20121    /**
20122     * Draw the default focus highlight onto the canvas.
20123     * @param canvas the canvas where we're drawing the highlight.
20124     */
20125    private void drawDefaultFocusHighlight(Canvas canvas) {
20126        if (mDefaultFocusHighlight != null) {
20127            if (mDefaultFocusHighlightSizeChanged) {
20128                mDefaultFocusHighlightSizeChanged = false;
20129                final int l = mScrollX;
20130                final int r = l + mRight - mLeft;
20131                final int t = mScrollY;
20132                final int b = t + mBottom - mTop;
20133                mDefaultFocusHighlight.setBounds(l, t, r, b);
20134            }
20135            mDefaultFocusHighlight.draw(canvas);
20136        }
20137    }
20138
20139    /**
20140     * Return an array of resource IDs of the drawable states representing the
20141     * current state of the view.
20142     *
20143     * @return The current drawable state
20144     *
20145     * @see Drawable#setState(int[])
20146     * @see #drawableStateChanged()
20147     * @see #onCreateDrawableState(int)
20148     */
20149    public final int[] getDrawableState() {
20150        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
20151            return mDrawableState;
20152        } else {
20153            mDrawableState = onCreateDrawableState(0);
20154            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
20155            return mDrawableState;
20156        }
20157    }
20158
20159    /**
20160     * Generate the new {@link android.graphics.drawable.Drawable} state for
20161     * this view. This is called by the view
20162     * system when the cached Drawable state is determined to be invalid.  To
20163     * retrieve the current state, you should use {@link #getDrawableState}.
20164     *
20165     * @param extraSpace if non-zero, this is the number of extra entries you
20166     * would like in the returned array in which you can place your own
20167     * states.
20168     *
20169     * @return Returns an array holding the current {@link Drawable} state of
20170     * the view.
20171     *
20172     * @see #mergeDrawableStates(int[], int[])
20173     */
20174    protected int[] onCreateDrawableState(int extraSpace) {
20175        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
20176                mParent instanceof View) {
20177            return ((View) mParent).onCreateDrawableState(extraSpace);
20178        }
20179
20180        int[] drawableState;
20181
20182        int privateFlags = mPrivateFlags;
20183
20184        int viewStateIndex = 0;
20185        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
20186        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
20187        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
20188        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
20189        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
20190        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
20191        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
20192                ThreadedRenderer.isAvailable()) {
20193            // This is set if HW acceleration is requested, even if the current
20194            // process doesn't allow it.  This is just to allow app preview
20195            // windows to better match their app.
20196            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
20197        }
20198        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
20199
20200        final int privateFlags2 = mPrivateFlags2;
20201        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
20202            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
20203        }
20204        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
20205            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
20206        }
20207
20208        drawableState = StateSet.get(viewStateIndex);
20209
20210        //noinspection ConstantIfStatement
20211        if (false) {
20212            Log.i("View", "drawableStateIndex=" + viewStateIndex);
20213            Log.i("View", toString()
20214                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
20215                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
20216                    + " fo=" + hasFocus()
20217                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
20218                    + " wf=" + hasWindowFocus()
20219                    + ": " + Arrays.toString(drawableState));
20220        }
20221
20222        if (extraSpace == 0) {
20223            return drawableState;
20224        }
20225
20226        final int[] fullState;
20227        if (drawableState != null) {
20228            fullState = new int[drawableState.length + extraSpace];
20229            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
20230        } else {
20231            fullState = new int[extraSpace];
20232        }
20233
20234        return fullState;
20235    }
20236
20237    /**
20238     * Merge your own state values in <var>additionalState</var> into the base
20239     * state values <var>baseState</var> that were returned by
20240     * {@link #onCreateDrawableState(int)}.
20241     *
20242     * @param baseState The base state values returned by
20243     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
20244     * own additional state values.
20245     *
20246     * @param additionalState The additional state values you would like
20247     * added to <var>baseState</var>; this array is not modified.
20248     *
20249     * @return As a convenience, the <var>baseState</var> array you originally
20250     * passed into the function is returned.
20251     *
20252     * @see #onCreateDrawableState(int)
20253     */
20254    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
20255        final int N = baseState.length;
20256        int i = N - 1;
20257        while (i >= 0 && baseState[i] == 0) {
20258            i--;
20259        }
20260        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
20261        return baseState;
20262    }
20263
20264    /**
20265     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
20266     * on all Drawable objects associated with this view.
20267     * <p>
20268     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
20269     * attached to this view.
20270     */
20271    @CallSuper
20272    public void jumpDrawablesToCurrentState() {
20273        if (mBackground != null) {
20274            mBackground.jumpToCurrentState();
20275        }
20276        if (mStateListAnimator != null) {
20277            mStateListAnimator.jumpToCurrentState();
20278        }
20279        if (mDefaultFocusHighlight != null) {
20280            mDefaultFocusHighlight.jumpToCurrentState();
20281        }
20282        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20283            mForegroundInfo.mDrawable.jumpToCurrentState();
20284        }
20285    }
20286
20287    /**
20288     * Sets the background color for this view.
20289     * @param color the color of the background
20290     */
20291    @RemotableViewMethod
20292    public void setBackgroundColor(@ColorInt int color) {
20293        if (mBackground instanceof ColorDrawable) {
20294            ((ColorDrawable) mBackground.mutate()).setColor(color);
20295            computeOpaqueFlags();
20296            mBackgroundResource = 0;
20297        } else {
20298            setBackground(new ColorDrawable(color));
20299        }
20300    }
20301
20302    /**
20303     * Set the background to a given resource. The resource should refer to
20304     * a Drawable object or 0 to remove the background.
20305     * @param resid The identifier of the resource.
20306     *
20307     * @attr ref android.R.styleable#View_background
20308     */
20309    @RemotableViewMethod
20310    public void setBackgroundResource(@DrawableRes int resid) {
20311        if (resid != 0 && resid == mBackgroundResource) {
20312            return;
20313        }
20314
20315        Drawable d = null;
20316        if (resid != 0) {
20317            d = mContext.getDrawable(resid);
20318        }
20319        setBackground(d);
20320
20321        mBackgroundResource = resid;
20322    }
20323
20324    /**
20325     * Set the background to a given Drawable, or remove the background. If the
20326     * background has padding, this View's padding is set to the background's
20327     * padding. However, when a background is removed, this View's padding isn't
20328     * touched. If setting the padding is desired, please use
20329     * {@link #setPadding(int, int, int, int)}.
20330     *
20331     * @param background The Drawable to use as the background, or null to remove the
20332     *        background
20333     */
20334    public void setBackground(Drawable background) {
20335        //noinspection deprecation
20336        setBackgroundDrawable(background);
20337    }
20338
20339    /**
20340     * @deprecated use {@link #setBackground(Drawable)} instead
20341     */
20342    @Deprecated
20343    public void setBackgroundDrawable(Drawable background) {
20344        computeOpaqueFlags();
20345
20346        if (background == mBackground) {
20347            return;
20348        }
20349
20350        boolean requestLayout = false;
20351
20352        mBackgroundResource = 0;
20353
20354        /*
20355         * Regardless of whether we're setting a new background or not, we want
20356         * to clear the previous drawable. setVisible first while we still have the callback set.
20357         */
20358        if (mBackground != null) {
20359            if (isAttachedToWindow()) {
20360                mBackground.setVisible(false, false);
20361            }
20362            mBackground.setCallback(null);
20363            unscheduleDrawable(mBackground);
20364        }
20365
20366        if (background != null) {
20367            Rect padding = sThreadLocal.get();
20368            if (padding == null) {
20369                padding = new Rect();
20370                sThreadLocal.set(padding);
20371            }
20372            resetResolvedDrawablesInternal();
20373            background.setLayoutDirection(getLayoutDirection());
20374            if (background.getPadding(padding)) {
20375                resetResolvedPaddingInternal();
20376                switch (background.getLayoutDirection()) {
20377                    case LAYOUT_DIRECTION_RTL:
20378                        mUserPaddingLeftInitial = padding.right;
20379                        mUserPaddingRightInitial = padding.left;
20380                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20381                        break;
20382                    case LAYOUT_DIRECTION_LTR:
20383                    default:
20384                        mUserPaddingLeftInitial = padding.left;
20385                        mUserPaddingRightInitial = padding.right;
20386                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20387                }
20388                mLeftPaddingDefined = false;
20389                mRightPaddingDefined = false;
20390            }
20391
20392            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20393            // if it has a different minimum size, we should layout again
20394            if (mBackground == null
20395                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
20396                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20397                requestLayout = true;
20398            }
20399
20400            // Set mBackground before we set this as the callback and start making other
20401            // background drawable state change calls. In particular, the setVisible call below
20402            // can result in drawables attempting to start animations or otherwise invalidate,
20403            // which requires the view set as the callback (us) to recognize the drawable as
20404            // belonging to it as per verifyDrawable.
20405            mBackground = background;
20406            if (background.isStateful()) {
20407                background.setState(getDrawableState());
20408            }
20409            if (isAttachedToWindow()) {
20410                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20411            }
20412
20413            applyBackgroundTint();
20414
20415            // Set callback last, since the view may still be initializing.
20416            background.setCallback(this);
20417
20418            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20419                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20420                requestLayout = true;
20421            }
20422        } else {
20423            /* Remove the background */
20424            mBackground = null;
20425            if ((mViewFlags & WILL_NOT_DRAW) != 0
20426                    && (mDefaultFocusHighlight == null)
20427                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20428                mPrivateFlags |= PFLAG_SKIP_DRAW;
20429            }
20430
20431            /*
20432             * When the background is set, we try to apply its padding to this
20433             * View. When the background is removed, we don't touch this View's
20434             * padding. This is noted in the Javadocs. Hence, we don't need to
20435             * requestLayout(), the invalidate() below is sufficient.
20436             */
20437
20438            // The old background's minimum size could have affected this
20439            // View's layout, so let's requestLayout
20440            requestLayout = true;
20441        }
20442
20443        computeOpaqueFlags();
20444
20445        if (requestLayout) {
20446            requestLayout();
20447        }
20448
20449        mBackgroundSizeChanged = true;
20450        invalidate(true);
20451        invalidateOutline();
20452    }
20453
20454    /**
20455     * Gets the background drawable
20456     *
20457     * @return The drawable used as the background for this view, if any.
20458     *
20459     * @see #setBackground(Drawable)
20460     *
20461     * @attr ref android.R.styleable#View_background
20462     */
20463    public Drawable getBackground() {
20464        return mBackground;
20465    }
20466
20467    /**
20468     * Applies a tint to the background drawable. Does not modify the current tint
20469     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20470     * <p>
20471     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20472     * mutate the drawable and apply the specified tint and tint mode using
20473     * {@link Drawable#setTintList(ColorStateList)}.
20474     *
20475     * @param tint the tint to apply, may be {@code null} to clear tint
20476     *
20477     * @attr ref android.R.styleable#View_backgroundTint
20478     * @see #getBackgroundTintList()
20479     * @see Drawable#setTintList(ColorStateList)
20480     */
20481    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20482        if (mBackgroundTint == null) {
20483            mBackgroundTint = new TintInfo();
20484        }
20485        mBackgroundTint.mTintList = tint;
20486        mBackgroundTint.mHasTintList = true;
20487
20488        applyBackgroundTint();
20489    }
20490
20491    /**
20492     * Return the tint applied to the background drawable, if specified.
20493     *
20494     * @return the tint applied to the background drawable
20495     * @attr ref android.R.styleable#View_backgroundTint
20496     * @see #setBackgroundTintList(ColorStateList)
20497     */
20498    @Nullable
20499    public ColorStateList getBackgroundTintList() {
20500        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20501    }
20502
20503    /**
20504     * Specifies the blending mode used to apply the tint specified by
20505     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20506     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20507     *
20508     * @param tintMode the blending mode used to apply the tint, may be
20509     *                 {@code null} to clear tint
20510     * @attr ref android.R.styleable#View_backgroundTintMode
20511     * @see #getBackgroundTintMode()
20512     * @see Drawable#setTintMode(PorterDuff.Mode)
20513     */
20514    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20515        if (mBackgroundTint == null) {
20516            mBackgroundTint = new TintInfo();
20517        }
20518        mBackgroundTint.mTintMode = tintMode;
20519        mBackgroundTint.mHasTintMode = true;
20520
20521        applyBackgroundTint();
20522    }
20523
20524    /**
20525     * Return the blending mode used to apply the tint to the background
20526     * drawable, if specified.
20527     *
20528     * @return the blending mode used to apply the tint to the background
20529     *         drawable
20530     * @attr ref android.R.styleable#View_backgroundTintMode
20531     * @see #setBackgroundTintMode(PorterDuff.Mode)
20532     */
20533    @Nullable
20534    public PorterDuff.Mode getBackgroundTintMode() {
20535        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20536    }
20537
20538    private void applyBackgroundTint() {
20539        if (mBackground != null && mBackgroundTint != null) {
20540            final TintInfo tintInfo = mBackgroundTint;
20541            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20542                mBackground = mBackground.mutate();
20543
20544                if (tintInfo.mHasTintList) {
20545                    mBackground.setTintList(tintInfo.mTintList);
20546                }
20547
20548                if (tintInfo.mHasTintMode) {
20549                    mBackground.setTintMode(tintInfo.mTintMode);
20550                }
20551
20552                // The drawable (or one of its children) may not have been
20553                // stateful before applying the tint, so let's try again.
20554                if (mBackground.isStateful()) {
20555                    mBackground.setState(getDrawableState());
20556                }
20557            }
20558        }
20559    }
20560
20561    /**
20562     * Returns the drawable used as the foreground of this View. The
20563     * foreground drawable, if non-null, is always drawn on top of the view's content.
20564     *
20565     * @return a Drawable or null if no foreground was set
20566     *
20567     * @see #onDrawForeground(Canvas)
20568     */
20569    public Drawable getForeground() {
20570        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20571    }
20572
20573    /**
20574     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20575     *
20576     * @param foreground the Drawable to be drawn on top of the children
20577     *
20578     * @attr ref android.R.styleable#View_foreground
20579     */
20580    public void setForeground(Drawable foreground) {
20581        if (mForegroundInfo == null) {
20582            if (foreground == null) {
20583                // Nothing to do.
20584                return;
20585            }
20586            mForegroundInfo = new ForegroundInfo();
20587        }
20588
20589        if (foreground == mForegroundInfo.mDrawable) {
20590            // Nothing to do
20591            return;
20592        }
20593
20594        if (mForegroundInfo.mDrawable != null) {
20595            if (isAttachedToWindow()) {
20596                mForegroundInfo.mDrawable.setVisible(false, false);
20597            }
20598            mForegroundInfo.mDrawable.setCallback(null);
20599            unscheduleDrawable(mForegroundInfo.mDrawable);
20600        }
20601
20602        mForegroundInfo.mDrawable = foreground;
20603        mForegroundInfo.mBoundsChanged = true;
20604        if (foreground != null) {
20605            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20606                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20607            }
20608            foreground.setLayoutDirection(getLayoutDirection());
20609            if (foreground.isStateful()) {
20610                foreground.setState(getDrawableState());
20611            }
20612            applyForegroundTint();
20613            if (isAttachedToWindow()) {
20614                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20615            }
20616            // Set callback last, since the view may still be initializing.
20617            foreground.setCallback(this);
20618        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20619                && (mDefaultFocusHighlight == null)) {
20620            mPrivateFlags |= PFLAG_SKIP_DRAW;
20621        }
20622        requestLayout();
20623        invalidate();
20624    }
20625
20626    /**
20627     * Magic bit used to support features of framework-internal window decor implementation details.
20628     * This used to live exclusively in FrameLayout.
20629     *
20630     * @return true if the foreground should draw inside the padding region or false
20631     *         if it should draw inset by the view's padding
20632     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20633     */
20634    public boolean isForegroundInsidePadding() {
20635        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20636    }
20637
20638    /**
20639     * Describes how the foreground is positioned.
20640     *
20641     * @return foreground gravity.
20642     *
20643     * @see #setForegroundGravity(int)
20644     *
20645     * @attr ref android.R.styleable#View_foregroundGravity
20646     */
20647    public int getForegroundGravity() {
20648        return mForegroundInfo != null ? mForegroundInfo.mGravity
20649                : Gravity.START | Gravity.TOP;
20650    }
20651
20652    /**
20653     * Describes how the foreground is positioned. Defaults to START and TOP.
20654     *
20655     * @param gravity see {@link android.view.Gravity}
20656     *
20657     * @see #getForegroundGravity()
20658     *
20659     * @attr ref android.R.styleable#View_foregroundGravity
20660     */
20661    public void setForegroundGravity(int gravity) {
20662        if (mForegroundInfo == null) {
20663            mForegroundInfo = new ForegroundInfo();
20664        }
20665
20666        if (mForegroundInfo.mGravity != gravity) {
20667            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20668                gravity |= Gravity.START;
20669            }
20670
20671            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20672                gravity |= Gravity.TOP;
20673            }
20674
20675            mForegroundInfo.mGravity = gravity;
20676            requestLayout();
20677        }
20678    }
20679
20680    /**
20681     * Applies a tint to the foreground drawable. Does not modify the current tint
20682     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20683     * <p>
20684     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20685     * mutate the drawable and apply the specified tint and tint mode using
20686     * {@link Drawable#setTintList(ColorStateList)}.
20687     *
20688     * @param tint the tint to apply, may be {@code null} to clear tint
20689     *
20690     * @attr ref android.R.styleable#View_foregroundTint
20691     * @see #getForegroundTintList()
20692     * @see Drawable#setTintList(ColorStateList)
20693     */
20694    public void setForegroundTintList(@Nullable ColorStateList tint) {
20695        if (mForegroundInfo == null) {
20696            mForegroundInfo = new ForegroundInfo();
20697        }
20698        if (mForegroundInfo.mTintInfo == null) {
20699            mForegroundInfo.mTintInfo = new TintInfo();
20700        }
20701        mForegroundInfo.mTintInfo.mTintList = tint;
20702        mForegroundInfo.mTintInfo.mHasTintList = true;
20703
20704        applyForegroundTint();
20705    }
20706
20707    /**
20708     * Return the tint applied to the foreground drawable, if specified.
20709     *
20710     * @return the tint applied to the foreground drawable
20711     * @attr ref android.R.styleable#View_foregroundTint
20712     * @see #setForegroundTintList(ColorStateList)
20713     */
20714    @Nullable
20715    public ColorStateList getForegroundTintList() {
20716        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20717                ? mForegroundInfo.mTintInfo.mTintList : null;
20718    }
20719
20720    /**
20721     * Specifies the blending mode used to apply the tint specified by
20722     * {@link #setForegroundTintList(ColorStateList)}} to the background
20723     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20724     *
20725     * @param tintMode the blending mode used to apply the tint, may be
20726     *                 {@code null} to clear tint
20727     * @attr ref android.R.styleable#View_foregroundTintMode
20728     * @see #getForegroundTintMode()
20729     * @see Drawable#setTintMode(PorterDuff.Mode)
20730     */
20731    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20732        if (mForegroundInfo == null) {
20733            mForegroundInfo = new ForegroundInfo();
20734        }
20735        if (mForegroundInfo.mTintInfo == null) {
20736            mForegroundInfo.mTintInfo = new TintInfo();
20737        }
20738        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20739        mForegroundInfo.mTintInfo.mHasTintMode = true;
20740
20741        applyForegroundTint();
20742    }
20743
20744    /**
20745     * Return the blending mode used to apply the tint to the foreground
20746     * drawable, if specified.
20747     *
20748     * @return the blending mode used to apply the tint to the foreground
20749     *         drawable
20750     * @attr ref android.R.styleable#View_foregroundTintMode
20751     * @see #setForegroundTintMode(PorterDuff.Mode)
20752     */
20753    @Nullable
20754    public PorterDuff.Mode getForegroundTintMode() {
20755        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20756                ? mForegroundInfo.mTintInfo.mTintMode : null;
20757    }
20758
20759    private void applyForegroundTint() {
20760        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20761                && mForegroundInfo.mTintInfo != null) {
20762            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20763            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20764                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20765
20766                if (tintInfo.mHasTintList) {
20767                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20768                }
20769
20770                if (tintInfo.mHasTintMode) {
20771                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20772                }
20773
20774                // The drawable (or one of its children) may not have been
20775                // stateful before applying the tint, so let's try again.
20776                if (mForegroundInfo.mDrawable.isStateful()) {
20777                    mForegroundInfo.mDrawable.setState(getDrawableState());
20778                }
20779            }
20780        }
20781    }
20782
20783    /**
20784     * Get the drawable to be overlayed when a view is autofilled
20785     *
20786     * @return The drawable
20787     *
20788     * @throws IllegalStateException if the drawable could not be found.
20789     */
20790    @Nullable private Drawable getAutofilledDrawable() {
20791        if (mAttachInfo == null) {
20792            return null;
20793        }
20794        // Lazily load the isAutofilled drawable.
20795        if (mAttachInfo.mAutofilledDrawable == null) {
20796            Context rootContext = getRootView().getContext();
20797            TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20798            int attributeResourceId = a.getResourceId(0, 0);
20799            mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
20800            a.recycle();
20801        }
20802
20803        return mAttachInfo.mAutofilledDrawable;
20804    }
20805
20806    /**
20807     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20808     *
20809     * @param canvas The canvas to draw on
20810     */
20811    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20812        if (isAutofilled()) {
20813            Drawable autofilledHighlight = getAutofilledDrawable();
20814
20815            if (autofilledHighlight != null) {
20816                autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20817                autofilledHighlight.draw(canvas);
20818            }
20819        }
20820    }
20821
20822    /**
20823     * Draw any foreground content for this view.
20824     *
20825     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20826     * drawable or other view-specific decorations. The foreground is drawn on top of the
20827     * primary view content.</p>
20828     *
20829     * @param canvas canvas to draw into
20830     */
20831    public void onDrawForeground(Canvas canvas) {
20832        onDrawScrollIndicators(canvas);
20833        onDrawScrollBars(canvas);
20834
20835        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20836        if (foreground != null) {
20837            if (mForegroundInfo.mBoundsChanged) {
20838                mForegroundInfo.mBoundsChanged = false;
20839                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20840                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20841
20842                if (mForegroundInfo.mInsidePadding) {
20843                    selfBounds.set(0, 0, getWidth(), getHeight());
20844                } else {
20845                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20846                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20847                }
20848
20849                final int ld = getLayoutDirection();
20850                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20851                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20852                foreground.setBounds(overlayBounds);
20853            }
20854
20855            foreground.draw(canvas);
20856        }
20857    }
20858
20859    /**
20860     * Sets the padding. The view may add on the space required to display
20861     * the scrollbars, depending on the style and visibility of the scrollbars.
20862     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20863     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20864     * from the values set in this call.
20865     *
20866     * @attr ref android.R.styleable#View_padding
20867     * @attr ref android.R.styleable#View_paddingBottom
20868     * @attr ref android.R.styleable#View_paddingLeft
20869     * @attr ref android.R.styleable#View_paddingRight
20870     * @attr ref android.R.styleable#View_paddingTop
20871     * @param left the left padding in pixels
20872     * @param top the top padding in pixels
20873     * @param right the right padding in pixels
20874     * @param bottom the bottom padding in pixels
20875     */
20876    public void setPadding(int left, int top, int right, int bottom) {
20877        resetResolvedPaddingInternal();
20878
20879        mUserPaddingStart = UNDEFINED_PADDING;
20880        mUserPaddingEnd = UNDEFINED_PADDING;
20881
20882        mUserPaddingLeftInitial = left;
20883        mUserPaddingRightInitial = right;
20884
20885        mLeftPaddingDefined = true;
20886        mRightPaddingDefined = true;
20887
20888        internalSetPadding(left, top, right, bottom);
20889    }
20890
20891    /**
20892     * @hide
20893     */
20894    protected void internalSetPadding(int left, int top, int right, int bottom) {
20895        mUserPaddingLeft = left;
20896        mUserPaddingRight = right;
20897        mUserPaddingBottom = bottom;
20898
20899        final int viewFlags = mViewFlags;
20900        boolean changed = false;
20901
20902        // Common case is there are no scroll bars.
20903        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20904            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20905                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20906                        ? 0 : getVerticalScrollbarWidth();
20907                switch (mVerticalScrollbarPosition) {
20908                    case SCROLLBAR_POSITION_DEFAULT:
20909                        if (isLayoutRtl()) {
20910                            left += offset;
20911                        } else {
20912                            right += offset;
20913                        }
20914                        break;
20915                    case SCROLLBAR_POSITION_RIGHT:
20916                        right += offset;
20917                        break;
20918                    case SCROLLBAR_POSITION_LEFT:
20919                        left += offset;
20920                        break;
20921                }
20922            }
20923            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20924                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20925                        ? 0 : getHorizontalScrollbarHeight();
20926            }
20927        }
20928
20929        if (mPaddingLeft != left) {
20930            changed = true;
20931            mPaddingLeft = left;
20932        }
20933        if (mPaddingTop != top) {
20934            changed = true;
20935            mPaddingTop = top;
20936        }
20937        if (mPaddingRight != right) {
20938            changed = true;
20939            mPaddingRight = right;
20940        }
20941        if (mPaddingBottom != bottom) {
20942            changed = true;
20943            mPaddingBottom = bottom;
20944        }
20945
20946        if (changed) {
20947            requestLayout();
20948            invalidateOutline();
20949        }
20950    }
20951
20952    /**
20953     * Sets the relative padding. The view may add on the space required to display
20954     * the scrollbars, depending on the style and visibility of the scrollbars.
20955     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20956     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20957     * from the values set in this call.
20958     *
20959     * @attr ref android.R.styleable#View_padding
20960     * @attr ref android.R.styleable#View_paddingBottom
20961     * @attr ref android.R.styleable#View_paddingStart
20962     * @attr ref android.R.styleable#View_paddingEnd
20963     * @attr ref android.R.styleable#View_paddingTop
20964     * @param start the start padding in pixels
20965     * @param top the top padding in pixels
20966     * @param end the end padding in pixels
20967     * @param bottom the bottom padding in pixels
20968     */
20969    public void setPaddingRelative(int start, int top, int end, int bottom) {
20970        resetResolvedPaddingInternal();
20971
20972        mUserPaddingStart = start;
20973        mUserPaddingEnd = end;
20974        mLeftPaddingDefined = true;
20975        mRightPaddingDefined = true;
20976
20977        switch(getLayoutDirection()) {
20978            case LAYOUT_DIRECTION_RTL:
20979                mUserPaddingLeftInitial = end;
20980                mUserPaddingRightInitial = start;
20981                internalSetPadding(end, top, start, bottom);
20982                break;
20983            case LAYOUT_DIRECTION_LTR:
20984            default:
20985                mUserPaddingLeftInitial = start;
20986                mUserPaddingRightInitial = end;
20987                internalSetPadding(start, top, end, bottom);
20988        }
20989    }
20990
20991    /**
20992     * Returns the top padding of this view.
20993     *
20994     * @return the top padding in pixels
20995     */
20996    public int getPaddingTop() {
20997        return mPaddingTop;
20998    }
20999
21000    /**
21001     * Returns the bottom padding of this view. If there are inset and enabled
21002     * scrollbars, this value may include the space required to display the
21003     * scrollbars as well.
21004     *
21005     * @return the bottom padding in pixels
21006     */
21007    public int getPaddingBottom() {
21008        return mPaddingBottom;
21009    }
21010
21011    /**
21012     * Returns the left padding of this view. If there are inset and enabled
21013     * scrollbars, this value may include the space required to display the
21014     * scrollbars as well.
21015     *
21016     * @return the left padding in pixels
21017     */
21018    public int getPaddingLeft() {
21019        if (!isPaddingResolved()) {
21020            resolvePadding();
21021        }
21022        return mPaddingLeft;
21023    }
21024
21025    /**
21026     * Returns the start padding of this view depending on its resolved layout direction.
21027     * If there are inset and enabled scrollbars, this value may include the space
21028     * required to display the scrollbars as well.
21029     *
21030     * @return the start padding in pixels
21031     */
21032    public int getPaddingStart() {
21033        if (!isPaddingResolved()) {
21034            resolvePadding();
21035        }
21036        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21037                mPaddingRight : mPaddingLeft;
21038    }
21039
21040    /**
21041     * Returns the right padding of this view. If there are inset and enabled
21042     * scrollbars, this value may include the space required to display the
21043     * scrollbars as well.
21044     *
21045     * @return the right padding in pixels
21046     */
21047    public int getPaddingRight() {
21048        if (!isPaddingResolved()) {
21049            resolvePadding();
21050        }
21051        return mPaddingRight;
21052    }
21053
21054    /**
21055     * Returns the end padding of this view depending on its resolved layout direction.
21056     * If there are inset and enabled scrollbars, this value may include the space
21057     * required to display the scrollbars as well.
21058     *
21059     * @return the end padding in pixels
21060     */
21061    public int getPaddingEnd() {
21062        if (!isPaddingResolved()) {
21063            resolvePadding();
21064        }
21065        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21066                mPaddingLeft : mPaddingRight;
21067    }
21068
21069    /**
21070     * Return if the padding has been set through relative values
21071     * {@link #setPaddingRelative(int, int, int, int)} or through
21072     * @attr ref android.R.styleable#View_paddingStart or
21073     * @attr ref android.R.styleable#View_paddingEnd
21074     *
21075     * @return true if the padding is relative or false if it is not.
21076     */
21077    public boolean isPaddingRelative() {
21078        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
21079    }
21080
21081    Insets computeOpticalInsets() {
21082        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
21083    }
21084
21085    /**
21086     * @hide
21087     */
21088    public void resetPaddingToInitialValues() {
21089        if (isRtlCompatibilityMode()) {
21090            mPaddingLeft = mUserPaddingLeftInitial;
21091            mPaddingRight = mUserPaddingRightInitial;
21092            return;
21093        }
21094        if (isLayoutRtl()) {
21095            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
21096            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
21097        } else {
21098            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
21099            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
21100        }
21101    }
21102
21103    /**
21104     * @hide
21105     */
21106    public Insets getOpticalInsets() {
21107        if (mLayoutInsets == null) {
21108            mLayoutInsets = computeOpticalInsets();
21109        }
21110        return mLayoutInsets;
21111    }
21112
21113    /**
21114     * Set this view's optical insets.
21115     *
21116     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
21117     * property. Views that compute their own optical insets should call it as part of measurement.
21118     * This method does not request layout. If you are setting optical insets outside of
21119     * measure/layout itself you will want to call requestLayout() yourself.
21120     * </p>
21121     * @hide
21122     */
21123    public void setOpticalInsets(Insets insets) {
21124        mLayoutInsets = insets;
21125    }
21126
21127    /**
21128     * Changes the selection state of this view. A view can be selected or not.
21129     * Note that selection is not the same as focus. Views are typically
21130     * selected in the context of an AdapterView like ListView or GridView;
21131     * the selected view is the view that is highlighted.
21132     *
21133     * @param selected true if the view must be selected, false otherwise
21134     */
21135    public void setSelected(boolean selected) {
21136        //noinspection DoubleNegation
21137        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
21138            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
21139            if (!selected) resetPressedState();
21140            invalidate(true);
21141            refreshDrawableState();
21142            dispatchSetSelected(selected);
21143            if (selected) {
21144                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
21145            } else {
21146                notifyViewAccessibilityStateChangedIfNeeded(
21147                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
21148            }
21149        }
21150    }
21151
21152    /**
21153     * Dispatch setSelected to all of this View's children.
21154     *
21155     * @see #setSelected(boolean)
21156     *
21157     * @param selected The new selected state
21158     */
21159    protected void dispatchSetSelected(boolean selected) {
21160    }
21161
21162    /**
21163     * Indicates the selection state of this view.
21164     *
21165     * @return true if the view is selected, false otherwise
21166     */
21167    @ViewDebug.ExportedProperty
21168    public boolean isSelected() {
21169        return (mPrivateFlags & PFLAG_SELECTED) != 0;
21170    }
21171
21172    /**
21173     * Changes the activated state of this view. A view can be activated or not.
21174     * Note that activation is not the same as selection.  Selection is
21175     * a transient property, representing the view (hierarchy) the user is
21176     * currently interacting with.  Activation is a longer-term state that the
21177     * user can move views in and out of.  For example, in a list view with
21178     * single or multiple selection enabled, the views in the current selection
21179     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
21180     * here.)  The activated state is propagated down to children of the view it
21181     * is set on.
21182     *
21183     * @param activated true if the view must be activated, false otherwise
21184     */
21185    public void setActivated(boolean activated) {
21186        //noinspection DoubleNegation
21187        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
21188            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
21189            invalidate(true);
21190            refreshDrawableState();
21191            dispatchSetActivated(activated);
21192        }
21193    }
21194
21195    /**
21196     * Dispatch setActivated to all of this View's children.
21197     *
21198     * @see #setActivated(boolean)
21199     *
21200     * @param activated The new activated state
21201     */
21202    protected void dispatchSetActivated(boolean activated) {
21203    }
21204
21205    /**
21206     * Indicates the activation state of this view.
21207     *
21208     * @return true if the view is activated, false otherwise
21209     */
21210    @ViewDebug.ExportedProperty
21211    public boolean isActivated() {
21212        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
21213    }
21214
21215    /**
21216     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
21217     * observer can be used to get notifications when global events, like
21218     * layout, happen.
21219     *
21220     * The returned ViewTreeObserver observer is not guaranteed to remain
21221     * valid for the lifetime of this View. If the caller of this method keeps
21222     * a long-lived reference to ViewTreeObserver, it should always check for
21223     * the return value of {@link ViewTreeObserver#isAlive()}.
21224     *
21225     * @return The ViewTreeObserver for this view's hierarchy.
21226     */
21227    public ViewTreeObserver getViewTreeObserver() {
21228        if (mAttachInfo != null) {
21229            return mAttachInfo.mTreeObserver;
21230        }
21231        if (mFloatingTreeObserver == null) {
21232            mFloatingTreeObserver = new ViewTreeObserver(mContext);
21233        }
21234        return mFloatingTreeObserver;
21235    }
21236
21237    /**
21238     * <p>Finds the topmost view in the current view hierarchy.</p>
21239     *
21240     * @return the topmost view containing this view
21241     */
21242    public View getRootView() {
21243        if (mAttachInfo != null) {
21244            final View v = mAttachInfo.mRootView;
21245            if (v != null) {
21246                return v;
21247            }
21248        }
21249
21250        View parent = this;
21251
21252        while (parent.mParent != null && parent.mParent instanceof View) {
21253            parent = (View) parent.mParent;
21254        }
21255
21256        return parent;
21257    }
21258
21259    /**
21260     * Transforms a motion event from view-local coordinates to on-screen
21261     * coordinates.
21262     *
21263     * @param ev the view-local motion event
21264     * @return false if the transformation could not be applied
21265     * @hide
21266     */
21267    public boolean toGlobalMotionEvent(MotionEvent ev) {
21268        final AttachInfo info = mAttachInfo;
21269        if (info == null) {
21270            return false;
21271        }
21272
21273        final Matrix m = info.mTmpMatrix;
21274        m.set(Matrix.IDENTITY_MATRIX);
21275        transformMatrixToGlobal(m);
21276        ev.transform(m);
21277        return true;
21278    }
21279
21280    /**
21281     * Transforms a motion event from on-screen coordinates to view-local
21282     * coordinates.
21283     *
21284     * @param ev the on-screen motion event
21285     * @return false if the transformation could not be applied
21286     * @hide
21287     */
21288    public boolean toLocalMotionEvent(MotionEvent ev) {
21289        final AttachInfo info = mAttachInfo;
21290        if (info == null) {
21291            return false;
21292        }
21293
21294        final Matrix m = info.mTmpMatrix;
21295        m.set(Matrix.IDENTITY_MATRIX);
21296        transformMatrixToLocal(m);
21297        ev.transform(m);
21298        return true;
21299    }
21300
21301    /**
21302     * Modifies the input matrix such that it maps view-local coordinates to
21303     * on-screen coordinates.
21304     *
21305     * @param m input matrix to modify
21306     * @hide
21307     */
21308    public void transformMatrixToGlobal(Matrix m) {
21309        final ViewParent parent = mParent;
21310        if (parent instanceof View) {
21311            final View vp = (View) parent;
21312            vp.transformMatrixToGlobal(m);
21313            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
21314        } else if (parent instanceof ViewRootImpl) {
21315            final ViewRootImpl vr = (ViewRootImpl) parent;
21316            vr.transformMatrixToGlobal(m);
21317            m.preTranslate(0, -vr.mCurScrollY);
21318        }
21319
21320        m.preTranslate(mLeft, mTop);
21321
21322        if (!hasIdentityMatrix()) {
21323            m.preConcat(getMatrix());
21324        }
21325    }
21326
21327    /**
21328     * Modifies the input matrix such that it maps on-screen coordinates to
21329     * view-local coordinates.
21330     *
21331     * @param m input matrix to modify
21332     * @hide
21333     */
21334    public void transformMatrixToLocal(Matrix m) {
21335        final ViewParent parent = mParent;
21336        if (parent instanceof View) {
21337            final View vp = (View) parent;
21338            vp.transformMatrixToLocal(m);
21339            m.postTranslate(vp.mScrollX, vp.mScrollY);
21340        } else if (parent instanceof ViewRootImpl) {
21341            final ViewRootImpl vr = (ViewRootImpl) parent;
21342            vr.transformMatrixToLocal(m);
21343            m.postTranslate(0, vr.mCurScrollY);
21344        }
21345
21346        m.postTranslate(-mLeft, -mTop);
21347
21348        if (!hasIdentityMatrix()) {
21349            m.postConcat(getInverseMatrix());
21350        }
21351    }
21352
21353    /**
21354     * @hide
21355     */
21356    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
21357            @ViewDebug.IntToString(from = 0, to = "x"),
21358            @ViewDebug.IntToString(from = 1, to = "y")
21359    })
21360    public int[] getLocationOnScreen() {
21361        int[] location = new int[2];
21362        getLocationOnScreen(location);
21363        return location;
21364    }
21365
21366    /**
21367     * <p>Computes the coordinates of this view on the screen. The argument
21368     * must be an array of two integers. After the method returns, the array
21369     * contains the x and y location in that order.</p>
21370     *
21371     * @param outLocation an array of two integers in which to hold the coordinates
21372     */
21373    public void getLocationOnScreen(@Size(2) int[] outLocation) {
21374        getLocationInWindow(outLocation);
21375
21376        final AttachInfo info = mAttachInfo;
21377        if (info != null) {
21378            outLocation[0] += info.mWindowLeft;
21379            outLocation[1] += info.mWindowTop;
21380        }
21381    }
21382
21383    /**
21384     * <p>Computes the coordinates of this view in its window. The argument
21385     * must be an array of two integers. After the method returns, the array
21386     * contains the x and y location in that order.</p>
21387     *
21388     * @param outLocation an array of two integers in which to hold the coordinates
21389     */
21390    public void getLocationInWindow(@Size(2) int[] outLocation) {
21391        if (outLocation == null || outLocation.length < 2) {
21392            throw new IllegalArgumentException("outLocation must be an array of two integers");
21393        }
21394
21395        outLocation[0] = 0;
21396        outLocation[1] = 0;
21397
21398        transformFromViewToWindowSpace(outLocation);
21399    }
21400
21401    /** @hide */
21402    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21403        if (inOutLocation == null || inOutLocation.length < 2) {
21404            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21405        }
21406
21407        if (mAttachInfo == null) {
21408            // When the view is not attached to a window, this method does not make sense
21409            inOutLocation[0] = inOutLocation[1] = 0;
21410            return;
21411        }
21412
21413        float position[] = mAttachInfo.mTmpTransformLocation;
21414        position[0] = inOutLocation[0];
21415        position[1] = inOutLocation[1];
21416
21417        if (!hasIdentityMatrix()) {
21418            getMatrix().mapPoints(position);
21419        }
21420
21421        position[0] += mLeft;
21422        position[1] += mTop;
21423
21424        ViewParent viewParent = mParent;
21425        while (viewParent instanceof View) {
21426            final View view = (View) viewParent;
21427
21428            position[0] -= view.mScrollX;
21429            position[1] -= view.mScrollY;
21430
21431            if (!view.hasIdentityMatrix()) {
21432                view.getMatrix().mapPoints(position);
21433            }
21434
21435            position[0] += view.mLeft;
21436            position[1] += view.mTop;
21437
21438            viewParent = view.mParent;
21439         }
21440
21441        if (viewParent instanceof ViewRootImpl) {
21442            // *cough*
21443            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21444            position[1] -= vr.mCurScrollY;
21445        }
21446
21447        inOutLocation[0] = Math.round(position[0]);
21448        inOutLocation[1] = Math.round(position[1]);
21449    }
21450
21451    /**
21452     * @param id the id of the view to be found
21453     * @return the view of the specified id, null if cannot be found
21454     * @hide
21455     */
21456    protected <T extends View> T findViewTraversal(@IdRes int id) {
21457        if (id == mID) {
21458            return (T) this;
21459        }
21460        return null;
21461    }
21462
21463    /**
21464     * @param tag the tag of the view to be found
21465     * @return the view of specified tag, null if cannot be found
21466     * @hide
21467     */
21468    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21469        if (tag != null && tag.equals(mTag)) {
21470            return (T) this;
21471        }
21472        return null;
21473    }
21474
21475    /**
21476     * @param predicate The predicate to evaluate.
21477     * @param childToSkip If not null, ignores this child during the recursive traversal.
21478     * @return The first view that matches the predicate or null.
21479     * @hide
21480     */
21481    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21482            View childToSkip) {
21483        if (predicate.test(this)) {
21484            return (T) this;
21485        }
21486        return null;
21487    }
21488
21489    /**
21490     * Finds the first descendant view with the given ID, the view itself if
21491     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21492     * (< 0) or there is no matching view in the hierarchy.
21493     * <p>
21494     * <strong>Note:</strong> In most cases -- depending on compiler support --
21495     * the resulting view is automatically cast to the target class type. If
21496     * the target class type is unconstrained, an explicit cast may be
21497     * necessary.
21498     *
21499     * @param id the ID to search for
21500     * @return a view with given ID if found, or {@code null} otherwise
21501     * @see View#findViewById(int)
21502     */
21503    @Nullable
21504    public final <T extends View> T findViewById(@IdRes int id) {
21505        if (id == NO_ID) {
21506            return null;
21507        }
21508        return findViewTraversal(id);
21509    }
21510
21511    /**
21512     * Finds a view by its unuque and stable accessibility id.
21513     *
21514     * @param accessibilityId The searched accessibility id.
21515     * @return The found view.
21516     */
21517    final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
21518        if (accessibilityId < 0) {
21519            return null;
21520        }
21521        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21522        if (view != null) {
21523            return view.includeForAccessibility() ? view : null;
21524        }
21525        return null;
21526    }
21527
21528    /**
21529     * Performs the traversal to find a view by its unique and stable accessibility id.
21530     *
21531     * <strong>Note:</strong>This method does not stop at the root namespace
21532     * boundary since the user can touch the screen at an arbitrary location
21533     * potentially crossing the root namespace boundary which will send an
21534     * accessibility event to accessibility services and they should be able
21535     * to obtain the event source. Also accessibility ids are guaranteed to be
21536     * unique in the window.
21537     *
21538     * @param accessibilityId The accessibility id.
21539     * @return The found view.
21540     * @hide
21541     */
21542    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21543        if (getAccessibilityViewId() == accessibilityId) {
21544            return (T) this;
21545        }
21546        return null;
21547    }
21548
21549    /**
21550     * Performs the traversal to find a view by its autofill id.
21551     *
21552     * <strong>Note:</strong>This method does not stop at the root namespace
21553     * boundary.
21554     *
21555     * @param autofillId The autofill id.
21556     * @return The found view.
21557     * @hide
21558     */
21559    public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
21560        if (getAutofillViewId() == autofillId) {
21561            return (T) this;
21562        }
21563        return null;
21564    }
21565
21566    /**
21567     * Look for a child view with the given tag.  If this view has the given
21568     * tag, return this view.
21569     *
21570     * @param tag The tag to search for, using "tag.equals(getTag())".
21571     * @return The View that has the given tag in the hierarchy or null
21572     */
21573    public final <T extends View> T findViewWithTag(Object tag) {
21574        if (tag == null) {
21575            return null;
21576        }
21577        return findViewWithTagTraversal(tag);
21578    }
21579
21580    /**
21581     * Look for a child view that matches the specified predicate.
21582     * If this view matches the predicate, return this view.
21583     *
21584     * @param predicate The predicate to evaluate.
21585     * @return The first view that matches the predicate or null.
21586     * @hide
21587     */
21588    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21589        return findViewByPredicateTraversal(predicate, null);
21590    }
21591
21592    /**
21593     * Look for a child view that matches the specified predicate,
21594     * starting with the specified view and its descendents and then
21595     * recusively searching the ancestors and siblings of that view
21596     * until this view is reached.
21597     *
21598     * This method is useful in cases where the predicate does not match
21599     * a single unique view (perhaps multiple views use the same id)
21600     * and we are trying to find the view that is "closest" in scope to the
21601     * starting view.
21602     *
21603     * @param start The view to start from.
21604     * @param predicate The predicate to evaluate.
21605     * @return The first view that matches the predicate or null.
21606     * @hide
21607     */
21608    public final <T extends View> T findViewByPredicateInsideOut(
21609            View start, Predicate<View> predicate) {
21610        View childToSkip = null;
21611        for (;;) {
21612            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21613            if (view != null || start == this) {
21614                return view;
21615            }
21616
21617            ViewParent parent = start.getParent();
21618            if (parent == null || !(parent instanceof View)) {
21619                return null;
21620            }
21621
21622            childToSkip = start;
21623            start = (View) parent;
21624        }
21625    }
21626
21627    /**
21628     * Sets the identifier for this view. The identifier does not have to be
21629     * unique in this view's hierarchy. The identifier should be a positive
21630     * number.
21631     *
21632     * @see #NO_ID
21633     * @see #getId()
21634     * @see #findViewById(int)
21635     *
21636     * @param id a number used to identify the view
21637     *
21638     * @attr ref android.R.styleable#View_id
21639     */
21640    public void setId(@IdRes int id) {
21641        mID = id;
21642        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21643            mID = generateViewId();
21644        }
21645    }
21646
21647    /**
21648     * {@hide}
21649     *
21650     * @param isRoot true if the view belongs to the root namespace, false
21651     *        otherwise
21652     */
21653    public void setIsRootNamespace(boolean isRoot) {
21654        if (isRoot) {
21655            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21656        } else {
21657            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21658        }
21659    }
21660
21661    /**
21662     * {@hide}
21663     *
21664     * @return true if the view belongs to the root namespace, false otherwise
21665     */
21666    public boolean isRootNamespace() {
21667        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21668    }
21669
21670    /**
21671     * Returns this view's identifier.
21672     *
21673     * @return a positive integer used to identify the view or {@link #NO_ID}
21674     *         if the view has no ID
21675     *
21676     * @see #setId(int)
21677     * @see #findViewById(int)
21678     * @attr ref android.R.styleable#View_id
21679     */
21680    @IdRes
21681    @ViewDebug.CapturedViewProperty
21682    public int getId() {
21683        return mID;
21684    }
21685
21686    /**
21687     * Returns this view's tag.
21688     *
21689     * @return the Object stored in this view as a tag, or {@code null} if not
21690     *         set
21691     *
21692     * @see #setTag(Object)
21693     * @see #getTag(int)
21694     */
21695    @ViewDebug.ExportedProperty
21696    public Object getTag() {
21697        return mTag;
21698    }
21699
21700    /**
21701     * Sets the tag associated with this view. A tag can be used to mark
21702     * a view in its hierarchy and does not have to be unique within the
21703     * hierarchy. Tags can also be used to store data within a view without
21704     * resorting to another data structure.
21705     *
21706     * @param tag an Object to tag the view with
21707     *
21708     * @see #getTag()
21709     * @see #setTag(int, Object)
21710     */
21711    public void setTag(final Object tag) {
21712        mTag = tag;
21713    }
21714
21715    /**
21716     * Returns the tag associated with this view and the specified key.
21717     *
21718     * @param key The key identifying the tag
21719     *
21720     * @return the Object stored in this view as a tag, or {@code null} if not
21721     *         set
21722     *
21723     * @see #setTag(int, Object)
21724     * @see #getTag()
21725     */
21726    public Object getTag(int key) {
21727        if (mKeyedTags != null) return mKeyedTags.get(key);
21728        return null;
21729    }
21730
21731    /**
21732     * Sets a tag associated with this view and a key. A tag can be used
21733     * to mark a view in its hierarchy and does not have to be unique within
21734     * the hierarchy. Tags can also be used to store data within a view
21735     * without resorting to another data structure.
21736     *
21737     * The specified key should be an id declared in the resources of the
21738     * application to ensure it is unique (see the <a
21739     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21740     * Keys identified as belonging to
21741     * the Android framework or not associated with any package will cause
21742     * an {@link IllegalArgumentException} to be thrown.
21743     *
21744     * @param key The key identifying the tag
21745     * @param tag An Object to tag the view with
21746     *
21747     * @throws IllegalArgumentException If they specified key is not valid
21748     *
21749     * @see #setTag(Object)
21750     * @see #getTag(int)
21751     */
21752    public void setTag(int key, final Object tag) {
21753        // If the package id is 0x00 or 0x01, it's either an undefined package
21754        // or a framework id
21755        if ((key >>> 24) < 2) {
21756            throw new IllegalArgumentException("The key must be an application-specific "
21757                    + "resource id.");
21758        }
21759
21760        setKeyedTag(key, tag);
21761    }
21762
21763    /**
21764     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21765     * framework id.
21766     *
21767     * @hide
21768     */
21769    public void setTagInternal(int key, Object tag) {
21770        if ((key >>> 24) != 0x1) {
21771            throw new IllegalArgumentException("The key must be a framework-specific "
21772                    + "resource id.");
21773        }
21774
21775        setKeyedTag(key, tag);
21776    }
21777
21778    private void setKeyedTag(int key, Object tag) {
21779        if (mKeyedTags == null) {
21780            mKeyedTags = new SparseArray<Object>(2);
21781        }
21782
21783        mKeyedTags.put(key, tag);
21784    }
21785
21786    /**
21787     * Prints information about this view in the log output, with the tag
21788     * {@link #VIEW_LOG_TAG}.
21789     *
21790     * @hide
21791     */
21792    public void debug() {
21793        debug(0);
21794    }
21795
21796    /**
21797     * Prints information about this view in the log output, with the tag
21798     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21799     * indentation defined by the <code>depth</code>.
21800     *
21801     * @param depth the indentation level
21802     *
21803     * @hide
21804     */
21805    protected void debug(int depth) {
21806        String output = debugIndent(depth - 1);
21807
21808        output += "+ " + this;
21809        int id = getId();
21810        if (id != -1) {
21811            output += " (id=" + id + ")";
21812        }
21813        Object tag = getTag();
21814        if (tag != null) {
21815            output += " (tag=" + tag + ")";
21816        }
21817        Log.d(VIEW_LOG_TAG, output);
21818
21819        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21820            output = debugIndent(depth) + " FOCUSED";
21821            Log.d(VIEW_LOG_TAG, output);
21822        }
21823
21824        output = debugIndent(depth);
21825        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21826                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21827                + "} ";
21828        Log.d(VIEW_LOG_TAG, output);
21829
21830        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21831                || mPaddingBottom != 0) {
21832            output = debugIndent(depth);
21833            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21834                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21835            Log.d(VIEW_LOG_TAG, output);
21836        }
21837
21838        output = debugIndent(depth);
21839        output += "mMeasureWidth=" + mMeasuredWidth +
21840                " mMeasureHeight=" + mMeasuredHeight;
21841        Log.d(VIEW_LOG_TAG, output);
21842
21843        output = debugIndent(depth);
21844        if (mLayoutParams == null) {
21845            output += "BAD! no layout params";
21846        } else {
21847            output = mLayoutParams.debug(output);
21848        }
21849        Log.d(VIEW_LOG_TAG, output);
21850
21851        output = debugIndent(depth);
21852        output += "flags={";
21853        output += View.printFlags(mViewFlags);
21854        output += "}";
21855        Log.d(VIEW_LOG_TAG, output);
21856
21857        output = debugIndent(depth);
21858        output += "privateFlags={";
21859        output += View.printPrivateFlags(mPrivateFlags);
21860        output += "}";
21861        Log.d(VIEW_LOG_TAG, output);
21862    }
21863
21864    /**
21865     * Creates a string of whitespaces used for indentation.
21866     *
21867     * @param depth the indentation level
21868     * @return a String containing (depth * 2 + 3) * 2 white spaces
21869     *
21870     * @hide
21871     */
21872    protected static String debugIndent(int depth) {
21873        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21874        for (int i = 0; i < (depth * 2) + 3; i++) {
21875            spaces.append(' ').append(' ');
21876        }
21877        return spaces.toString();
21878    }
21879
21880    /**
21881     * <p>Return the offset of the widget's text baseline from the widget's top
21882     * boundary. If this widget does not support baseline alignment, this
21883     * method returns -1. </p>
21884     *
21885     * @return the offset of the baseline within the widget's bounds or -1
21886     *         if baseline alignment is not supported
21887     */
21888    @ViewDebug.ExportedProperty(category = "layout")
21889    public int getBaseline() {
21890        return -1;
21891    }
21892
21893    /**
21894     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21895     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21896     * a layout pass.
21897     *
21898     * @return whether the view hierarchy is currently undergoing a layout pass
21899     */
21900    public boolean isInLayout() {
21901        ViewRootImpl viewRoot = getViewRootImpl();
21902        return (viewRoot != null && viewRoot.isInLayout());
21903    }
21904
21905    /**
21906     * Call this when something has changed which has invalidated the
21907     * layout of this view. This will schedule a layout pass of the view
21908     * tree. This should not be called while the view hierarchy is currently in a layout
21909     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21910     * end of the current layout pass (and then layout will run again) or after the current
21911     * frame is drawn and the next layout occurs.
21912     *
21913     * <p>Subclasses which override this method should call the superclass method to
21914     * handle possible request-during-layout errors correctly.</p>
21915     */
21916    @CallSuper
21917    public void requestLayout() {
21918        if (mMeasureCache != null) mMeasureCache.clear();
21919
21920        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21921            // Only trigger request-during-layout logic if this is the view requesting it,
21922            // not the views in its parent hierarchy
21923            ViewRootImpl viewRoot = getViewRootImpl();
21924            if (viewRoot != null && viewRoot.isInLayout()) {
21925                if (!viewRoot.requestLayoutDuringLayout(this)) {
21926                    return;
21927                }
21928            }
21929            mAttachInfo.mViewRequestingLayout = this;
21930        }
21931
21932        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21933        mPrivateFlags |= PFLAG_INVALIDATED;
21934
21935        if (mParent != null && !mParent.isLayoutRequested()) {
21936            mParent.requestLayout();
21937        }
21938        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21939            mAttachInfo.mViewRequestingLayout = null;
21940        }
21941    }
21942
21943    /**
21944     * Forces this view to be laid out during the next layout pass.
21945     * This method does not call requestLayout() or forceLayout()
21946     * on the parent.
21947     */
21948    public void forceLayout() {
21949        if (mMeasureCache != null) mMeasureCache.clear();
21950
21951        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21952        mPrivateFlags |= PFLAG_INVALIDATED;
21953    }
21954
21955    /**
21956     * <p>
21957     * This is called to find out how big a view should be. The parent
21958     * supplies constraint information in the width and height parameters.
21959     * </p>
21960     *
21961     * <p>
21962     * The actual measurement work of a view is performed in
21963     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21964     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21965     * </p>
21966     *
21967     *
21968     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21969     *        parent
21970     * @param heightMeasureSpec Vertical space requirements as imposed by the
21971     *        parent
21972     *
21973     * @see #onMeasure(int, int)
21974     */
21975    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21976        boolean optical = isLayoutModeOptical(this);
21977        if (optical != isLayoutModeOptical(mParent)) {
21978            Insets insets = getOpticalInsets();
21979            int oWidth  = insets.left + insets.right;
21980            int oHeight = insets.top  + insets.bottom;
21981            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21982            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21983        }
21984
21985        // Suppress sign extension for the low bytes
21986        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21987        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21988
21989        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21990
21991        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21992        // already measured as the correct size. In API 23 and below, this
21993        // extra pass is required to make LinearLayout re-distribute weight.
21994        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21995                || heightMeasureSpec != mOldHeightMeasureSpec;
21996        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21997                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21998        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21999                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
22000        final boolean needsLayout = specChanged
22001                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
22002
22003        if (forceLayout || needsLayout) {
22004            // first clears the measured dimension flag
22005            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
22006
22007            resolveRtlPropertiesIfNeeded();
22008
22009            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
22010            if (cacheIndex < 0 || sIgnoreMeasureCache) {
22011                // measure ourselves, this should set the measured dimension flag back
22012                onMeasure(widthMeasureSpec, heightMeasureSpec);
22013                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22014            } else {
22015                long value = mMeasureCache.valueAt(cacheIndex);
22016                // Casting a long to int drops the high 32 bits, no mask needed
22017                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
22018                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22019            }
22020
22021            // flag not set, setMeasuredDimension() was not invoked, we raise
22022            // an exception to warn the developer
22023            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
22024                throw new IllegalStateException("View with id " + getId() + ": "
22025                        + getClass().getName() + "#onMeasure() did not set the"
22026                        + " measured dimension by calling"
22027                        + " setMeasuredDimension()");
22028            }
22029
22030            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
22031        }
22032
22033        mOldWidthMeasureSpec = widthMeasureSpec;
22034        mOldHeightMeasureSpec = heightMeasureSpec;
22035
22036        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
22037                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
22038    }
22039
22040    /**
22041     * <p>
22042     * Measure the view and its content to determine the measured width and the
22043     * measured height. This method is invoked by {@link #measure(int, int)} and
22044     * should be overridden by subclasses to provide accurate and efficient
22045     * measurement of their contents.
22046     * </p>
22047     *
22048     * <p>
22049     * <strong>CONTRACT:</strong> When overriding this method, you
22050     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
22051     * measured width and height of this view. Failure to do so will trigger an
22052     * <code>IllegalStateException</code>, thrown by
22053     * {@link #measure(int, int)}. Calling the superclass'
22054     * {@link #onMeasure(int, int)} is a valid use.
22055     * </p>
22056     *
22057     * <p>
22058     * The base class implementation of measure defaults to the background size,
22059     * unless a larger size is allowed by the MeasureSpec. Subclasses should
22060     * override {@link #onMeasure(int, int)} to provide better measurements of
22061     * their content.
22062     * </p>
22063     *
22064     * <p>
22065     * If this method is overridden, it is the subclass's responsibility to make
22066     * sure the measured height and width are at least the view's minimum height
22067     * and width ({@link #getSuggestedMinimumHeight()} and
22068     * {@link #getSuggestedMinimumWidth()}).
22069     * </p>
22070     *
22071     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
22072     *                         The requirements are encoded with
22073     *                         {@link android.view.View.MeasureSpec}.
22074     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
22075     *                         The requirements are encoded with
22076     *                         {@link android.view.View.MeasureSpec}.
22077     *
22078     * @see #getMeasuredWidth()
22079     * @see #getMeasuredHeight()
22080     * @see #setMeasuredDimension(int, int)
22081     * @see #getSuggestedMinimumHeight()
22082     * @see #getSuggestedMinimumWidth()
22083     * @see android.view.View.MeasureSpec#getMode(int)
22084     * @see android.view.View.MeasureSpec#getSize(int)
22085     */
22086    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22087        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
22088                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
22089    }
22090
22091    /**
22092     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
22093     * measured width and measured height. Failing to do so will trigger an
22094     * exception at measurement time.</p>
22095     *
22096     * @param measuredWidth The measured width of this view.  May be a complex
22097     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22098     * {@link #MEASURED_STATE_TOO_SMALL}.
22099     * @param measuredHeight The measured height of this view.  May be a complex
22100     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22101     * {@link #MEASURED_STATE_TOO_SMALL}.
22102     */
22103    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
22104        boolean optical = isLayoutModeOptical(this);
22105        if (optical != isLayoutModeOptical(mParent)) {
22106            Insets insets = getOpticalInsets();
22107            int opticalWidth  = insets.left + insets.right;
22108            int opticalHeight = insets.top  + insets.bottom;
22109
22110            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
22111            measuredHeight += optical ? opticalHeight : -opticalHeight;
22112        }
22113        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
22114    }
22115
22116    /**
22117     * Sets the measured dimension without extra processing for things like optical bounds.
22118     * Useful for reapplying consistent values that have already been cooked with adjustments
22119     * for optical bounds, etc. such as those from the measurement cache.
22120     *
22121     * @param measuredWidth The measured width of this view.  May be a complex
22122     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22123     * {@link #MEASURED_STATE_TOO_SMALL}.
22124     * @param measuredHeight The measured height of this view.  May be a complex
22125     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22126     * {@link #MEASURED_STATE_TOO_SMALL}.
22127     */
22128    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
22129        mMeasuredWidth = measuredWidth;
22130        mMeasuredHeight = measuredHeight;
22131
22132        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
22133    }
22134
22135    /**
22136     * Merge two states as returned by {@link #getMeasuredState()}.
22137     * @param curState The current state as returned from a view or the result
22138     * of combining multiple views.
22139     * @param newState The new view state to combine.
22140     * @return Returns a new integer reflecting the combination of the two
22141     * states.
22142     */
22143    public static int combineMeasuredStates(int curState, int newState) {
22144        return curState | newState;
22145    }
22146
22147    /**
22148     * Version of {@link #resolveSizeAndState(int, int, int)}
22149     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
22150     */
22151    public static int resolveSize(int size, int measureSpec) {
22152        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
22153    }
22154
22155    /**
22156     * Utility to reconcile a desired size and state, with constraints imposed
22157     * by a MeasureSpec. Will take the desired size, unless a different size
22158     * is imposed by the constraints. The returned value is a compound integer,
22159     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
22160     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
22161     * resulting size is smaller than the size the view wants to be.
22162     *
22163     * @param size How big the view wants to be.
22164     * @param measureSpec Constraints imposed by the parent.
22165     * @param childMeasuredState Size information bit mask for the view's
22166     *                           children.
22167     * @return Size information bit mask as defined by
22168     *         {@link #MEASURED_SIZE_MASK} and
22169     *         {@link #MEASURED_STATE_TOO_SMALL}.
22170     */
22171    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
22172        final int specMode = MeasureSpec.getMode(measureSpec);
22173        final int specSize = MeasureSpec.getSize(measureSpec);
22174        final int result;
22175        switch (specMode) {
22176            case MeasureSpec.AT_MOST:
22177                if (specSize < size) {
22178                    result = specSize | MEASURED_STATE_TOO_SMALL;
22179                } else {
22180                    result = size;
22181                }
22182                break;
22183            case MeasureSpec.EXACTLY:
22184                result = specSize;
22185                break;
22186            case MeasureSpec.UNSPECIFIED:
22187            default:
22188                result = size;
22189        }
22190        return result | (childMeasuredState & MEASURED_STATE_MASK);
22191    }
22192
22193    /**
22194     * Utility to return a default size. Uses the supplied size if the
22195     * MeasureSpec imposed no constraints. Will get larger if allowed
22196     * by the MeasureSpec.
22197     *
22198     * @param size Default size for this view
22199     * @param measureSpec Constraints imposed by the parent
22200     * @return The size this view should be.
22201     */
22202    public static int getDefaultSize(int size, int measureSpec) {
22203        int result = size;
22204        int specMode = MeasureSpec.getMode(measureSpec);
22205        int specSize = MeasureSpec.getSize(measureSpec);
22206
22207        switch (specMode) {
22208        case MeasureSpec.UNSPECIFIED:
22209            result = size;
22210            break;
22211        case MeasureSpec.AT_MOST:
22212        case MeasureSpec.EXACTLY:
22213            result = specSize;
22214            break;
22215        }
22216        return result;
22217    }
22218
22219    /**
22220     * Returns the suggested minimum height that the view should use. This
22221     * returns the maximum of the view's minimum height
22222     * and the background's minimum height
22223     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
22224     * <p>
22225     * When being used in {@link #onMeasure(int, int)}, the caller should still
22226     * ensure the returned height is within the requirements of the parent.
22227     *
22228     * @return The suggested minimum height of the view.
22229     */
22230    protected int getSuggestedMinimumHeight() {
22231        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
22232
22233    }
22234
22235    /**
22236     * Returns the suggested minimum width that the view should use. This
22237     * returns the maximum of the view's minimum width
22238     * and the background's minimum width
22239     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
22240     * <p>
22241     * When being used in {@link #onMeasure(int, int)}, the caller should still
22242     * ensure the returned width is within the requirements of the parent.
22243     *
22244     * @return The suggested minimum width of the view.
22245     */
22246    protected int getSuggestedMinimumWidth() {
22247        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
22248    }
22249
22250    /**
22251     * Returns the minimum height of the view.
22252     *
22253     * @return the minimum height the view will try to be, in pixels
22254     *
22255     * @see #setMinimumHeight(int)
22256     *
22257     * @attr ref android.R.styleable#View_minHeight
22258     */
22259    public int getMinimumHeight() {
22260        return mMinHeight;
22261    }
22262
22263    /**
22264     * Sets the minimum height of the view. It is not guaranteed the view will
22265     * be able to achieve this minimum height (for example, if its parent layout
22266     * constrains it with less available height).
22267     *
22268     * @param minHeight The minimum height the view will try to be, in pixels
22269     *
22270     * @see #getMinimumHeight()
22271     *
22272     * @attr ref android.R.styleable#View_minHeight
22273     */
22274    @RemotableViewMethod
22275    public void setMinimumHeight(int minHeight) {
22276        mMinHeight = minHeight;
22277        requestLayout();
22278    }
22279
22280    /**
22281     * Returns the minimum width of the view.
22282     *
22283     * @return the minimum width the view will try to be, in pixels
22284     *
22285     * @see #setMinimumWidth(int)
22286     *
22287     * @attr ref android.R.styleable#View_minWidth
22288     */
22289    public int getMinimumWidth() {
22290        return mMinWidth;
22291    }
22292
22293    /**
22294     * Sets the minimum width of the view. It is not guaranteed the view will
22295     * be able to achieve this minimum width (for example, if its parent layout
22296     * constrains it with less available width).
22297     *
22298     * @param minWidth The minimum width the view will try to be, in pixels
22299     *
22300     * @see #getMinimumWidth()
22301     *
22302     * @attr ref android.R.styleable#View_minWidth
22303     */
22304    public void setMinimumWidth(int minWidth) {
22305        mMinWidth = minWidth;
22306        requestLayout();
22307
22308    }
22309
22310    /**
22311     * Get the animation currently associated with this view.
22312     *
22313     * @return The animation that is currently playing or
22314     *         scheduled to play for this view.
22315     */
22316    public Animation getAnimation() {
22317        return mCurrentAnimation;
22318    }
22319
22320    /**
22321     * Start the specified animation now.
22322     *
22323     * @param animation the animation to start now
22324     */
22325    public void startAnimation(Animation animation) {
22326        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
22327        setAnimation(animation);
22328        invalidateParentCaches();
22329        invalidate(true);
22330    }
22331
22332    /**
22333     * Cancels any animations for this view.
22334     */
22335    public void clearAnimation() {
22336        if (mCurrentAnimation != null) {
22337            mCurrentAnimation.detach();
22338        }
22339        mCurrentAnimation = null;
22340        invalidateParentIfNeeded();
22341    }
22342
22343    /**
22344     * Sets the next animation to play for this view.
22345     * If you want the animation to play immediately, use
22346     * {@link #startAnimation(android.view.animation.Animation)} instead.
22347     * This method provides allows fine-grained
22348     * control over the start time and invalidation, but you
22349     * must make sure that 1) the animation has a start time set, and
22350     * 2) the view's parent (which controls animations on its children)
22351     * will be invalidated when the animation is supposed to
22352     * start.
22353     *
22354     * @param animation The next animation, or null.
22355     */
22356    public void setAnimation(Animation animation) {
22357        mCurrentAnimation = animation;
22358
22359        if (animation != null) {
22360            // If the screen is off assume the animation start time is now instead of
22361            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
22362            // would cause the animation to start when the screen turns back on
22363            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
22364                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
22365                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
22366            }
22367            animation.reset();
22368        }
22369    }
22370
22371    /**
22372     * Invoked by a parent ViewGroup to notify the start of the animation
22373     * currently associated with this view. If you override this method,
22374     * always call super.onAnimationStart();
22375     *
22376     * @see #setAnimation(android.view.animation.Animation)
22377     * @see #getAnimation()
22378     */
22379    @CallSuper
22380    protected void onAnimationStart() {
22381        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22382    }
22383
22384    /**
22385     * Invoked by a parent ViewGroup to notify the end of the animation
22386     * currently associated with this view. If you override this method,
22387     * always call super.onAnimationEnd();
22388     *
22389     * @see #setAnimation(android.view.animation.Animation)
22390     * @see #getAnimation()
22391     */
22392    @CallSuper
22393    protected void onAnimationEnd() {
22394        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22395    }
22396
22397    /**
22398     * Invoked if there is a Transform that involves alpha. Subclass that can
22399     * draw themselves with the specified alpha should return true, and then
22400     * respect that alpha when their onDraw() is called. If this returns false
22401     * then the view may be redirected to draw into an offscreen buffer to
22402     * fulfill the request, which will look fine, but may be slower than if the
22403     * subclass handles it internally. The default implementation returns false.
22404     *
22405     * @param alpha The alpha (0..255) to apply to the view's drawing
22406     * @return true if the view can draw with the specified alpha.
22407     */
22408    protected boolean onSetAlpha(int alpha) {
22409        return false;
22410    }
22411
22412    /**
22413     * This is used by the RootView to perform an optimization when
22414     * the view hierarchy contains one or several SurfaceView.
22415     * SurfaceView is always considered transparent, but its children are not,
22416     * therefore all View objects remove themselves from the global transparent
22417     * region (passed as a parameter to this function).
22418     *
22419     * @param region The transparent region for this ViewAncestor (window).
22420     *
22421     * @return Returns true if the effective visibility of the view at this
22422     * point is opaque, regardless of the transparent region; returns false
22423     * if it is possible for underlying windows to be seen behind the view.
22424     *
22425     * {@hide}
22426     */
22427    public boolean gatherTransparentRegion(Region region) {
22428        final AttachInfo attachInfo = mAttachInfo;
22429        if (region != null && attachInfo != null) {
22430            final int pflags = mPrivateFlags;
22431            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22432                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22433                // remove it from the transparent region.
22434                final int[] location = attachInfo.mTransparentLocation;
22435                getLocationInWindow(location);
22436                // When a view has Z value, then it will be better to leave some area below the view
22437                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22438                // the bottom part needs more offset than the left, top and right parts due to the
22439                // spot light effects.
22440                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22441                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22442                        location[0] + mRight - mLeft + shadowOffset,
22443                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22444            } else {
22445                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22446                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22447                    // the background drawable's non-transparent parts from this transparent region.
22448                    applyDrawableToTransparentRegion(mBackground, region);
22449                }
22450                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22451                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22452                    // Similarly, we remove the foreground drawable's non-transparent parts.
22453                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22454                }
22455                if (mDefaultFocusHighlight != null
22456                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22457                    // Similarly, we remove the default focus highlight's non-transparent parts.
22458                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22459                }
22460            }
22461        }
22462        return true;
22463    }
22464
22465    /**
22466     * Play a sound effect for this view.
22467     *
22468     * <p>The framework will play sound effects for some built in actions, such as
22469     * clicking, but you may wish to play these effects in your widget,
22470     * for instance, for internal navigation.
22471     *
22472     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22473     * {@link #isSoundEffectsEnabled()} is true.
22474     *
22475     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22476     */
22477    public void playSoundEffect(int soundConstant) {
22478        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22479            return;
22480        }
22481        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22482    }
22483
22484    /**
22485     * BZZZTT!!1!
22486     *
22487     * <p>Provide haptic feedback to the user for this view.
22488     *
22489     * <p>The framework will provide haptic feedback for some built in actions,
22490     * such as long presses, but you may wish to provide feedback for your
22491     * own widget.
22492     *
22493     * <p>The feedback will only be performed if
22494     * {@link #isHapticFeedbackEnabled()} is true.
22495     *
22496     * @param feedbackConstant One of the constants defined in
22497     * {@link HapticFeedbackConstants}
22498     */
22499    public boolean performHapticFeedback(int feedbackConstant) {
22500        return performHapticFeedback(feedbackConstant, 0);
22501    }
22502
22503    /**
22504     * BZZZTT!!1!
22505     *
22506     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22507     *
22508     * @param feedbackConstant One of the constants defined in
22509     * {@link HapticFeedbackConstants}
22510     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22511     */
22512    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22513        if (mAttachInfo == null) {
22514            return false;
22515        }
22516        //noinspection SimplifiableIfStatement
22517        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22518                && !isHapticFeedbackEnabled()) {
22519            return false;
22520        }
22521        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22522                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22523    }
22524
22525    /**
22526     * Request that the visibility of the status bar or other screen/window
22527     * decorations be changed.
22528     *
22529     * <p>This method is used to put the over device UI into temporary modes
22530     * where the user's attention is focused more on the application content,
22531     * by dimming or hiding surrounding system affordances.  This is typically
22532     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22533     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22534     * to be placed behind the action bar (and with these flags other system
22535     * affordances) so that smooth transitions between hiding and showing them
22536     * can be done.
22537     *
22538     * <p>Two representative examples of the use of system UI visibility is
22539     * implementing a content browsing application (like a magazine reader)
22540     * and a video playing application.
22541     *
22542     * <p>The first code shows a typical implementation of a View in a content
22543     * browsing application.  In this implementation, the application goes
22544     * into a content-oriented mode by hiding the status bar and action bar,
22545     * and putting the navigation elements into lights out mode.  The user can
22546     * then interact with content while in this mode.  Such an application should
22547     * provide an easy way for the user to toggle out of the mode (such as to
22548     * check information in the status bar or access notifications).  In the
22549     * implementation here, this is done simply by tapping on the content.
22550     *
22551     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22552     *      content}
22553     *
22554     * <p>This second code sample shows a typical implementation of a View
22555     * in a video playing application.  In this situation, while the video is
22556     * playing the application would like to go into a complete full-screen mode,
22557     * to use as much of the display as possible for the video.  When in this state
22558     * the user can not interact with the application; the system intercepts
22559     * touching on the screen to pop the UI out of full screen mode.  See
22560     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22561     *
22562     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22563     *      content}
22564     *
22565     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22566     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22567     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22568     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22569     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22570     */
22571    public void setSystemUiVisibility(int visibility) {
22572        if (visibility != mSystemUiVisibility) {
22573            mSystemUiVisibility = visibility;
22574            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22575                mParent.recomputeViewAttributes(this);
22576            }
22577        }
22578    }
22579
22580    /**
22581     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22582     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22583     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22584     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22585     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22586     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22587     */
22588    public int getSystemUiVisibility() {
22589        return mSystemUiVisibility;
22590    }
22591
22592    /**
22593     * Returns the current system UI visibility that is currently set for
22594     * the entire window.  This is the combination of the
22595     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22596     * views in the window.
22597     */
22598    public int getWindowSystemUiVisibility() {
22599        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22600    }
22601
22602    /**
22603     * Override to find out when the window's requested system UI visibility
22604     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22605     * This is different from the callbacks received through
22606     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22607     * in that this is only telling you about the local request of the window,
22608     * not the actual values applied by the system.
22609     */
22610    public void onWindowSystemUiVisibilityChanged(int visible) {
22611    }
22612
22613    /**
22614     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22615     * the view hierarchy.
22616     */
22617    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22618        onWindowSystemUiVisibilityChanged(visible);
22619    }
22620
22621    /**
22622     * Set a listener to receive callbacks when the visibility of the system bar changes.
22623     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22624     */
22625    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22626        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22627        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22628            mParent.recomputeViewAttributes(this);
22629        }
22630    }
22631
22632    /**
22633     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22634     * the view hierarchy.
22635     */
22636    public void dispatchSystemUiVisibilityChanged(int visibility) {
22637        ListenerInfo li = mListenerInfo;
22638        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22639            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22640                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22641        }
22642    }
22643
22644    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22645        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22646        if (val != mSystemUiVisibility) {
22647            setSystemUiVisibility(val);
22648            return true;
22649        }
22650        return false;
22651    }
22652
22653    /** @hide */
22654    public void setDisabledSystemUiVisibility(int flags) {
22655        if (mAttachInfo != null) {
22656            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22657                mAttachInfo.mDisabledSystemUiVisibility = flags;
22658                if (mParent != null) {
22659                    mParent.recomputeViewAttributes(this);
22660                }
22661            }
22662        }
22663    }
22664
22665    /**
22666     * Creates an image that the system displays during the drag and drop
22667     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22668     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22669     * appearance as the given View. The default also positions the center of the drag shadow
22670     * directly under the touch point. If no View is provided (the constructor with no parameters
22671     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22672     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22673     * default is an invisible drag shadow.
22674     * <p>
22675     * You are not required to use the View you provide to the constructor as the basis of the
22676     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22677     * anything you want as the drag shadow.
22678     * </p>
22679     * <p>
22680     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22681     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22682     *  size and position of the drag shadow. It uses this data to construct a
22683     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22684     *  so that your application can draw the shadow image in the Canvas.
22685     * </p>
22686     *
22687     * <div class="special reference">
22688     * <h3>Developer Guides</h3>
22689     * <p>For a guide to implementing drag and drop features, read the
22690     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22691     * </div>
22692     */
22693    public static class DragShadowBuilder {
22694        private final WeakReference<View> mView;
22695
22696        /**
22697         * Constructs a shadow image builder based on a View. By default, the resulting drag
22698         * shadow will have the same appearance and dimensions as the View, with the touch point
22699         * over the center of the View.
22700         * @param view A View. Any View in scope can be used.
22701         */
22702        public DragShadowBuilder(View view) {
22703            mView = new WeakReference<View>(view);
22704        }
22705
22706        /**
22707         * Construct a shadow builder object with no associated View.  This
22708         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22709         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22710         * to supply the drag shadow's dimensions and appearance without
22711         * reference to any View object. If they are not overridden, then the result is an
22712         * invisible drag shadow.
22713         */
22714        public DragShadowBuilder() {
22715            mView = new WeakReference<View>(null);
22716        }
22717
22718        /**
22719         * Returns the View object that had been passed to the
22720         * {@link #View.DragShadowBuilder(View)}
22721         * constructor.  If that View parameter was {@code null} or if the
22722         * {@link #View.DragShadowBuilder()}
22723         * constructor was used to instantiate the builder object, this method will return
22724         * null.
22725         *
22726         * @return The View object associate with this builder object.
22727         */
22728        @SuppressWarnings({"JavadocReference"})
22729        final public View getView() {
22730            return mView.get();
22731        }
22732
22733        /**
22734         * Provides the metrics for the shadow image. These include the dimensions of
22735         * the shadow image, and the point within that shadow that should
22736         * be centered under the touch location while dragging.
22737         * <p>
22738         * The default implementation sets the dimensions of the shadow to be the
22739         * same as the dimensions of the View itself and centers the shadow under
22740         * the touch point.
22741         * </p>
22742         *
22743         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22744         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22745         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22746         * image.
22747         *
22748         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22749         * shadow image that should be underneath the touch point during the drag and drop
22750         * operation. Your application must set {@link android.graphics.Point#x} to the
22751         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22752         */
22753        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22754            final View view = mView.get();
22755            if (view != null) {
22756                outShadowSize.set(view.getWidth(), view.getHeight());
22757                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22758            } else {
22759                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22760            }
22761        }
22762
22763        /**
22764         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22765         * based on the dimensions it received from the
22766         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22767         *
22768         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22769         */
22770        public void onDrawShadow(Canvas canvas) {
22771            final View view = mView.get();
22772            if (view != null) {
22773                view.draw(canvas);
22774            } else {
22775                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22776            }
22777        }
22778    }
22779
22780    /**
22781     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22782     * startDragAndDrop()} for newer platform versions.
22783     */
22784    @Deprecated
22785    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22786                                   Object myLocalState, int flags) {
22787        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22788    }
22789
22790    /**
22791     * Starts a drag and drop operation. When your application calls this method, it passes a
22792     * {@link android.view.View.DragShadowBuilder} object to the system. The
22793     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22794     * to get metrics for the drag shadow, and then calls the object's
22795     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22796     * <p>
22797     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22798     *  drag events to all the View objects in your application that are currently visible. It does
22799     *  this either by calling the View object's drag listener (an implementation of
22800     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22801     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22802     *  Both are passed a {@link android.view.DragEvent} object that has a
22803     *  {@link android.view.DragEvent#getAction()} value of
22804     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22805     * </p>
22806     * <p>
22807     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22808     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22809     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22810     * to the View the user selected for dragging.
22811     * </p>
22812     * @param data A {@link android.content.ClipData} object pointing to the data to be
22813     * transferred by the drag and drop operation.
22814     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22815     * drag shadow.
22816     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22817     * drop operation. When dispatching drag events to views in the same activity this object
22818     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22819     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22820     * will return null).
22821     * <p>
22822     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22823     * to the target Views. For example, it can contain flags that differentiate between a
22824     * a copy operation and a move operation.
22825     * </p>
22826     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22827     * flags, or any combination of the following:
22828     *     <ul>
22829     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22830     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22831     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22832     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22833     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22834     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22835     *     </ul>
22836     * @return {@code true} if the method completes successfully, or
22837     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22838     * do a drag, and so no drag operation is in progress.
22839     */
22840    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22841            Object myLocalState, int flags) {
22842        if (ViewDebug.DEBUG_DRAG) {
22843            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22844        }
22845        if (mAttachInfo == null) {
22846            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22847            return false;
22848        }
22849
22850        if (data != null) {
22851            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22852        }
22853
22854        boolean okay = false;
22855
22856        Point shadowSize = new Point();
22857        Point shadowTouchPoint = new Point();
22858        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22859
22860        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22861                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22862            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22863        }
22864
22865        if (ViewDebug.DEBUG_DRAG) {
22866            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22867                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22868        }
22869        if (mAttachInfo.mDragSurface != null) {
22870            mAttachInfo.mDragSurface.release();
22871        }
22872        mAttachInfo.mDragSurface = new Surface();
22873        try {
22874            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22875                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22876            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22877                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22878            if (mAttachInfo.mDragToken != null) {
22879                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22880                try {
22881                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22882                    shadowBuilder.onDrawShadow(canvas);
22883                } finally {
22884                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22885                }
22886
22887                final ViewRootImpl root = getViewRootImpl();
22888
22889                // Cache the local state object for delivery with DragEvents
22890                root.setLocalDragState(myLocalState);
22891
22892                // repurpose 'shadowSize' for the last touch point
22893                root.getLastTouchPoint(shadowSize);
22894
22895                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22896                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22897                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22898                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22899            }
22900        } catch (Exception e) {
22901            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22902            mAttachInfo.mDragSurface.destroy();
22903            mAttachInfo.mDragSurface = null;
22904        }
22905
22906        return okay;
22907    }
22908
22909    /**
22910     * Cancels an ongoing drag and drop operation.
22911     * <p>
22912     * A {@link android.view.DragEvent} object with
22913     * {@link android.view.DragEvent#getAction()} value of
22914     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22915     * {@link android.view.DragEvent#getResult()} value of {@code false}
22916     * will be sent to every
22917     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22918     * even if they are not currently visible.
22919     * </p>
22920     * <p>
22921     * This method can be called on any View in the same window as the View on which
22922     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22923     * was called.
22924     * </p>
22925     */
22926    public final void cancelDragAndDrop() {
22927        if (ViewDebug.DEBUG_DRAG) {
22928            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22929        }
22930        if (mAttachInfo == null) {
22931            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22932            return;
22933        }
22934        if (mAttachInfo.mDragToken != null) {
22935            try {
22936                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22937            } catch (Exception e) {
22938                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22939            }
22940            mAttachInfo.mDragToken = null;
22941        } else {
22942            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22943        }
22944    }
22945
22946    /**
22947     * Updates the drag shadow for the ongoing drag and drop operation.
22948     *
22949     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22950     * new drag shadow.
22951     */
22952    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22953        if (ViewDebug.DEBUG_DRAG) {
22954            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22955        }
22956        if (mAttachInfo == null) {
22957            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22958            return;
22959        }
22960        if (mAttachInfo.mDragToken != null) {
22961            try {
22962                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22963                try {
22964                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22965                    shadowBuilder.onDrawShadow(canvas);
22966                } finally {
22967                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22968                }
22969            } catch (Exception e) {
22970                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22971            }
22972        } else {
22973            Log.e(VIEW_LOG_TAG, "No active drag");
22974        }
22975    }
22976
22977    /**
22978     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22979     * between {startX, startY} and the new cursor positon.
22980     * @param startX horizontal coordinate where the move started.
22981     * @param startY vertical coordinate where the move started.
22982     * @return whether moving was started successfully.
22983     * @hide
22984     */
22985    public final boolean startMovingTask(float startX, float startY) {
22986        if (ViewDebug.DEBUG_POSITIONING) {
22987            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22988        }
22989        try {
22990            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22991        } catch (RemoteException e) {
22992            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22993        }
22994        return false;
22995    }
22996
22997    /**
22998     * Handles drag events sent by the system following a call to
22999     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
23000     * startDragAndDrop()}.
23001     *<p>
23002     * When the system calls this method, it passes a
23003     * {@link android.view.DragEvent} object. A call to
23004     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
23005     * in DragEvent. The method uses these to determine what is happening in the drag and drop
23006     * operation.
23007     * @param event The {@link android.view.DragEvent} sent by the system.
23008     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
23009     * in DragEvent, indicating the type of drag event represented by this object.
23010     * @return {@code true} if the method was successful, otherwise {@code false}.
23011     * <p>
23012     *  The method should return {@code true} in response to an action type of
23013     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
23014     *  operation.
23015     * </p>
23016     * <p>
23017     *  The method should also return {@code true} in response to an action type of
23018     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
23019     *  {@code false} if it didn't.
23020     * </p>
23021     * <p>
23022     *  For all other events, the return value is ignored.
23023     * </p>
23024     */
23025    public boolean onDragEvent(DragEvent event) {
23026        return false;
23027    }
23028
23029    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
23030    boolean dispatchDragEnterExitInPreN(DragEvent event) {
23031        return callDragEventHandler(event);
23032    }
23033
23034    /**
23035     * Detects if this View is enabled and has a drag event listener.
23036     * If both are true, then it calls the drag event listener with the
23037     * {@link android.view.DragEvent} it received. If the drag event listener returns
23038     * {@code true}, then dispatchDragEvent() returns {@code true}.
23039     * <p>
23040     * For all other cases, the method calls the
23041     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
23042     * method and returns its result.
23043     * </p>
23044     * <p>
23045     * This ensures that a drag event is always consumed, even if the View does not have a drag
23046     * event listener. However, if the View has a listener and the listener returns true, then
23047     * onDragEvent() is not called.
23048     * </p>
23049     */
23050    public boolean dispatchDragEvent(DragEvent event) {
23051        event.mEventHandlerWasCalled = true;
23052        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
23053            event.mAction == DragEvent.ACTION_DROP) {
23054            // About to deliver an event with coordinates to this view. Notify that now this view
23055            // has drag focus. This will send exit/enter events as needed.
23056            getViewRootImpl().setDragFocus(this, event);
23057        }
23058        return callDragEventHandler(event);
23059    }
23060
23061    final boolean callDragEventHandler(DragEvent event) {
23062        final boolean result;
23063
23064        ListenerInfo li = mListenerInfo;
23065        //noinspection SimplifiableIfStatement
23066        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
23067                && li.mOnDragListener.onDrag(this, event)) {
23068            result = true;
23069        } else {
23070            result = onDragEvent(event);
23071        }
23072
23073        switch (event.mAction) {
23074            case DragEvent.ACTION_DRAG_ENTERED: {
23075                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
23076                refreshDrawableState();
23077            } break;
23078            case DragEvent.ACTION_DRAG_EXITED: {
23079                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
23080                refreshDrawableState();
23081            } break;
23082            case DragEvent.ACTION_DRAG_ENDED: {
23083                mPrivateFlags2 &= ~View.DRAG_MASK;
23084                refreshDrawableState();
23085            } break;
23086        }
23087
23088        return result;
23089    }
23090
23091    boolean canAcceptDrag() {
23092        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
23093    }
23094
23095    /**
23096     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
23097     * it is ever exposed at all.
23098     * @hide
23099     */
23100    public void onCloseSystemDialogs(String reason) {
23101    }
23102
23103    /**
23104     * Given a Drawable whose bounds have been set to draw into this view,
23105     * update a Region being computed for
23106     * {@link #gatherTransparentRegion(android.graphics.Region)} so
23107     * that any non-transparent parts of the Drawable are removed from the
23108     * given transparent region.
23109     *
23110     * @param dr The Drawable whose transparency is to be applied to the region.
23111     * @param region A Region holding the current transparency information,
23112     * where any parts of the region that are set are considered to be
23113     * transparent.  On return, this region will be modified to have the
23114     * transparency information reduced by the corresponding parts of the
23115     * Drawable that are not transparent.
23116     * {@hide}
23117     */
23118    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
23119        if (DBG) {
23120            Log.i("View", "Getting transparent region for: " + this);
23121        }
23122        final Region r = dr.getTransparentRegion();
23123        final Rect db = dr.getBounds();
23124        final AttachInfo attachInfo = mAttachInfo;
23125        if (r != null && attachInfo != null) {
23126            final int w = getRight()-getLeft();
23127            final int h = getBottom()-getTop();
23128            if (db.left > 0) {
23129                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
23130                r.op(0, 0, db.left, h, Region.Op.UNION);
23131            }
23132            if (db.right < w) {
23133                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
23134                r.op(db.right, 0, w, h, Region.Op.UNION);
23135            }
23136            if (db.top > 0) {
23137                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
23138                r.op(0, 0, w, db.top, Region.Op.UNION);
23139            }
23140            if (db.bottom < h) {
23141                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
23142                r.op(0, db.bottom, w, h, Region.Op.UNION);
23143            }
23144            final int[] location = attachInfo.mTransparentLocation;
23145            getLocationInWindow(location);
23146            r.translate(location[0], location[1]);
23147            region.op(r, Region.Op.INTERSECT);
23148        } else {
23149            region.op(db, Region.Op.DIFFERENCE);
23150        }
23151    }
23152
23153    private void checkForLongClick(int delayOffset, float x, float y) {
23154        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
23155            mHasPerformedLongPress = false;
23156
23157            if (mPendingCheckForLongPress == null) {
23158                mPendingCheckForLongPress = new CheckForLongPress();
23159            }
23160            mPendingCheckForLongPress.setAnchor(x, y);
23161            mPendingCheckForLongPress.rememberWindowAttachCount();
23162            mPendingCheckForLongPress.rememberPressedState();
23163            postDelayed(mPendingCheckForLongPress,
23164                    ViewConfiguration.getLongPressTimeout() - delayOffset);
23165        }
23166    }
23167
23168    /**
23169     * Inflate a view from an XML resource.  This convenience method wraps the {@link
23170     * LayoutInflater} class, which provides a full range of options for view inflation.
23171     *
23172     * @param context The Context object for your activity or application.
23173     * @param resource The resource ID to inflate
23174     * @param root A view group that will be the parent.  Used to properly inflate the
23175     * layout_* parameters.
23176     * @see LayoutInflater
23177     */
23178    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
23179        LayoutInflater factory = LayoutInflater.from(context);
23180        return factory.inflate(resource, root);
23181    }
23182
23183    /**
23184     * Scroll the view with standard behavior for scrolling beyond the normal
23185     * content boundaries. Views that call this method should override
23186     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
23187     * results of an over-scroll operation.
23188     *
23189     * Views can use this method to handle any touch or fling-based scrolling.
23190     *
23191     * @param deltaX Change in X in pixels
23192     * @param deltaY Change in Y in pixels
23193     * @param scrollX Current X scroll value in pixels before applying deltaX
23194     * @param scrollY Current Y scroll value in pixels before applying deltaY
23195     * @param scrollRangeX Maximum content scroll range along the X axis
23196     * @param scrollRangeY Maximum content scroll range along the Y axis
23197     * @param maxOverScrollX Number of pixels to overscroll by in either direction
23198     *          along the X axis.
23199     * @param maxOverScrollY Number of pixels to overscroll by in either direction
23200     *          along the Y axis.
23201     * @param isTouchEvent true if this scroll operation is the result of a touch event.
23202     * @return true if scrolling was clamped to an over-scroll boundary along either
23203     *          axis, false otherwise.
23204     */
23205    @SuppressWarnings({"UnusedParameters"})
23206    protected boolean overScrollBy(int deltaX, int deltaY,
23207            int scrollX, int scrollY,
23208            int scrollRangeX, int scrollRangeY,
23209            int maxOverScrollX, int maxOverScrollY,
23210            boolean isTouchEvent) {
23211        final int overScrollMode = mOverScrollMode;
23212        final boolean canScrollHorizontal =
23213                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
23214        final boolean canScrollVertical =
23215                computeVerticalScrollRange() > computeVerticalScrollExtent();
23216        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
23217                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
23218        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
23219                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
23220
23221        int newScrollX = scrollX + deltaX;
23222        if (!overScrollHorizontal) {
23223            maxOverScrollX = 0;
23224        }
23225
23226        int newScrollY = scrollY + deltaY;
23227        if (!overScrollVertical) {
23228            maxOverScrollY = 0;
23229        }
23230
23231        // Clamp values if at the limits and record
23232        final int left = -maxOverScrollX;
23233        final int right = maxOverScrollX + scrollRangeX;
23234        final int top = -maxOverScrollY;
23235        final int bottom = maxOverScrollY + scrollRangeY;
23236
23237        boolean clampedX = false;
23238        if (newScrollX > right) {
23239            newScrollX = right;
23240            clampedX = true;
23241        } else if (newScrollX < left) {
23242            newScrollX = left;
23243            clampedX = true;
23244        }
23245
23246        boolean clampedY = false;
23247        if (newScrollY > bottom) {
23248            newScrollY = bottom;
23249            clampedY = true;
23250        } else if (newScrollY < top) {
23251            newScrollY = top;
23252            clampedY = true;
23253        }
23254
23255        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
23256
23257        return clampedX || clampedY;
23258    }
23259
23260    /**
23261     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
23262     * respond to the results of an over-scroll operation.
23263     *
23264     * @param scrollX New X scroll value in pixels
23265     * @param scrollY New Y scroll value in pixels
23266     * @param clampedX True if scrollX was clamped to an over-scroll boundary
23267     * @param clampedY True if scrollY was clamped to an over-scroll boundary
23268     */
23269    protected void onOverScrolled(int scrollX, int scrollY,
23270            boolean clampedX, boolean clampedY) {
23271        // Intentionally empty.
23272    }
23273
23274    /**
23275     * Returns the over-scroll mode for this view. The result will be
23276     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23277     * (allow over-scrolling only if the view content is larger than the container),
23278     * or {@link #OVER_SCROLL_NEVER}.
23279     *
23280     * @return This view's over-scroll mode.
23281     */
23282    public int getOverScrollMode() {
23283        return mOverScrollMode;
23284    }
23285
23286    /**
23287     * Set the over-scroll mode for this view. Valid over-scroll modes are
23288     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23289     * (allow over-scrolling only if the view content is larger than the container),
23290     * or {@link #OVER_SCROLL_NEVER}.
23291     *
23292     * Setting the over-scroll mode of a view will have an effect only if the
23293     * view is capable of scrolling.
23294     *
23295     * @param overScrollMode The new over-scroll mode for this view.
23296     */
23297    public void setOverScrollMode(int overScrollMode) {
23298        if (overScrollMode != OVER_SCROLL_ALWAYS &&
23299                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
23300                overScrollMode != OVER_SCROLL_NEVER) {
23301            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
23302        }
23303        mOverScrollMode = overScrollMode;
23304    }
23305
23306    /**
23307     * Enable or disable nested scrolling for this view.
23308     *
23309     * <p>If this property is set to true the view will be permitted to initiate nested
23310     * scrolling operations with a compatible parent view in the current hierarchy. If this
23311     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
23312     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
23313     * the nested scroll.</p>
23314     *
23315     * @param enabled true to enable nested scrolling, false to disable
23316     *
23317     * @see #isNestedScrollingEnabled()
23318     */
23319    public void setNestedScrollingEnabled(boolean enabled) {
23320        if (enabled) {
23321            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
23322        } else {
23323            stopNestedScroll();
23324            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
23325        }
23326    }
23327
23328    /**
23329     * Returns true if nested scrolling is enabled for this view.
23330     *
23331     * <p>If nested scrolling is enabled and this View class implementation supports it,
23332     * this view will act as a nested scrolling child view when applicable, forwarding data
23333     * about the scroll operation in progress to a compatible and cooperating nested scrolling
23334     * parent.</p>
23335     *
23336     * @return true if nested scrolling is enabled
23337     *
23338     * @see #setNestedScrollingEnabled(boolean)
23339     */
23340    public boolean isNestedScrollingEnabled() {
23341        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
23342                PFLAG3_NESTED_SCROLLING_ENABLED;
23343    }
23344
23345    /**
23346     * Begin a nestable scroll operation along the given axes.
23347     *
23348     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
23349     *
23350     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
23351     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
23352     * In the case of touch scrolling the nested scroll will be terminated automatically in
23353     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
23354     * In the event of programmatic scrolling the caller must explicitly call
23355     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
23356     *
23357     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
23358     * If it returns false the caller may ignore the rest of this contract until the next scroll.
23359     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
23360     *
23361     * <p>At each incremental step of the scroll the caller should invoke
23362     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
23363     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
23364     * parent at least partially consumed the scroll and the caller should adjust the amount it
23365     * scrolls by.</p>
23366     *
23367     * <p>After applying the remainder of the scroll delta the caller should invoke
23368     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
23369     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
23370     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
23371     * </p>
23372     *
23373     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
23374     *             {@link #SCROLL_AXIS_VERTICAL}.
23375     * @return true if a cooperative parent was found and nested scrolling has been enabled for
23376     *         the current gesture.
23377     *
23378     * @see #stopNestedScroll()
23379     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23380     * @see #dispatchNestedScroll(int, int, int, int, int[])
23381     */
23382    public boolean startNestedScroll(int axes) {
23383        if (hasNestedScrollingParent()) {
23384            // Already in progress
23385            return true;
23386        }
23387        if (isNestedScrollingEnabled()) {
23388            ViewParent p = getParent();
23389            View child = this;
23390            while (p != null) {
23391                try {
23392                    if (p.onStartNestedScroll(child, this, axes)) {
23393                        mNestedScrollingParent = p;
23394                        p.onNestedScrollAccepted(child, this, axes);
23395                        return true;
23396                    }
23397                } catch (AbstractMethodError e) {
23398                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23399                            "method onStartNestedScroll", e);
23400                    // Allow the search upward to continue
23401                }
23402                if (p instanceof View) {
23403                    child = (View) p;
23404                }
23405                p = p.getParent();
23406            }
23407        }
23408        return false;
23409    }
23410
23411    /**
23412     * Stop a nested scroll in progress.
23413     *
23414     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23415     *
23416     * @see #startNestedScroll(int)
23417     */
23418    public void stopNestedScroll() {
23419        if (mNestedScrollingParent != null) {
23420            mNestedScrollingParent.onStopNestedScroll(this);
23421            mNestedScrollingParent = null;
23422        }
23423    }
23424
23425    /**
23426     * Returns true if this view has a nested scrolling parent.
23427     *
23428     * <p>The presence of a nested scrolling parent indicates that this view has initiated
23429     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23430     *
23431     * @return whether this view has a nested scrolling parent
23432     */
23433    public boolean hasNestedScrollingParent() {
23434        return mNestedScrollingParent != null;
23435    }
23436
23437    /**
23438     * Dispatch one step of a nested scroll in progress.
23439     *
23440     * <p>Implementations of views that support nested scrolling should call this to report
23441     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23442     * is not currently in progress or nested scrolling is not
23443     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23444     *
23445     * <p>Compatible View implementations should also call
23446     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23447     * consuming a component of the scroll event themselves.</p>
23448     *
23449     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23450     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23451     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23452     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23453     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23454     *                       in local view coordinates of this view from before this operation
23455     *                       to after it completes. View implementations may use this to adjust
23456     *                       expected input coordinate tracking.
23457     * @return true if the event was dispatched, false if it could not be dispatched.
23458     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23459     */
23460    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23461            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23462        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23463            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23464                int startX = 0;
23465                int startY = 0;
23466                if (offsetInWindow != null) {
23467                    getLocationInWindow(offsetInWindow);
23468                    startX = offsetInWindow[0];
23469                    startY = offsetInWindow[1];
23470                }
23471
23472                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23473                        dxUnconsumed, dyUnconsumed);
23474
23475                if (offsetInWindow != null) {
23476                    getLocationInWindow(offsetInWindow);
23477                    offsetInWindow[0] -= startX;
23478                    offsetInWindow[1] -= startY;
23479                }
23480                return true;
23481            } else if (offsetInWindow != null) {
23482                // No motion, no dispatch. Keep offsetInWindow up to date.
23483                offsetInWindow[0] = 0;
23484                offsetInWindow[1] = 0;
23485            }
23486        }
23487        return false;
23488    }
23489
23490    /**
23491     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23492     *
23493     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23494     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23495     * scrolling operation to consume some or all of the scroll operation before the child view
23496     * consumes it.</p>
23497     *
23498     * @param dx Horizontal scroll distance in pixels
23499     * @param dy Vertical scroll distance in pixels
23500     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23501     *                 and consumed[1] the consumed dy.
23502     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23503     *                       in local view coordinates of this view from before this operation
23504     *                       to after it completes. View implementations may use this to adjust
23505     *                       expected input coordinate tracking.
23506     * @return true if the parent consumed some or all of the scroll delta
23507     * @see #dispatchNestedScroll(int, int, int, int, int[])
23508     */
23509    public boolean dispatchNestedPreScroll(int dx, int dy,
23510            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23511        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23512            if (dx != 0 || dy != 0) {
23513                int startX = 0;
23514                int startY = 0;
23515                if (offsetInWindow != null) {
23516                    getLocationInWindow(offsetInWindow);
23517                    startX = offsetInWindow[0];
23518                    startY = offsetInWindow[1];
23519                }
23520
23521                if (consumed == null) {
23522                    if (mTempNestedScrollConsumed == null) {
23523                        mTempNestedScrollConsumed = new int[2];
23524                    }
23525                    consumed = mTempNestedScrollConsumed;
23526                }
23527                consumed[0] = 0;
23528                consumed[1] = 0;
23529                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23530
23531                if (offsetInWindow != null) {
23532                    getLocationInWindow(offsetInWindow);
23533                    offsetInWindow[0] -= startX;
23534                    offsetInWindow[1] -= startY;
23535                }
23536                return consumed[0] != 0 || consumed[1] != 0;
23537            } else if (offsetInWindow != null) {
23538                offsetInWindow[0] = 0;
23539                offsetInWindow[1] = 0;
23540            }
23541        }
23542        return false;
23543    }
23544
23545    /**
23546     * Dispatch a fling to a nested scrolling parent.
23547     *
23548     * <p>This method should be used to indicate that a nested scrolling child has detected
23549     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23550     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23551     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23552     * along a scrollable axis.</p>
23553     *
23554     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23555     * its own content, it can use this method to delegate the fling to its nested scrolling
23556     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23557     *
23558     * @param velocityX Horizontal fling velocity in pixels per second
23559     * @param velocityY Vertical fling velocity in pixels per second
23560     * @param consumed true if the child consumed the fling, false otherwise
23561     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23562     */
23563    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23564        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23565            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23566        }
23567        return false;
23568    }
23569
23570    /**
23571     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23572     *
23573     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23574     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23575     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23576     * before the child view consumes it. If this method returns <code>true</code>, a nested
23577     * parent view consumed the fling and this view should not scroll as a result.</p>
23578     *
23579     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23580     * the fling at a time. If a parent view consumed the fling this method will return false.
23581     * Custom view implementations should account for this in two ways:</p>
23582     *
23583     * <ul>
23584     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23585     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23586     *     position regardless.</li>
23587     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23588     *     even to settle back to a valid idle position.</li>
23589     * </ul>
23590     *
23591     * <p>Views should also not offer fling velocities to nested parent views along an axis
23592     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23593     * should not offer a horizontal fling velocity to its parents since scrolling along that
23594     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23595     *
23596     * @param velocityX Horizontal fling velocity in pixels per second
23597     * @param velocityY Vertical fling velocity in pixels per second
23598     * @return true if a nested scrolling parent consumed the fling
23599     */
23600    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23601        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23602            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23603        }
23604        return false;
23605    }
23606
23607    /**
23608     * Gets a scale factor that determines the distance the view should scroll
23609     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23610     * @return The vertical scroll scale factor.
23611     * @hide
23612     */
23613    protected float getVerticalScrollFactor() {
23614        if (mVerticalScrollFactor == 0) {
23615            TypedValue outValue = new TypedValue();
23616            if (!mContext.getTheme().resolveAttribute(
23617                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23618                throw new IllegalStateException(
23619                        "Expected theme to define listPreferredItemHeight.");
23620            }
23621            mVerticalScrollFactor = outValue.getDimension(
23622                    mContext.getResources().getDisplayMetrics());
23623        }
23624        return mVerticalScrollFactor;
23625    }
23626
23627    /**
23628     * Gets a scale factor that determines the distance the view should scroll
23629     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23630     * @return The horizontal scroll scale factor.
23631     * @hide
23632     */
23633    protected float getHorizontalScrollFactor() {
23634        // TODO: Should use something else.
23635        return getVerticalScrollFactor();
23636    }
23637
23638    /**
23639     * Return the value specifying the text direction or policy that was set with
23640     * {@link #setTextDirection(int)}.
23641     *
23642     * @return the defined text direction. It can be one of:
23643     *
23644     * {@link #TEXT_DIRECTION_INHERIT},
23645     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23646     * {@link #TEXT_DIRECTION_ANY_RTL},
23647     * {@link #TEXT_DIRECTION_LTR},
23648     * {@link #TEXT_DIRECTION_RTL},
23649     * {@link #TEXT_DIRECTION_LOCALE},
23650     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23651     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23652     *
23653     * @attr ref android.R.styleable#View_textDirection
23654     *
23655     * @hide
23656     */
23657    @ViewDebug.ExportedProperty(category = "text", mapping = {
23658            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23659            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23660            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23661            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23662            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23663            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23664            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23665            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23666    })
23667    public int getRawTextDirection() {
23668        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23669    }
23670
23671    /**
23672     * Set the text direction.
23673     *
23674     * @param textDirection the direction to set. Should be one of:
23675     *
23676     * {@link #TEXT_DIRECTION_INHERIT},
23677     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23678     * {@link #TEXT_DIRECTION_ANY_RTL},
23679     * {@link #TEXT_DIRECTION_LTR},
23680     * {@link #TEXT_DIRECTION_RTL},
23681     * {@link #TEXT_DIRECTION_LOCALE}
23682     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23683     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23684     *
23685     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23686     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23687     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23688     *
23689     * @attr ref android.R.styleable#View_textDirection
23690     */
23691    public void setTextDirection(int textDirection) {
23692        if (getRawTextDirection() != textDirection) {
23693            // Reset the current text direction and the resolved one
23694            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23695            resetResolvedTextDirection();
23696            // Set the new text direction
23697            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23698            // Do resolution
23699            resolveTextDirection();
23700            // Notify change
23701            onRtlPropertiesChanged(getLayoutDirection());
23702            // Refresh
23703            requestLayout();
23704            invalidate(true);
23705        }
23706    }
23707
23708    /**
23709     * Return the resolved text direction.
23710     *
23711     * @return the resolved text direction. Returns one of:
23712     *
23713     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23714     * {@link #TEXT_DIRECTION_ANY_RTL},
23715     * {@link #TEXT_DIRECTION_LTR},
23716     * {@link #TEXT_DIRECTION_RTL},
23717     * {@link #TEXT_DIRECTION_LOCALE},
23718     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23719     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23720     *
23721     * @attr ref android.R.styleable#View_textDirection
23722     */
23723    @ViewDebug.ExportedProperty(category = "text", mapping = {
23724            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23725            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23726            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23727            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23728            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23729            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23730            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23731            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23732    })
23733    public int getTextDirection() {
23734        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23735    }
23736
23737    /**
23738     * Resolve the text direction.
23739     *
23740     * @return true if resolution has been done, false otherwise.
23741     *
23742     * @hide
23743     */
23744    public boolean resolveTextDirection() {
23745        // Reset any previous text direction resolution
23746        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23747
23748        if (hasRtlSupport()) {
23749            // Set resolved text direction flag depending on text direction flag
23750            final int textDirection = getRawTextDirection();
23751            switch(textDirection) {
23752                case TEXT_DIRECTION_INHERIT:
23753                    if (!canResolveTextDirection()) {
23754                        // We cannot do the resolution if there is no parent, so use the default one
23755                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23756                        // Resolution will need to happen again later
23757                        return false;
23758                    }
23759
23760                    // Parent has not yet resolved, so we still return the default
23761                    try {
23762                        if (!mParent.isTextDirectionResolved()) {
23763                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23764                            // Resolution will need to happen again later
23765                            return false;
23766                        }
23767                    } catch (AbstractMethodError e) {
23768                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23769                                " does not fully implement ViewParent", e);
23770                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23771                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23772                        return true;
23773                    }
23774
23775                    // Set current resolved direction to the same value as the parent's one
23776                    int parentResolvedDirection;
23777                    try {
23778                        parentResolvedDirection = mParent.getTextDirection();
23779                    } catch (AbstractMethodError e) {
23780                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23781                                " does not fully implement ViewParent", e);
23782                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23783                    }
23784                    switch (parentResolvedDirection) {
23785                        case TEXT_DIRECTION_FIRST_STRONG:
23786                        case TEXT_DIRECTION_ANY_RTL:
23787                        case TEXT_DIRECTION_LTR:
23788                        case TEXT_DIRECTION_RTL:
23789                        case TEXT_DIRECTION_LOCALE:
23790                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23791                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23792                            mPrivateFlags2 |=
23793                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23794                            break;
23795                        default:
23796                            // Default resolved direction is "first strong" heuristic
23797                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23798                    }
23799                    break;
23800                case TEXT_DIRECTION_FIRST_STRONG:
23801                case TEXT_DIRECTION_ANY_RTL:
23802                case TEXT_DIRECTION_LTR:
23803                case TEXT_DIRECTION_RTL:
23804                case TEXT_DIRECTION_LOCALE:
23805                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23806                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23807                    // Resolved direction is the same as text direction
23808                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23809                    break;
23810                default:
23811                    // Default resolved direction is "first strong" heuristic
23812                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23813            }
23814        } else {
23815            // Default resolved direction is "first strong" heuristic
23816            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23817        }
23818
23819        // Set to resolved
23820        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23821        return true;
23822    }
23823
23824    /**
23825     * Check if text direction resolution can be done.
23826     *
23827     * @return true if text direction resolution can be done otherwise return false.
23828     */
23829    public boolean canResolveTextDirection() {
23830        switch (getRawTextDirection()) {
23831            case TEXT_DIRECTION_INHERIT:
23832                if (mParent != null) {
23833                    try {
23834                        return mParent.canResolveTextDirection();
23835                    } catch (AbstractMethodError e) {
23836                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23837                                " does not fully implement ViewParent", e);
23838                    }
23839                }
23840                return false;
23841
23842            default:
23843                return true;
23844        }
23845    }
23846
23847    /**
23848     * Reset resolved text direction. Text direction will be resolved during a call to
23849     * {@link #onMeasure(int, int)}.
23850     *
23851     * @hide
23852     */
23853    public void resetResolvedTextDirection() {
23854        // Reset any previous text direction resolution
23855        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23856        // Set to default value
23857        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23858    }
23859
23860    /**
23861     * @return true if text direction is inherited.
23862     *
23863     * @hide
23864     */
23865    public boolean isTextDirectionInherited() {
23866        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23867    }
23868
23869    /**
23870     * @return true if text direction is resolved.
23871     */
23872    public boolean isTextDirectionResolved() {
23873        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23874    }
23875
23876    /**
23877     * Return the value specifying the text alignment or policy that was set with
23878     * {@link #setTextAlignment(int)}.
23879     *
23880     * @return the defined text alignment. It can be one of:
23881     *
23882     * {@link #TEXT_ALIGNMENT_INHERIT},
23883     * {@link #TEXT_ALIGNMENT_GRAVITY},
23884     * {@link #TEXT_ALIGNMENT_CENTER},
23885     * {@link #TEXT_ALIGNMENT_TEXT_START},
23886     * {@link #TEXT_ALIGNMENT_TEXT_END},
23887     * {@link #TEXT_ALIGNMENT_VIEW_START},
23888     * {@link #TEXT_ALIGNMENT_VIEW_END}
23889     *
23890     * @attr ref android.R.styleable#View_textAlignment
23891     *
23892     * @hide
23893     */
23894    @ViewDebug.ExportedProperty(category = "text", mapping = {
23895            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23896            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23897            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23898            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23899            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23900            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23901            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23902    })
23903    @TextAlignment
23904    public int getRawTextAlignment() {
23905        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23906    }
23907
23908    /**
23909     * Set the text alignment.
23910     *
23911     * @param textAlignment The text alignment to set. Should be one of
23912     *
23913     * {@link #TEXT_ALIGNMENT_INHERIT},
23914     * {@link #TEXT_ALIGNMENT_GRAVITY},
23915     * {@link #TEXT_ALIGNMENT_CENTER},
23916     * {@link #TEXT_ALIGNMENT_TEXT_START},
23917     * {@link #TEXT_ALIGNMENT_TEXT_END},
23918     * {@link #TEXT_ALIGNMENT_VIEW_START},
23919     * {@link #TEXT_ALIGNMENT_VIEW_END}
23920     *
23921     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23922     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23923     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23924     *
23925     * @attr ref android.R.styleable#View_textAlignment
23926     */
23927    public void setTextAlignment(@TextAlignment int textAlignment) {
23928        if (textAlignment != getRawTextAlignment()) {
23929            // Reset the current and resolved text alignment
23930            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23931            resetResolvedTextAlignment();
23932            // Set the new text alignment
23933            mPrivateFlags2 |=
23934                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23935            // Do resolution
23936            resolveTextAlignment();
23937            // Notify change
23938            onRtlPropertiesChanged(getLayoutDirection());
23939            // Refresh
23940            requestLayout();
23941            invalidate(true);
23942        }
23943    }
23944
23945    /**
23946     * Return the resolved text alignment.
23947     *
23948     * @return the resolved text alignment. Returns one of:
23949     *
23950     * {@link #TEXT_ALIGNMENT_GRAVITY},
23951     * {@link #TEXT_ALIGNMENT_CENTER},
23952     * {@link #TEXT_ALIGNMENT_TEXT_START},
23953     * {@link #TEXT_ALIGNMENT_TEXT_END},
23954     * {@link #TEXT_ALIGNMENT_VIEW_START},
23955     * {@link #TEXT_ALIGNMENT_VIEW_END}
23956     *
23957     * @attr ref android.R.styleable#View_textAlignment
23958     */
23959    @ViewDebug.ExportedProperty(category = "text", mapping = {
23960            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23961            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23962            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23963            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23964            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23965            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23966            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23967    })
23968    @TextAlignment
23969    public int getTextAlignment() {
23970        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23971                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23972    }
23973
23974    /**
23975     * Resolve the text alignment.
23976     *
23977     * @return true if resolution has been done, false otherwise.
23978     *
23979     * @hide
23980     */
23981    public boolean resolveTextAlignment() {
23982        // Reset any previous text alignment resolution
23983        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23984
23985        if (hasRtlSupport()) {
23986            // Set resolved text alignment flag depending on text alignment flag
23987            final int textAlignment = getRawTextAlignment();
23988            switch (textAlignment) {
23989                case TEXT_ALIGNMENT_INHERIT:
23990                    // Check if we can resolve the text alignment
23991                    if (!canResolveTextAlignment()) {
23992                        // We cannot do the resolution if there is no parent so use the default
23993                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23994                        // Resolution will need to happen again later
23995                        return false;
23996                    }
23997
23998                    // Parent has not yet resolved, so we still return the default
23999                    try {
24000                        if (!mParent.isTextAlignmentResolved()) {
24001                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24002                            // Resolution will need to happen again later
24003                            return false;
24004                        }
24005                    } catch (AbstractMethodError e) {
24006                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24007                                " does not fully implement ViewParent", e);
24008                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
24009                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24010                        return true;
24011                    }
24012
24013                    int parentResolvedTextAlignment;
24014                    try {
24015                        parentResolvedTextAlignment = mParent.getTextAlignment();
24016                    } catch (AbstractMethodError e) {
24017                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24018                                " does not fully implement ViewParent", e);
24019                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
24020                    }
24021                    switch (parentResolvedTextAlignment) {
24022                        case TEXT_ALIGNMENT_GRAVITY:
24023                        case TEXT_ALIGNMENT_TEXT_START:
24024                        case TEXT_ALIGNMENT_TEXT_END:
24025                        case TEXT_ALIGNMENT_CENTER:
24026                        case TEXT_ALIGNMENT_VIEW_START:
24027                        case TEXT_ALIGNMENT_VIEW_END:
24028                            // Resolved text alignment is the same as the parent resolved
24029                            // text alignment
24030                            mPrivateFlags2 |=
24031                                    (parentResolvedTextAlignment << 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                    break;
24038                case TEXT_ALIGNMENT_GRAVITY:
24039                case TEXT_ALIGNMENT_TEXT_START:
24040                case TEXT_ALIGNMENT_TEXT_END:
24041                case TEXT_ALIGNMENT_CENTER:
24042                case TEXT_ALIGNMENT_VIEW_START:
24043                case TEXT_ALIGNMENT_VIEW_END:
24044                    // Resolved text alignment is the same as text alignment
24045                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24046                    break;
24047                default:
24048                    // Use default resolved text alignment
24049                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24050            }
24051        } else {
24052            // Use default resolved text alignment
24053            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24054        }
24055
24056        // Set the resolved
24057        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24058        return true;
24059    }
24060
24061    /**
24062     * Check if text alignment resolution can be done.
24063     *
24064     * @return true if text alignment resolution can be done otherwise return false.
24065     */
24066    public boolean canResolveTextAlignment() {
24067        switch (getRawTextAlignment()) {
24068            case TEXT_DIRECTION_INHERIT:
24069                if (mParent != null) {
24070                    try {
24071                        return mParent.canResolveTextAlignment();
24072                    } catch (AbstractMethodError e) {
24073                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24074                                " does not fully implement ViewParent", e);
24075                    }
24076                }
24077                return false;
24078
24079            default:
24080                return true;
24081        }
24082    }
24083
24084    /**
24085     * Reset resolved text alignment. Text alignment will be resolved during a call to
24086     * {@link #onMeasure(int, int)}.
24087     *
24088     * @hide
24089     */
24090    public void resetResolvedTextAlignment() {
24091        // Reset any previous text alignment resolution
24092        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24093        // Set to default
24094        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24095    }
24096
24097    /**
24098     * @return true if text alignment is inherited.
24099     *
24100     * @hide
24101     */
24102    public boolean isTextAlignmentInherited() {
24103        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
24104    }
24105
24106    /**
24107     * @return true if text alignment is resolved.
24108     */
24109    public boolean isTextAlignmentResolved() {
24110        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24111    }
24112
24113    /**
24114     * Generate a value suitable for use in {@link #setId(int)}.
24115     * This value will not collide with ID values generated at build time by aapt for R.id.
24116     *
24117     * @return a generated ID value
24118     */
24119    public static int generateViewId() {
24120        for (;;) {
24121            final int result = sNextGeneratedId.get();
24122            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
24123            int newValue = result + 1;
24124            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
24125            if (sNextGeneratedId.compareAndSet(result, newValue)) {
24126                return result;
24127            }
24128        }
24129    }
24130
24131    private static boolean isViewIdGenerated(int id) {
24132        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
24133    }
24134
24135    /**
24136     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
24137     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
24138     *                           a normal View or a ViewGroup with
24139     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
24140     * @hide
24141     */
24142    public void captureTransitioningViews(List<View> transitioningViews) {
24143        if (getVisibility() == View.VISIBLE) {
24144            transitioningViews.add(this);
24145        }
24146    }
24147
24148    /**
24149     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
24150     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
24151     * @hide
24152     */
24153    public void findNamedViews(Map<String, View> namedElements) {
24154        if (getVisibility() == VISIBLE || mGhostView != null) {
24155            String transitionName = getTransitionName();
24156            if (transitionName != null) {
24157                namedElements.put(transitionName, this);
24158            }
24159        }
24160    }
24161
24162    /**
24163     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
24164     * The default implementation does not care the location or event types, but some subclasses
24165     * may use it (such as WebViews).
24166     * @param event The MotionEvent from a mouse
24167     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
24168     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
24169     * @see PointerIcon
24170     */
24171    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
24172        final float x = event.getX(pointerIndex);
24173        final float y = event.getY(pointerIndex);
24174        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
24175            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
24176        }
24177        return mPointerIcon;
24178    }
24179
24180    /**
24181     * Set the pointer icon for the current view.
24182     * Passing {@code null} will restore the pointer icon to its default value.
24183     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
24184     */
24185    public void setPointerIcon(PointerIcon pointerIcon) {
24186        mPointerIcon = pointerIcon;
24187        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
24188            return;
24189        }
24190        try {
24191            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
24192        } catch (RemoteException e) {
24193        }
24194    }
24195
24196    /**
24197     * Gets the pointer icon for the current view.
24198     */
24199    public PointerIcon getPointerIcon() {
24200        return mPointerIcon;
24201    }
24202
24203    /**
24204     * Checks pointer capture status.
24205     *
24206     * @return true if the view has pointer capture.
24207     * @see #requestPointerCapture()
24208     * @see #hasPointerCapture()
24209     */
24210    public boolean hasPointerCapture() {
24211        final ViewRootImpl viewRootImpl = getViewRootImpl();
24212        if (viewRootImpl == null) {
24213            return false;
24214        }
24215        return viewRootImpl.hasPointerCapture();
24216    }
24217
24218    /**
24219     * Requests pointer capture mode.
24220     * <p>
24221     * When the window has pointer capture, the mouse pointer icon will disappear and will not
24222     * change its position. Further mouse will be dispatched with the source
24223     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
24224     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
24225     * (touchscreens, or stylus) will not be affected.
24226     * <p>
24227     * If the window already has pointer capture, this call does nothing.
24228     * <p>
24229     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
24230     * automatically when the window loses focus.
24231     *
24232     * @see #releasePointerCapture()
24233     * @see #hasPointerCapture()
24234     */
24235    public void requestPointerCapture() {
24236        final ViewRootImpl viewRootImpl = getViewRootImpl();
24237        if (viewRootImpl != null) {
24238            viewRootImpl.requestPointerCapture(true);
24239        }
24240    }
24241
24242
24243    /**
24244     * Releases the pointer capture.
24245     * <p>
24246     * If the window does not have pointer capture, this call will do nothing.
24247     * @see #requestPointerCapture()
24248     * @see #hasPointerCapture()
24249     */
24250    public void releasePointerCapture() {
24251        final ViewRootImpl viewRootImpl = getViewRootImpl();
24252        if (viewRootImpl != null) {
24253            viewRootImpl.requestPointerCapture(false);
24254        }
24255    }
24256
24257    /**
24258     * Called when the window has just acquired or lost pointer capture.
24259     *
24260     * @param hasCapture True if the view now has pointerCapture, false otherwise.
24261     */
24262    @CallSuper
24263    public void onPointerCaptureChange(boolean hasCapture) {
24264    }
24265
24266    /**
24267     * @see #onPointerCaptureChange
24268     */
24269    public void dispatchPointerCaptureChanged(boolean hasCapture) {
24270        onPointerCaptureChange(hasCapture);
24271    }
24272
24273    /**
24274     * Implement this method to handle captured pointer events
24275     *
24276     * @param event The captured pointer event.
24277     * @return True if the event was handled, false otherwise.
24278     * @see #requestPointerCapture()
24279     */
24280    public boolean onCapturedPointerEvent(MotionEvent event) {
24281        return false;
24282    }
24283
24284    /**
24285     * Interface definition for a callback to be invoked when a captured pointer event
24286     * is being dispatched this view. The callback will be invoked before the event is
24287     * given to the view.
24288     */
24289    public interface OnCapturedPointerListener {
24290        /**
24291         * Called when a captured pointer event is dispatched to a view.
24292         * @param view The view this event has been dispatched to.
24293         * @param event The captured event.
24294         * @return True if the listener has consumed the event, false otherwise.
24295         */
24296        boolean onCapturedPointer(View view, MotionEvent event);
24297    }
24298
24299    /**
24300     * Set a listener to receive callbacks when the pointer capture state of a view changes.
24301     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
24302     */
24303    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
24304        getListenerInfo().mOnCapturedPointerListener = l;
24305    }
24306
24307    // Properties
24308    //
24309    /**
24310     * A Property wrapper around the <code>alpha</code> functionality handled by the
24311     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
24312     */
24313    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
24314        @Override
24315        public void setValue(View object, float value) {
24316            object.setAlpha(value);
24317        }
24318
24319        @Override
24320        public Float get(View object) {
24321            return object.getAlpha();
24322        }
24323    };
24324
24325    /**
24326     * A Property wrapper around the <code>translationX</code> functionality handled by the
24327     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
24328     */
24329    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
24330        @Override
24331        public void setValue(View object, float value) {
24332            object.setTranslationX(value);
24333        }
24334
24335                @Override
24336        public Float get(View object) {
24337            return object.getTranslationX();
24338        }
24339    };
24340
24341    /**
24342     * A Property wrapper around the <code>translationY</code> functionality handled by the
24343     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
24344     */
24345    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
24346        @Override
24347        public void setValue(View object, float value) {
24348            object.setTranslationY(value);
24349        }
24350
24351        @Override
24352        public Float get(View object) {
24353            return object.getTranslationY();
24354        }
24355    };
24356
24357    /**
24358     * A Property wrapper around the <code>translationZ</code> functionality handled by the
24359     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
24360     */
24361    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
24362        @Override
24363        public void setValue(View object, float value) {
24364            object.setTranslationZ(value);
24365        }
24366
24367        @Override
24368        public Float get(View object) {
24369            return object.getTranslationZ();
24370        }
24371    };
24372
24373    /**
24374     * A Property wrapper around the <code>x</code> functionality handled by the
24375     * {@link View#setX(float)} and {@link View#getX()} methods.
24376     */
24377    public static final Property<View, Float> X = new FloatProperty<View>("x") {
24378        @Override
24379        public void setValue(View object, float value) {
24380            object.setX(value);
24381        }
24382
24383        @Override
24384        public Float get(View object) {
24385            return object.getX();
24386        }
24387    };
24388
24389    /**
24390     * A Property wrapper around the <code>y</code> functionality handled by the
24391     * {@link View#setY(float)} and {@link View#getY()} methods.
24392     */
24393    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24394        @Override
24395        public void setValue(View object, float value) {
24396            object.setY(value);
24397        }
24398
24399        @Override
24400        public Float get(View object) {
24401            return object.getY();
24402        }
24403    };
24404
24405    /**
24406     * A Property wrapper around the <code>z</code> functionality handled by the
24407     * {@link View#setZ(float)} and {@link View#getZ()} methods.
24408     */
24409    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24410        @Override
24411        public void setValue(View object, float value) {
24412            object.setZ(value);
24413        }
24414
24415        @Override
24416        public Float get(View object) {
24417            return object.getZ();
24418        }
24419    };
24420
24421    /**
24422     * A Property wrapper around the <code>rotation</code> functionality handled by the
24423     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24424     */
24425    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24426        @Override
24427        public void setValue(View object, float value) {
24428            object.setRotation(value);
24429        }
24430
24431        @Override
24432        public Float get(View object) {
24433            return object.getRotation();
24434        }
24435    };
24436
24437    /**
24438     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24439     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24440     */
24441    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24442        @Override
24443        public void setValue(View object, float value) {
24444            object.setRotationX(value);
24445        }
24446
24447        @Override
24448        public Float get(View object) {
24449            return object.getRotationX();
24450        }
24451    };
24452
24453    /**
24454     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24455     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24456     */
24457    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24458        @Override
24459        public void setValue(View object, float value) {
24460            object.setRotationY(value);
24461        }
24462
24463        @Override
24464        public Float get(View object) {
24465            return object.getRotationY();
24466        }
24467    };
24468
24469    /**
24470     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24471     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24472     */
24473    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24474        @Override
24475        public void setValue(View object, float value) {
24476            object.setScaleX(value);
24477        }
24478
24479        @Override
24480        public Float get(View object) {
24481            return object.getScaleX();
24482        }
24483    };
24484
24485    /**
24486     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24487     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24488     */
24489    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24490        @Override
24491        public void setValue(View object, float value) {
24492            object.setScaleY(value);
24493        }
24494
24495        @Override
24496        public Float get(View object) {
24497            return object.getScaleY();
24498        }
24499    };
24500
24501    /**
24502     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24503     * Each MeasureSpec represents a requirement for either the width or the height.
24504     * A MeasureSpec is comprised of a size and a mode. There are three possible
24505     * modes:
24506     * <dl>
24507     * <dt>UNSPECIFIED</dt>
24508     * <dd>
24509     * The parent has not imposed any constraint on the child. It can be whatever size
24510     * it wants.
24511     * </dd>
24512     *
24513     * <dt>EXACTLY</dt>
24514     * <dd>
24515     * The parent has determined an exact size for the child. The child is going to be
24516     * given those bounds regardless of how big it wants to be.
24517     * </dd>
24518     *
24519     * <dt>AT_MOST</dt>
24520     * <dd>
24521     * The child can be as large as it wants up to the specified size.
24522     * </dd>
24523     * </dl>
24524     *
24525     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24526     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24527     */
24528    public static class MeasureSpec {
24529        private static final int MODE_SHIFT = 30;
24530        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24531
24532        /** @hide */
24533        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24534        @Retention(RetentionPolicy.SOURCE)
24535        public @interface MeasureSpecMode {}
24536
24537        /**
24538         * Measure specification mode: The parent has not imposed any constraint
24539         * on the child. It can be whatever size it wants.
24540         */
24541        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24542
24543        /**
24544         * Measure specification mode: The parent has determined an exact size
24545         * for the child. The child is going to be given those bounds regardless
24546         * of how big it wants to be.
24547         */
24548        public static final int EXACTLY     = 1 << MODE_SHIFT;
24549
24550        /**
24551         * Measure specification mode: The child can be as large as it wants up
24552         * to the specified size.
24553         */
24554        public static final int AT_MOST     = 2 << MODE_SHIFT;
24555
24556        /**
24557         * Creates a measure specification based on the supplied size and mode.
24558         *
24559         * The mode must always be one of the following:
24560         * <ul>
24561         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24562         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24563         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24564         * </ul>
24565         *
24566         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24567         * implementation was such that the order of arguments did not matter
24568         * and overflow in either value could impact the resulting MeasureSpec.
24569         * {@link android.widget.RelativeLayout} was affected by this bug.
24570         * Apps targeting API levels greater than 17 will get the fixed, more strict
24571         * behavior.</p>
24572         *
24573         * @param size the size of the measure specification
24574         * @param mode the mode of the measure specification
24575         * @return the measure specification based on size and mode
24576         */
24577        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24578                                          @MeasureSpecMode int mode) {
24579            if (sUseBrokenMakeMeasureSpec) {
24580                return size + mode;
24581            } else {
24582                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24583            }
24584        }
24585
24586        /**
24587         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24588         * will automatically get a size of 0. Older apps expect this.
24589         *
24590         * @hide internal use only for compatibility with system widgets and older apps
24591         */
24592        public static int makeSafeMeasureSpec(int size, int mode) {
24593            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24594                return 0;
24595            }
24596            return makeMeasureSpec(size, mode);
24597        }
24598
24599        /**
24600         * Extracts the mode from the supplied measure specification.
24601         *
24602         * @param measureSpec the measure specification to extract the mode from
24603         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24604         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24605         *         {@link android.view.View.MeasureSpec#EXACTLY}
24606         */
24607        @MeasureSpecMode
24608        public static int getMode(int measureSpec) {
24609            //noinspection ResourceType
24610            return (measureSpec & MODE_MASK);
24611        }
24612
24613        /**
24614         * Extracts the size from the supplied measure specification.
24615         *
24616         * @param measureSpec the measure specification to extract the size from
24617         * @return the size in pixels defined in the supplied measure specification
24618         */
24619        public static int getSize(int measureSpec) {
24620            return (measureSpec & ~MODE_MASK);
24621        }
24622
24623        static int adjust(int measureSpec, int delta) {
24624            final int mode = getMode(measureSpec);
24625            int size = getSize(measureSpec);
24626            if (mode == UNSPECIFIED) {
24627                // No need to adjust size for UNSPECIFIED mode.
24628                return makeMeasureSpec(size, UNSPECIFIED);
24629            }
24630            size += delta;
24631            if (size < 0) {
24632                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24633                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24634                size = 0;
24635            }
24636            return makeMeasureSpec(size, mode);
24637        }
24638
24639        /**
24640         * Returns a String representation of the specified measure
24641         * specification.
24642         *
24643         * @param measureSpec the measure specification to convert to a String
24644         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24645         */
24646        public static String toString(int measureSpec) {
24647            int mode = getMode(measureSpec);
24648            int size = getSize(measureSpec);
24649
24650            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24651
24652            if (mode == UNSPECIFIED)
24653                sb.append("UNSPECIFIED ");
24654            else if (mode == EXACTLY)
24655                sb.append("EXACTLY ");
24656            else if (mode == AT_MOST)
24657                sb.append("AT_MOST ");
24658            else
24659                sb.append(mode).append(" ");
24660
24661            sb.append(size);
24662            return sb.toString();
24663        }
24664    }
24665
24666    private final class CheckForLongPress implements Runnable {
24667        private int mOriginalWindowAttachCount;
24668        private float mX;
24669        private float mY;
24670        private boolean mOriginalPressedState;
24671
24672        @Override
24673        public void run() {
24674            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24675                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24676                if (performLongClick(mX, mY)) {
24677                    mHasPerformedLongPress = true;
24678                }
24679            }
24680        }
24681
24682        public void setAnchor(float x, float y) {
24683            mX = x;
24684            mY = y;
24685        }
24686
24687        public void rememberWindowAttachCount() {
24688            mOriginalWindowAttachCount = mWindowAttachCount;
24689        }
24690
24691        public void rememberPressedState() {
24692            mOriginalPressedState = isPressed();
24693        }
24694    }
24695
24696    private final class CheckForTap implements Runnable {
24697        public float x;
24698        public float y;
24699
24700        @Override
24701        public void run() {
24702            mPrivateFlags &= ~PFLAG_PREPRESSED;
24703            setPressed(true, x, y);
24704            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24705        }
24706    }
24707
24708    private final class PerformClick implements Runnable {
24709        @Override
24710        public void run() {
24711            performClick();
24712        }
24713    }
24714
24715    /**
24716     * This method returns a ViewPropertyAnimator object, which can be used to animate
24717     * specific properties on this View.
24718     *
24719     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24720     */
24721    public ViewPropertyAnimator animate() {
24722        if (mAnimator == null) {
24723            mAnimator = new ViewPropertyAnimator(this);
24724        }
24725        return mAnimator;
24726    }
24727
24728    /**
24729     * Sets the name of the View to be used to identify Views in Transitions.
24730     * Names should be unique in the View hierarchy.
24731     *
24732     * @param transitionName The name of the View to uniquely identify it for Transitions.
24733     */
24734    public final void setTransitionName(String transitionName) {
24735        mTransitionName = transitionName;
24736    }
24737
24738    /**
24739     * Returns the name of the View to be used to identify Views in Transitions.
24740     * Names should be unique in the View hierarchy.
24741     *
24742     * <p>This returns null if the View has not been given a name.</p>
24743     *
24744     * @return The name used of the View to be used to identify Views in Transitions or null
24745     * if no name has been given.
24746     */
24747    @ViewDebug.ExportedProperty
24748    public String getTransitionName() {
24749        return mTransitionName;
24750    }
24751
24752    /**
24753     * @hide
24754     */
24755    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24756        // Do nothing.
24757    }
24758
24759    /**
24760     * Interface definition for a callback to be invoked when a hardware key event is
24761     * dispatched to this view. The callback will be invoked before the key event is
24762     * given to the view. This is only useful for hardware keyboards; a software input
24763     * method has no obligation to trigger this listener.
24764     */
24765    public interface OnKeyListener {
24766        /**
24767         * Called when a hardware key is dispatched to a view. This allows listeners to
24768         * get a chance to respond before the target view.
24769         * <p>Key presses in software keyboards will generally NOT trigger this method,
24770         * although some may elect to do so in some situations. Do not assume a
24771         * software input method has to be key-based; even if it is, it may use key presses
24772         * in a different way than you expect, so there is no way to reliably catch soft
24773         * input key presses.
24774         *
24775         * @param v The view the key has been dispatched to.
24776         * @param keyCode The code for the physical key that was pressed
24777         * @param event The KeyEvent object containing full information about
24778         *        the event.
24779         * @return True if the listener has consumed the event, false otherwise.
24780         */
24781        boolean onKey(View v, int keyCode, KeyEvent event);
24782    }
24783
24784    /**
24785     * Interface definition for a callback to be invoked when a touch event is
24786     * dispatched to this view. The callback will be invoked before the touch
24787     * event is given to the view.
24788     */
24789    public interface OnTouchListener {
24790        /**
24791         * Called when a touch event is dispatched to a view. This allows listeners to
24792         * get a chance to respond before the target view.
24793         *
24794         * @param v The view the touch event has been dispatched to.
24795         * @param event The MotionEvent object containing full information about
24796         *        the event.
24797         * @return True if the listener has consumed the event, false otherwise.
24798         */
24799        boolean onTouch(View v, MotionEvent event);
24800    }
24801
24802    /**
24803     * Interface definition for a callback to be invoked when a hover event is
24804     * dispatched to this view. The callback will be invoked before the hover
24805     * event is given to the view.
24806     */
24807    public interface OnHoverListener {
24808        /**
24809         * Called when a hover event is dispatched to a view. This allows listeners to
24810         * get a chance to respond before the target view.
24811         *
24812         * @param v The view the hover event has been dispatched to.
24813         * @param event The MotionEvent object containing full information about
24814         *        the event.
24815         * @return True if the listener has consumed the event, false otherwise.
24816         */
24817        boolean onHover(View v, MotionEvent event);
24818    }
24819
24820    /**
24821     * Interface definition for a callback to be invoked when a generic motion event is
24822     * dispatched to this view. The callback will be invoked before the generic motion
24823     * event is given to the view.
24824     */
24825    public interface OnGenericMotionListener {
24826        /**
24827         * Called when a generic motion event is dispatched to a view. This allows listeners to
24828         * get a chance to respond before the target view.
24829         *
24830         * @param v The view the generic motion event has been dispatched to.
24831         * @param event The MotionEvent object containing full information about
24832         *        the event.
24833         * @return True if the listener has consumed the event, false otherwise.
24834         */
24835        boolean onGenericMotion(View v, MotionEvent event);
24836    }
24837
24838    /**
24839     * Interface definition for a callback to be invoked when a view has been clicked and held.
24840     */
24841    public interface OnLongClickListener {
24842        /**
24843         * Called when a view has been clicked and held.
24844         *
24845         * @param v The view that was clicked and held.
24846         *
24847         * @return true if the callback consumed the long click, false otherwise.
24848         */
24849        boolean onLongClick(View v);
24850    }
24851
24852    /**
24853     * Interface definition for a callback to be invoked when a drag is being dispatched
24854     * to this view.  The callback will be invoked before the hosting view's own
24855     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24856     * onDrag(event) behavior, it should return 'false' from this callback.
24857     *
24858     * <div class="special reference">
24859     * <h3>Developer Guides</h3>
24860     * <p>For a guide to implementing drag and drop features, read the
24861     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24862     * </div>
24863     */
24864    public interface OnDragListener {
24865        /**
24866         * Called when a drag event is dispatched to a view. This allows listeners
24867         * to get a chance to override base View behavior.
24868         *
24869         * @param v The View that received the drag event.
24870         * @param event The {@link android.view.DragEvent} object for the drag event.
24871         * @return {@code true} if the drag event was handled successfully, or {@code false}
24872         * if the drag event was not handled. Note that {@code false} will trigger the View
24873         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24874         */
24875        boolean onDrag(View v, DragEvent event);
24876    }
24877
24878    /**
24879     * Interface definition for a callback to be invoked when the focus state of
24880     * a view changed.
24881     */
24882    public interface OnFocusChangeListener {
24883        /**
24884         * Called when the focus state of a view has changed.
24885         *
24886         * @param v The view whose state has changed.
24887         * @param hasFocus The new focus state of v.
24888         */
24889        void onFocusChange(View v, boolean hasFocus);
24890    }
24891
24892    /**
24893     * Interface definition for a callback to be invoked when a view is clicked.
24894     */
24895    public interface OnClickListener {
24896        /**
24897         * Called when a view has been clicked.
24898         *
24899         * @param v The view that was clicked.
24900         */
24901        void onClick(View v);
24902    }
24903
24904    /**
24905     * Interface definition for a callback to be invoked when a view is context clicked.
24906     */
24907    public interface OnContextClickListener {
24908        /**
24909         * Called when a view is context clicked.
24910         *
24911         * @param v The view that has been context clicked.
24912         * @return true if the callback consumed the context click, false otherwise.
24913         */
24914        boolean onContextClick(View v);
24915    }
24916
24917    /**
24918     * Interface definition for a callback to be invoked when the context menu
24919     * for this view is being built.
24920     */
24921    public interface OnCreateContextMenuListener {
24922        /**
24923         * Called when the context menu for this view is being built. It is not
24924         * safe to hold onto the menu after this method returns.
24925         *
24926         * @param menu The context menu that is being built
24927         * @param v The view for which the context menu is being built
24928         * @param menuInfo Extra information about the item for which the
24929         *            context menu should be shown. This information will vary
24930         *            depending on the class of v.
24931         */
24932        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24933    }
24934
24935    /**
24936     * Interface definition for a callback to be invoked when the status bar changes
24937     * visibility.  This reports <strong>global</strong> changes to the system UI
24938     * state, not what the application is requesting.
24939     *
24940     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24941     */
24942    public interface OnSystemUiVisibilityChangeListener {
24943        /**
24944         * Called when the status bar changes visibility because of a call to
24945         * {@link View#setSystemUiVisibility(int)}.
24946         *
24947         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24948         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24949         * This tells you the <strong>global</strong> state of these UI visibility
24950         * flags, not what your app is currently applying.
24951         */
24952        public void onSystemUiVisibilityChange(int visibility);
24953    }
24954
24955    /**
24956     * Interface definition for a callback to be invoked when this view is attached
24957     * or detached from its window.
24958     */
24959    public interface OnAttachStateChangeListener {
24960        /**
24961         * Called when the view is attached to a window.
24962         * @param v The view that was attached
24963         */
24964        public void onViewAttachedToWindow(View v);
24965        /**
24966         * Called when the view is detached from a window.
24967         * @param v The view that was detached
24968         */
24969        public void onViewDetachedFromWindow(View v);
24970    }
24971
24972    /**
24973     * Listener for applying window insets on a view in a custom way.
24974     *
24975     * <p>Apps may choose to implement this interface if they want to apply custom policy
24976     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24977     * is set, its
24978     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24979     * method will be called instead of the View's own
24980     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24981     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24982     * the View's normal behavior as part of its own.</p>
24983     */
24984    public interface OnApplyWindowInsetsListener {
24985        /**
24986         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24987         * on a View, this listener method will be called instead of the view's own
24988         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24989         *
24990         * @param v The view applying window insets
24991         * @param insets The insets to apply
24992         * @return The insets supplied, minus any insets that were consumed
24993         */
24994        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24995    }
24996
24997    private final class UnsetPressedState implements Runnable {
24998        @Override
24999        public void run() {
25000            setPressed(false);
25001        }
25002    }
25003
25004    /**
25005     * When a view becomes invisible checks if autofill considers the view invisible too. This
25006     * happens after the regular removal operation to make sure the operation is finished by the
25007     * time this is called.
25008     */
25009    private static class VisibilityChangeForAutofillHandler extends Handler {
25010        private final AutofillManager mAfm;
25011        private final View mView;
25012
25013        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
25014                @NonNull View view) {
25015            mAfm = afm;
25016            mView = view;
25017        }
25018
25019        @Override
25020        public void handleMessage(Message msg) {
25021            mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
25022        }
25023    }
25024
25025    /**
25026     * Base class for derived classes that want to save and restore their own
25027     * state in {@link android.view.View#onSaveInstanceState()}.
25028     */
25029    public static class BaseSavedState extends AbsSavedState {
25030        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
25031        static final int IS_AUTOFILLED = 0b10;
25032        static final int AUTOFILL_ID = 0b100;
25033
25034        // Flags that describe what data in this state is valid
25035        int mSavedData;
25036        String mStartActivityRequestWhoSaved;
25037        boolean mIsAutofilled;
25038        int mAutofillViewId;
25039
25040        /**
25041         * Constructor used when reading from a parcel. Reads the state of the superclass.
25042         *
25043         * @param source parcel to read from
25044         */
25045        public BaseSavedState(Parcel source) {
25046            this(source, null);
25047        }
25048
25049        /**
25050         * Constructor used when reading from a parcel using a given class loader.
25051         * Reads the state of the superclass.
25052         *
25053         * @param source parcel to read from
25054         * @param loader ClassLoader to use for reading
25055         */
25056        public BaseSavedState(Parcel source, ClassLoader loader) {
25057            super(source, loader);
25058            mSavedData = source.readInt();
25059            mStartActivityRequestWhoSaved = source.readString();
25060            mIsAutofilled = source.readBoolean();
25061            mAutofillViewId = source.readInt();
25062        }
25063
25064        /**
25065         * Constructor called by derived classes when creating their SavedState objects
25066         *
25067         * @param superState The state of the superclass of this view
25068         */
25069        public BaseSavedState(Parcelable superState) {
25070            super(superState);
25071        }
25072
25073        @Override
25074        public void writeToParcel(Parcel out, int flags) {
25075            super.writeToParcel(out, flags);
25076
25077            out.writeInt(mSavedData);
25078            out.writeString(mStartActivityRequestWhoSaved);
25079            out.writeBoolean(mIsAutofilled);
25080            out.writeInt(mAutofillViewId);
25081        }
25082
25083        public static final Parcelable.Creator<BaseSavedState> CREATOR
25084                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
25085            @Override
25086            public BaseSavedState createFromParcel(Parcel in) {
25087                return new BaseSavedState(in);
25088            }
25089
25090            @Override
25091            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
25092                return new BaseSavedState(in, loader);
25093            }
25094
25095            @Override
25096            public BaseSavedState[] newArray(int size) {
25097                return new BaseSavedState[size];
25098            }
25099        };
25100    }
25101
25102    /**
25103     * A set of information given to a view when it is attached to its parent
25104     * window.
25105     */
25106    final static class AttachInfo {
25107        interface Callbacks {
25108            void playSoundEffect(int effectId);
25109            boolean performHapticFeedback(int effectId, boolean always);
25110        }
25111
25112        /**
25113         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
25114         * to a Handler. This class contains the target (View) to invalidate and
25115         * the coordinates of the dirty rectangle.
25116         *
25117         * For performance purposes, this class also implements a pool of up to
25118         * POOL_LIMIT objects that get reused. This reduces memory allocations
25119         * whenever possible.
25120         */
25121        static class InvalidateInfo {
25122            private static final int POOL_LIMIT = 10;
25123
25124            private static final SynchronizedPool<InvalidateInfo> sPool =
25125                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
25126
25127            View target;
25128
25129            int left;
25130            int top;
25131            int right;
25132            int bottom;
25133
25134            public static InvalidateInfo obtain() {
25135                InvalidateInfo instance = sPool.acquire();
25136                return (instance != null) ? instance : new InvalidateInfo();
25137            }
25138
25139            public void recycle() {
25140                target = null;
25141                sPool.release(this);
25142            }
25143        }
25144
25145        final IWindowSession mSession;
25146
25147        final IWindow mWindow;
25148
25149        final IBinder mWindowToken;
25150
25151        Display mDisplay;
25152
25153        final Callbacks mRootCallbacks;
25154
25155        IWindowId mIWindowId;
25156        WindowId mWindowId;
25157
25158        /**
25159         * The top view of the hierarchy.
25160         */
25161        View mRootView;
25162
25163        IBinder mPanelParentWindowToken;
25164
25165        boolean mHardwareAccelerated;
25166        boolean mHardwareAccelerationRequested;
25167        ThreadedRenderer mThreadedRenderer;
25168        List<RenderNode> mPendingAnimatingRenderNodes;
25169
25170        /**
25171         * The state of the display to which the window is attached, as reported
25172         * by {@link Display#getState()}.  Note that the display state constants
25173         * declared by {@link Display} do not exactly line up with the screen state
25174         * constants declared by {@link View} (there are more display states than
25175         * screen states).
25176         */
25177        int mDisplayState = Display.STATE_UNKNOWN;
25178
25179        /**
25180         * Scale factor used by the compatibility mode
25181         */
25182        float mApplicationScale;
25183
25184        /**
25185         * Indicates whether the application is in compatibility mode
25186         */
25187        boolean mScalingRequired;
25188
25189        /**
25190         * Left position of this view's window
25191         */
25192        int mWindowLeft;
25193
25194        /**
25195         * Top position of this view's window
25196         */
25197        int mWindowTop;
25198
25199        /**
25200         * Indicates whether views need to use 32-bit drawing caches
25201         */
25202        boolean mUse32BitDrawingCache;
25203
25204        /**
25205         * For windows that are full-screen but using insets to layout inside
25206         * of the screen areas, these are the current insets to appear inside
25207         * the overscan area of the display.
25208         */
25209        final Rect mOverscanInsets = 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         * content of the window.
25215         */
25216        final Rect mContentInsets = new Rect();
25217
25218        /**
25219         * For windows that are full-screen but using insets to layout inside
25220         * of the screen decorations, these are the current insets for the
25221         * actual visible parts of the window.
25222         */
25223        final Rect mVisibleInsets = new Rect();
25224
25225        /**
25226         * For windows that are full-screen but using insets to layout inside
25227         * of the screen decorations, these are the current insets for the
25228         * stable system windows.
25229         */
25230        final Rect mStableInsets = new Rect();
25231
25232        /**
25233         * For windows that include areas that are not covered by real surface these are the outsets
25234         * for real surface.
25235         */
25236        final Rect mOutsets = new Rect();
25237
25238        /**
25239         * In multi-window we force show the navigation bar. Because we don't want that the surface
25240         * size changes in this mode, we instead have a flag whether the navigation bar size should
25241         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
25242         */
25243        boolean mAlwaysConsumeNavBar;
25244
25245        /**
25246         * The internal insets given by this window.  This value is
25247         * supplied by the client (through
25248         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
25249         * be given to the window manager when changed to be used in laying
25250         * out windows behind it.
25251         */
25252        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
25253                = new ViewTreeObserver.InternalInsetsInfo();
25254
25255        /**
25256         * Set to true when mGivenInternalInsets is non-empty.
25257         */
25258        boolean mHasNonEmptyGivenInternalInsets;
25259
25260        /**
25261         * All views in the window's hierarchy that serve as scroll containers,
25262         * used to determine if the window can be resized or must be panned
25263         * to adjust for a soft input area.
25264         */
25265        final ArrayList<View> mScrollContainers = new ArrayList<View>();
25266
25267        final KeyEvent.DispatcherState mKeyDispatchState
25268                = new KeyEvent.DispatcherState();
25269
25270        /**
25271         * Indicates whether the view's window currently has the focus.
25272         */
25273        boolean mHasWindowFocus;
25274
25275        /**
25276         * The current visibility of the window.
25277         */
25278        int mWindowVisibility;
25279
25280        /**
25281         * Indicates the time at which drawing started to occur.
25282         */
25283        long mDrawingTime;
25284
25285        /**
25286         * Indicates whether or not ignoring the DIRTY_MASK flags.
25287         */
25288        boolean mIgnoreDirtyState;
25289
25290        /**
25291         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
25292         * to avoid clearing that flag prematurely.
25293         */
25294        boolean mSetIgnoreDirtyState = false;
25295
25296        /**
25297         * Indicates whether the view's window is currently in touch mode.
25298         */
25299        boolean mInTouchMode;
25300
25301        /**
25302         * Indicates whether the view has requested unbuffered input dispatching for the current
25303         * event stream.
25304         */
25305        boolean mUnbufferedDispatchRequested;
25306
25307        /**
25308         * Indicates that ViewAncestor should trigger a global layout change
25309         * the next time it performs a traversal
25310         */
25311        boolean mRecomputeGlobalAttributes;
25312
25313        /**
25314         * Always report new attributes at next traversal.
25315         */
25316        boolean mForceReportNewAttributes;
25317
25318        /**
25319         * Set during a traveral if any views want to keep the screen on.
25320         */
25321        boolean mKeepScreenOn;
25322
25323        /**
25324         * Set during a traveral if the light center needs to be updated.
25325         */
25326        boolean mNeedsUpdateLightCenter;
25327
25328        /**
25329         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
25330         */
25331        int mSystemUiVisibility;
25332
25333        /**
25334         * Hack to force certain system UI visibility flags to be cleared.
25335         */
25336        int mDisabledSystemUiVisibility;
25337
25338        /**
25339         * Last global system UI visibility reported by the window manager.
25340         */
25341        int mGlobalSystemUiVisibility = -1;
25342
25343        /**
25344         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
25345         * attached.
25346         */
25347        boolean mHasSystemUiListeners;
25348
25349        /**
25350         * Set if the window has requested to extend into the overscan region
25351         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
25352         */
25353        boolean mOverscanRequested;
25354
25355        /**
25356         * Set if the visibility of any views has changed.
25357         */
25358        boolean mViewVisibilityChanged;
25359
25360        /**
25361         * Set to true if a view has been scrolled.
25362         */
25363        boolean mViewScrollChanged;
25364
25365        /**
25366         * Set to true if high contrast mode enabled
25367         */
25368        boolean mHighContrastText;
25369
25370        /**
25371         * Set to true if a pointer event is currently being handled.
25372         */
25373        boolean mHandlingPointerEvent;
25374
25375        /**
25376         * Global to the view hierarchy used as a temporary for dealing with
25377         * x/y points in the transparent region computations.
25378         */
25379        final int[] mTransparentLocation = new int[2];
25380
25381        /**
25382         * Global to the view hierarchy used as a temporary for dealing with
25383         * x/y points in the ViewGroup.invalidateChild implementation.
25384         */
25385        final int[] mInvalidateChildLocation = new int[2];
25386
25387        /**
25388         * Global to the view hierarchy used as a temporary for dealing with
25389         * computing absolute on-screen location.
25390         */
25391        final int[] mTmpLocation = new int[2];
25392
25393        /**
25394         * Global to the view hierarchy used as a temporary for dealing with
25395         * x/y location when view is transformed.
25396         */
25397        final float[] mTmpTransformLocation = new float[2];
25398
25399        /**
25400         * The view tree observer used to dispatch global events like
25401         * layout, pre-draw, touch mode change, etc.
25402         */
25403        final ViewTreeObserver mTreeObserver;
25404
25405        /**
25406         * A Canvas used by the view hierarchy to perform bitmap caching.
25407         */
25408        Canvas mCanvas;
25409
25410        /**
25411         * The view root impl.
25412         */
25413        final ViewRootImpl mViewRootImpl;
25414
25415        /**
25416         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25417         * handler can be used to pump events in the UI events queue.
25418         */
25419        final Handler mHandler;
25420
25421        /**
25422         * Temporary for use in computing invalidate rectangles while
25423         * calling up the hierarchy.
25424         */
25425        final Rect mTmpInvalRect = new Rect();
25426
25427        /**
25428         * Temporary for use in computing hit areas with transformed views
25429         */
25430        final RectF mTmpTransformRect = new RectF();
25431
25432        /**
25433         * Temporary for use in computing hit areas with transformed views
25434         */
25435        final RectF mTmpTransformRect1 = new RectF();
25436
25437        /**
25438         * Temporary list of rectanges.
25439         */
25440        final List<RectF> mTmpRectList = new ArrayList<>();
25441
25442        /**
25443         * Temporary for use in transforming invalidation rect
25444         */
25445        final Matrix mTmpMatrix = new Matrix();
25446
25447        /**
25448         * Temporary for use in transforming invalidation rect
25449         */
25450        final Transformation mTmpTransformation = new Transformation();
25451
25452        /**
25453         * Temporary for use in querying outlines from OutlineProviders
25454         */
25455        final Outline mTmpOutline = new Outline();
25456
25457        /**
25458         * Temporary list for use in collecting focusable descendents of a view.
25459         */
25460        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25461
25462        /**
25463         * The id of the window for accessibility purposes.
25464         */
25465        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25466
25467        /**
25468         * Flags related to accessibility processing.
25469         *
25470         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25471         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25472         */
25473        int mAccessibilityFetchFlags;
25474
25475        /**
25476         * The drawable for highlighting accessibility focus.
25477         */
25478        Drawable mAccessibilityFocusDrawable;
25479
25480        /**
25481         * The drawable for highlighting autofilled views.
25482         *
25483         * @see #isAutofilled()
25484         */
25485        Drawable mAutofilledDrawable;
25486
25487        /**
25488         * Show where the margins, bounds and layout bounds are for each view.
25489         */
25490        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25491
25492        /**
25493         * Point used to compute visible regions.
25494         */
25495        final Point mPoint = new Point();
25496
25497        /**
25498         * Used to track which View originated a requestLayout() call, used when
25499         * requestLayout() is called during layout.
25500         */
25501        View mViewRequestingLayout;
25502
25503        /**
25504         * Used to track views that need (at least) a partial relayout at their current size
25505         * during the next traversal.
25506         */
25507        List<View> mPartialLayoutViews = new ArrayList<>();
25508
25509        /**
25510         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25511         * modification. Lazily assigned during ViewRootImpl layout.
25512         */
25513        List<View> mEmptyPartialLayoutViews;
25514
25515        /**
25516         * Used to track the identity of the current drag operation.
25517         */
25518        IBinder mDragToken;
25519
25520        /**
25521         * The drag shadow surface for the current drag operation.
25522         */
25523        public Surface mDragSurface;
25524
25525
25526        /**
25527         * The view that currently has a tooltip displayed.
25528         */
25529        View mTooltipHost;
25530
25531        /**
25532         * Creates a new set of attachment information with the specified
25533         * events handler and thread.
25534         *
25535         * @param handler the events handler the view must use
25536         */
25537        AttachInfo(IWindowSession session, IWindow window, Display display,
25538                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25539                Context context) {
25540            mSession = session;
25541            mWindow = window;
25542            mWindowToken = window.asBinder();
25543            mDisplay = display;
25544            mViewRootImpl = viewRootImpl;
25545            mHandler = handler;
25546            mRootCallbacks = effectPlayer;
25547            mTreeObserver = new ViewTreeObserver(context);
25548        }
25549    }
25550
25551    /**
25552     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25553     * is supported. This avoids keeping too many unused fields in most
25554     * instances of View.</p>
25555     */
25556    private static class ScrollabilityCache implements Runnable {
25557
25558        /**
25559         * Scrollbars are not visible
25560         */
25561        public static final int OFF = 0;
25562
25563        /**
25564         * Scrollbars are visible
25565         */
25566        public static final int ON = 1;
25567
25568        /**
25569         * Scrollbars are fading away
25570         */
25571        public static final int FADING = 2;
25572
25573        public boolean fadeScrollBars;
25574
25575        public int fadingEdgeLength;
25576        public int scrollBarDefaultDelayBeforeFade;
25577        public int scrollBarFadeDuration;
25578
25579        public int scrollBarSize;
25580        public int scrollBarMinTouchTarget;
25581        public ScrollBarDrawable scrollBar;
25582        public float[] interpolatorValues;
25583        public View host;
25584
25585        public final Paint paint;
25586        public final Matrix matrix;
25587        public Shader shader;
25588
25589        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25590
25591        private static final float[] OPAQUE = { 255 };
25592        private static final float[] TRANSPARENT = { 0.0f };
25593
25594        /**
25595         * When fading should start. This time moves into the future every time
25596         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25597         */
25598        public long fadeStartTime;
25599
25600
25601        /**
25602         * The current state of the scrollbars: ON, OFF, or FADING
25603         */
25604        public int state = OFF;
25605
25606        private int mLastColor;
25607
25608        public final Rect mScrollBarBounds = new Rect();
25609        public final Rect mScrollBarTouchBounds = new Rect();
25610
25611        public static final int NOT_DRAGGING = 0;
25612        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25613        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25614        public int mScrollBarDraggingState = NOT_DRAGGING;
25615
25616        public float mScrollBarDraggingPos = 0;
25617
25618        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25619            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25620            scrollBarSize = configuration.getScaledScrollBarSize();
25621            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25622            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25623            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25624
25625            paint = new Paint();
25626            matrix = new Matrix();
25627            // use use a height of 1, and then wack the matrix each time we
25628            // actually use it.
25629            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25630            paint.setShader(shader);
25631            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25632
25633            this.host = host;
25634        }
25635
25636        public void setFadeColor(int color) {
25637            if (color != mLastColor) {
25638                mLastColor = color;
25639
25640                if (color != 0) {
25641                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25642                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25643                    paint.setShader(shader);
25644                    // Restore the default transfer mode (src_over)
25645                    paint.setXfermode(null);
25646                } else {
25647                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25648                    paint.setShader(shader);
25649                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25650                }
25651            }
25652        }
25653
25654        public void run() {
25655            long now = AnimationUtils.currentAnimationTimeMillis();
25656            if (now >= fadeStartTime) {
25657
25658                // the animation fades the scrollbars out by changing
25659                // the opacity (alpha) from fully opaque to fully
25660                // transparent
25661                int nextFrame = (int) now;
25662                int framesCount = 0;
25663
25664                Interpolator interpolator = scrollBarInterpolator;
25665
25666                // Start opaque
25667                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25668
25669                // End transparent
25670                nextFrame += scrollBarFadeDuration;
25671                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25672
25673                state = FADING;
25674
25675                // Kick off the fade animation
25676                host.invalidate(true);
25677            }
25678        }
25679    }
25680
25681    /**
25682     * Resuable callback for sending
25683     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25684     */
25685    private class SendViewScrolledAccessibilityEvent implements Runnable {
25686        public volatile boolean mIsPending;
25687
25688        public void run() {
25689            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25690            mIsPending = false;
25691        }
25692    }
25693
25694    /**
25695     * <p>
25696     * This class represents a delegate that can be registered in a {@link View}
25697     * to enhance accessibility support via composition rather via inheritance.
25698     * It is specifically targeted to widget developers that extend basic View
25699     * classes i.e. classes in package android.view, that would like their
25700     * applications to be backwards compatible.
25701     * </p>
25702     * <div class="special reference">
25703     * <h3>Developer Guides</h3>
25704     * <p>For more information about making applications accessible, read the
25705     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25706     * developer guide.</p>
25707     * </div>
25708     * <p>
25709     * A scenario in which a developer would like to use an accessibility delegate
25710     * is overriding a method introduced in a later API version than the minimal API
25711     * version supported by the application. For example, the method
25712     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25713     * in API version 4 when the accessibility APIs were first introduced. If a
25714     * developer would like his application to run on API version 4 devices (assuming
25715     * all other APIs used by the application are version 4 or lower) and take advantage
25716     * of this method, instead of overriding the method which would break the application's
25717     * backwards compatibility, he can override the corresponding method in this
25718     * delegate and register the delegate in the target View if the API version of
25719     * the system is high enough, i.e. the API version is the same as or higher than the API
25720     * version that introduced
25721     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25722     * </p>
25723     * <p>
25724     * Here is an example implementation:
25725     * </p>
25726     * <code><pre><p>
25727     * if (Build.VERSION.SDK_INT >= 14) {
25728     *     // If the API version is equal of higher than the version in
25729     *     // which onInitializeAccessibilityNodeInfo was introduced we
25730     *     // register a delegate with a customized implementation.
25731     *     View view = findViewById(R.id.view_id);
25732     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25733     *         public void onInitializeAccessibilityNodeInfo(View host,
25734     *                 AccessibilityNodeInfo info) {
25735     *             // Let the default implementation populate the info.
25736     *             super.onInitializeAccessibilityNodeInfo(host, info);
25737     *             // Set some other information.
25738     *             info.setEnabled(host.isEnabled());
25739     *         }
25740     *     });
25741     * }
25742     * </code></pre></p>
25743     * <p>
25744     * This delegate contains methods that correspond to the accessibility methods
25745     * in View. If a delegate has been specified the implementation in View hands
25746     * off handling to the corresponding method in this delegate. The default
25747     * implementation the delegate methods behaves exactly as the corresponding
25748     * method in View for the case of no accessibility delegate been set. Hence,
25749     * to customize the behavior of a View method, clients can override only the
25750     * corresponding delegate method without altering the behavior of the rest
25751     * accessibility related methods of the host view.
25752     * </p>
25753     * <p>
25754     * <strong>Note:</strong> On platform versions prior to
25755     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25756     * views in the {@code android.widget.*} package are called <i>before</i>
25757     * host methods. This prevents certain properties such as class name from
25758     * being modified by overriding
25759     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25760     * as any changes will be overwritten by the host class.
25761     * <p>
25762     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25763     * methods are called <i>after</i> host methods, which all properties to be
25764     * modified without being overwritten by the host class.
25765     */
25766    public static class AccessibilityDelegate {
25767
25768        /**
25769         * Sends an accessibility event of the given type. If accessibility is not
25770         * enabled this method has no effect.
25771         * <p>
25772         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25773         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25774         * been set.
25775         * </p>
25776         *
25777         * @param host The View hosting the delegate.
25778         * @param eventType The type of the event to send.
25779         *
25780         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25781         */
25782        public void sendAccessibilityEvent(View host, int eventType) {
25783            host.sendAccessibilityEventInternal(eventType);
25784        }
25785
25786        /**
25787         * Performs the specified accessibility action on the view. For
25788         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25789         * <p>
25790         * The default implementation behaves as
25791         * {@link View#performAccessibilityAction(int, Bundle)
25792         *  View#performAccessibilityAction(int, Bundle)} for the case of
25793         *  no accessibility delegate been set.
25794         * </p>
25795         *
25796         * @param action The action to perform.
25797         * @return Whether the action was performed.
25798         *
25799         * @see View#performAccessibilityAction(int, Bundle)
25800         *      View#performAccessibilityAction(int, Bundle)
25801         */
25802        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25803            return host.performAccessibilityActionInternal(action, args);
25804        }
25805
25806        /**
25807         * Sends an accessibility event. This method behaves exactly as
25808         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25809         * empty {@link AccessibilityEvent} and does not perform a check whether
25810         * accessibility is enabled.
25811         * <p>
25812         * The default implementation behaves as
25813         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25814         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25815         * the case of no accessibility delegate been set.
25816         * </p>
25817         *
25818         * @param host The View hosting the delegate.
25819         * @param event The event to send.
25820         *
25821         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25822         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25823         */
25824        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25825            host.sendAccessibilityEventUncheckedInternal(event);
25826        }
25827
25828        /**
25829         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25830         * to its children for adding their text content to the event.
25831         * <p>
25832         * The default implementation behaves as
25833         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25834         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25835         * the case of no accessibility delegate been set.
25836         * </p>
25837         *
25838         * @param host The View hosting the delegate.
25839         * @param event The event.
25840         * @return True if the event population was completed.
25841         *
25842         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25843         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25844         */
25845        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25846            return host.dispatchPopulateAccessibilityEventInternal(event);
25847        }
25848
25849        /**
25850         * Gives a chance to the host View to populate the accessibility event with its
25851         * text content.
25852         * <p>
25853         * The default implementation behaves as
25854         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25855         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25856         * the case of no accessibility delegate been set.
25857         * </p>
25858         *
25859         * @param host The View hosting the delegate.
25860         * @param event The accessibility event which to populate.
25861         *
25862         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25863         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25864         */
25865        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25866            host.onPopulateAccessibilityEventInternal(event);
25867        }
25868
25869        /**
25870         * Initializes an {@link AccessibilityEvent} with information about the
25871         * the host View which is the event source.
25872         * <p>
25873         * The default implementation behaves as
25874         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25875         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25876         * the case of no accessibility delegate been set.
25877         * </p>
25878         *
25879         * @param host The View hosting the delegate.
25880         * @param event The event to initialize.
25881         *
25882         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25883         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25884         */
25885        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25886            host.onInitializeAccessibilityEventInternal(event);
25887        }
25888
25889        /**
25890         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25891         * <p>
25892         * The default implementation behaves as
25893         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25894         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25895         * the case of no accessibility delegate been set.
25896         * </p>
25897         *
25898         * @param host The View hosting the delegate.
25899         * @param info The instance to initialize.
25900         *
25901         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25902         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25903         */
25904        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25905            host.onInitializeAccessibilityNodeInfoInternal(info);
25906        }
25907
25908        /**
25909         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25910         * additional data.
25911         * <p>
25912         * This method only needs to be implemented if the View offers to provide additional data.
25913         * </p>
25914         * <p>
25915         * The default implementation behaves as
25916         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
25917         * for the case where no accessibility delegate is set.
25918         * </p>
25919         *
25920         * @param host The View hosting the delegate. Never {@code null}.
25921         * @param info The info to which to add the extra data. Never {@code null}.
25922         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25923         *                     extra data should be added to the {@link Bundle} returned by
25924         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25925         *                     {@code null}.
25926         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25927         *                  May be {@code null} if the if the service provided no arguments.
25928         *
25929         * @see AccessibilityNodeInfo#setExtraAvailableData
25930         */
25931        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25932                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25933                @Nullable Bundle arguments) {
25934            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25935        }
25936
25937        /**
25938         * Called when a child of the host View has requested sending an
25939         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25940         * to augment the event.
25941         * <p>
25942         * The default implementation behaves as
25943         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25944         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25945         * the case of no accessibility delegate been set.
25946         * </p>
25947         *
25948         * @param host The View hosting the delegate.
25949         * @param child The child which requests sending the event.
25950         * @param event The event to be sent.
25951         * @return True if the event should be sent
25952         *
25953         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25954         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25955         */
25956        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25957                AccessibilityEvent event) {
25958            return host.onRequestSendAccessibilityEventInternal(child, event);
25959        }
25960
25961        /**
25962         * Gets the provider for managing a virtual view hierarchy rooted at this View
25963         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25964         * that explore the window content.
25965         * <p>
25966         * The default implementation behaves as
25967         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25968         * the case of no accessibility delegate been set.
25969         * </p>
25970         *
25971         * @return The provider.
25972         *
25973         * @see AccessibilityNodeProvider
25974         */
25975        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25976            return null;
25977        }
25978
25979        /**
25980         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25981         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25982         * This method is responsible for obtaining an accessibility node info from a
25983         * pool of reusable instances and calling
25984         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25985         * view to initialize the former.
25986         * <p>
25987         * <strong>Note:</strong> The client is responsible for recycling the obtained
25988         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25989         * creation.
25990         * </p>
25991         * <p>
25992         * The default implementation behaves as
25993         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25994         * the case of no accessibility delegate been set.
25995         * </p>
25996         * @return A populated {@link AccessibilityNodeInfo}.
25997         *
25998         * @see AccessibilityNodeInfo
25999         *
26000         * @hide
26001         */
26002        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
26003            return host.createAccessibilityNodeInfoInternal();
26004        }
26005    }
26006
26007    private static class MatchIdPredicate implements Predicate<View> {
26008        public int mId;
26009
26010        @Override
26011        public boolean test(View view) {
26012            return (view.mID == mId);
26013        }
26014    }
26015
26016    private static class MatchLabelForPredicate implements Predicate<View> {
26017        private int mLabeledId;
26018
26019        @Override
26020        public boolean test(View view) {
26021            return (view.mLabelForId == mLabeledId);
26022        }
26023    }
26024
26025    /**
26026     * Dump all private flags in readable format, useful for documentation and
26027     * sanity checking.
26028     */
26029    private static void dumpFlags() {
26030        final HashMap<String, String> found = Maps.newHashMap();
26031        try {
26032            for (Field field : View.class.getDeclaredFields()) {
26033                final int modifiers = field.getModifiers();
26034                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
26035                    if (field.getType().equals(int.class)) {
26036                        final int value = field.getInt(null);
26037                        dumpFlag(found, field.getName(), value);
26038                    } else if (field.getType().equals(int[].class)) {
26039                        final int[] values = (int[]) field.get(null);
26040                        for (int i = 0; i < values.length; i++) {
26041                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
26042                        }
26043                    }
26044                }
26045            }
26046        } catch (IllegalAccessException e) {
26047            throw new RuntimeException(e);
26048        }
26049
26050        final ArrayList<String> keys = Lists.newArrayList();
26051        keys.addAll(found.keySet());
26052        Collections.sort(keys);
26053        for (String key : keys) {
26054            Log.d(VIEW_LOG_TAG, found.get(key));
26055        }
26056    }
26057
26058    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
26059        // Sort flags by prefix, then by bits, always keeping unique keys
26060        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
26061        final int prefix = name.indexOf('_');
26062        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
26063        final String output = bits + " " + name;
26064        found.put(key, output);
26065    }
26066
26067    /** {@hide} */
26068    public void encode(@NonNull ViewHierarchyEncoder stream) {
26069        stream.beginObject(this);
26070        encodeProperties(stream);
26071        stream.endObject();
26072    }
26073
26074    /** {@hide} */
26075    @CallSuper
26076    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
26077        Object resolveId = ViewDebug.resolveId(getContext(), mID);
26078        if (resolveId instanceof String) {
26079            stream.addProperty("id", (String) resolveId);
26080        } else {
26081            stream.addProperty("id", mID);
26082        }
26083
26084        stream.addProperty("misc:transformation.alpha",
26085                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
26086        stream.addProperty("misc:transitionName", getTransitionName());
26087
26088        // layout
26089        stream.addProperty("layout:left", mLeft);
26090        stream.addProperty("layout:right", mRight);
26091        stream.addProperty("layout:top", mTop);
26092        stream.addProperty("layout:bottom", mBottom);
26093        stream.addProperty("layout:width", getWidth());
26094        stream.addProperty("layout:height", getHeight());
26095        stream.addProperty("layout:layoutDirection", getLayoutDirection());
26096        stream.addProperty("layout:layoutRtl", isLayoutRtl());
26097        stream.addProperty("layout:hasTransientState", hasTransientState());
26098        stream.addProperty("layout:baseline", getBaseline());
26099
26100        // layout params
26101        ViewGroup.LayoutParams layoutParams = getLayoutParams();
26102        if (layoutParams != null) {
26103            stream.addPropertyKey("layoutParams");
26104            layoutParams.encode(stream);
26105        }
26106
26107        // scrolling
26108        stream.addProperty("scrolling:scrollX", mScrollX);
26109        stream.addProperty("scrolling:scrollY", mScrollY);
26110
26111        // padding
26112        stream.addProperty("padding:paddingLeft", mPaddingLeft);
26113        stream.addProperty("padding:paddingRight", mPaddingRight);
26114        stream.addProperty("padding:paddingTop", mPaddingTop);
26115        stream.addProperty("padding:paddingBottom", mPaddingBottom);
26116        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
26117        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
26118        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
26119        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
26120        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
26121
26122        // measurement
26123        stream.addProperty("measurement:minHeight", mMinHeight);
26124        stream.addProperty("measurement:minWidth", mMinWidth);
26125        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
26126        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
26127
26128        // drawing
26129        stream.addProperty("drawing:elevation", getElevation());
26130        stream.addProperty("drawing:translationX", getTranslationX());
26131        stream.addProperty("drawing:translationY", getTranslationY());
26132        stream.addProperty("drawing:translationZ", getTranslationZ());
26133        stream.addProperty("drawing:rotation", getRotation());
26134        stream.addProperty("drawing:rotationX", getRotationX());
26135        stream.addProperty("drawing:rotationY", getRotationY());
26136        stream.addProperty("drawing:scaleX", getScaleX());
26137        stream.addProperty("drawing:scaleY", getScaleY());
26138        stream.addProperty("drawing:pivotX", getPivotX());
26139        stream.addProperty("drawing:pivotY", getPivotY());
26140        stream.addProperty("drawing:opaque", isOpaque());
26141        stream.addProperty("drawing:alpha", getAlpha());
26142        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
26143        stream.addProperty("drawing:shadow", hasShadow());
26144        stream.addProperty("drawing:solidColor", getSolidColor());
26145        stream.addProperty("drawing:layerType", mLayerType);
26146        stream.addProperty("drawing:willNotDraw", willNotDraw());
26147        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
26148        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
26149        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
26150        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
26151
26152        // focus
26153        stream.addProperty("focus:hasFocus", hasFocus());
26154        stream.addProperty("focus:isFocused", isFocused());
26155        stream.addProperty("focus:focusable", getFocusable());
26156        stream.addProperty("focus:isFocusable", isFocusable());
26157        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
26158
26159        stream.addProperty("misc:clickable", isClickable());
26160        stream.addProperty("misc:pressed", isPressed());
26161        stream.addProperty("misc:selected", isSelected());
26162        stream.addProperty("misc:touchMode", isInTouchMode());
26163        stream.addProperty("misc:hovered", isHovered());
26164        stream.addProperty("misc:activated", isActivated());
26165
26166        stream.addProperty("misc:visibility", getVisibility());
26167        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
26168        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
26169
26170        stream.addProperty("misc:enabled", isEnabled());
26171        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
26172        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
26173
26174        // theme attributes
26175        Resources.Theme theme = getContext().getTheme();
26176        if (theme != null) {
26177            stream.addPropertyKey("theme");
26178            theme.encode(stream);
26179        }
26180
26181        // view attribute information
26182        int n = mAttributes != null ? mAttributes.length : 0;
26183        stream.addProperty("meta:__attrCount__", n/2);
26184        for (int i = 0; i < n; i += 2) {
26185            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
26186        }
26187
26188        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
26189
26190        // text
26191        stream.addProperty("text:textDirection", getTextDirection());
26192        stream.addProperty("text:textAlignment", getTextAlignment());
26193
26194        // accessibility
26195        CharSequence contentDescription = getContentDescription();
26196        stream.addProperty("accessibility:contentDescription",
26197                contentDescription == null ? "" : contentDescription.toString());
26198        stream.addProperty("accessibility:labelFor", getLabelFor());
26199        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
26200    }
26201
26202    /**
26203     * Determine if this view is rendered on a round wearable device and is the main view
26204     * on the screen.
26205     */
26206    boolean shouldDrawRoundScrollbar() {
26207        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
26208            return false;
26209        }
26210
26211        final View rootView = getRootView();
26212        final WindowInsets insets = getRootWindowInsets();
26213
26214        int height = getHeight();
26215        int width = getWidth();
26216        int displayHeight = rootView.getHeight();
26217        int displayWidth = rootView.getWidth();
26218
26219        if (height != displayHeight || width != displayWidth) {
26220            return false;
26221        }
26222
26223        getLocationInWindow(mAttachInfo.mTmpLocation);
26224        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
26225                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
26226    }
26227
26228    /**
26229     * Sets the tooltip text which will be displayed in a small popup next to the view.
26230     * <p>
26231     * The tooltip will be displayed:
26232     * <ul>
26233     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
26234     * menu). </li>
26235     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
26236     * </ul>
26237     * <p>
26238     * <strong>Note:</strong> Do not override this method, as it will have no
26239     * effect on the text displayed in the tooltip.
26240     *
26241     * @param tooltipText the tooltip text, or null if no tooltip is required
26242     * @see #getTooltipText()
26243     * @attr ref android.R.styleable#View_tooltipText
26244     */
26245    public void setTooltipText(@Nullable CharSequence tooltipText) {
26246        if (TextUtils.isEmpty(tooltipText)) {
26247            setFlags(0, TOOLTIP);
26248            hideTooltip();
26249            mTooltipInfo = null;
26250        } else {
26251            setFlags(TOOLTIP, TOOLTIP);
26252            if (mTooltipInfo == null) {
26253                mTooltipInfo = new TooltipInfo();
26254                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
26255                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
26256            }
26257            mTooltipInfo.mTooltipText = tooltipText;
26258        }
26259    }
26260
26261    /**
26262     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26263     */
26264    public void setTooltip(@Nullable CharSequence tooltipText) {
26265        setTooltipText(tooltipText);
26266    }
26267
26268    /**
26269     * Returns the view's tooltip text.
26270     *
26271     * <strong>Note:</strong> Do not override this method, as it will have no
26272     * effect on the text displayed in the tooltip. You must call
26273     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
26274     *
26275     * @return the tooltip text
26276     * @see #setTooltipText(CharSequence)
26277     * @attr ref android.R.styleable#View_tooltipText
26278     */
26279    @Nullable
26280    public CharSequence getTooltipText() {
26281        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
26282    }
26283
26284    /**
26285     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26286     */
26287    @Nullable
26288    public CharSequence getTooltip() {
26289        return getTooltipText();
26290    }
26291
26292    private boolean showTooltip(int x, int y, boolean fromLongClick) {
26293        if (mAttachInfo == null || mTooltipInfo == null) {
26294            return false;
26295        }
26296        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
26297            return false;
26298        }
26299        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
26300            return false;
26301        }
26302        hideTooltip();
26303        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
26304        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
26305        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
26306        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
26307        mAttachInfo.mTooltipHost = this;
26308        return true;
26309    }
26310
26311    void hideTooltip() {
26312        if (mTooltipInfo == null) {
26313            return;
26314        }
26315        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26316        if (mTooltipInfo.mTooltipPopup == null) {
26317            return;
26318        }
26319        mTooltipInfo.mTooltipPopup.hide();
26320        mTooltipInfo.mTooltipPopup = null;
26321        mTooltipInfo.mTooltipFromLongClick = false;
26322        if (mAttachInfo != null) {
26323            mAttachInfo.mTooltipHost = null;
26324        }
26325    }
26326
26327    private boolean showLongClickTooltip(int x, int y) {
26328        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26329        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26330        return showTooltip(x, y, true);
26331    }
26332
26333    private void showHoverTooltip() {
26334        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
26335    }
26336
26337    boolean dispatchTooltipHoverEvent(MotionEvent event) {
26338        if (mTooltipInfo == null) {
26339            return false;
26340        }
26341        switch(event.getAction()) {
26342            case MotionEvent.ACTION_HOVER_MOVE:
26343                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
26344                    break;
26345                }
26346                if (!mTooltipInfo.mTooltipFromLongClick) {
26347                    if (mTooltipInfo.mTooltipPopup == null) {
26348                        // Schedule showing the tooltip after a timeout.
26349                        mTooltipInfo.mAnchorX = (int) event.getX();
26350                        mTooltipInfo.mAnchorY = (int) event.getY();
26351                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26352                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
26353                                ViewConfiguration.getHoverTooltipShowTimeout());
26354                    }
26355
26356                    // Hide hover-triggered tooltip after a period of inactivity.
26357                    // Match the timeout used by NativeInputManager to hide the mouse pointer
26358                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26359                    final int timeout;
26360                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26361                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
26362                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26363                    } else {
26364                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26365                    }
26366                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26367                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26368                }
26369                return true;
26370
26371            case MotionEvent.ACTION_HOVER_EXIT:
26372                if (!mTooltipInfo.mTooltipFromLongClick) {
26373                    hideTooltip();
26374                }
26375                break;
26376        }
26377        return false;
26378    }
26379
26380    void handleTooltipKey(KeyEvent event) {
26381        switch (event.getAction()) {
26382            case KeyEvent.ACTION_DOWN:
26383                if (event.getRepeatCount() == 0) {
26384                    hideTooltip();
26385                }
26386                break;
26387
26388            case KeyEvent.ACTION_UP:
26389                handleTooltipUp();
26390                break;
26391        }
26392    }
26393
26394    private void handleTooltipUp() {
26395        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26396            return;
26397        }
26398        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26399        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26400                ViewConfiguration.getLongPressTooltipHideTimeout());
26401    }
26402
26403    private int getFocusableAttribute(TypedArray attributes) {
26404        TypedValue val = new TypedValue();
26405        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26406            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26407                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26408            } else {
26409                return val.data;
26410            }
26411        } else {
26412            return FOCUSABLE_AUTO;
26413        }
26414    }
26415
26416    /**
26417     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26418     * is not showing.
26419     * @hide
26420     */
26421    @TestApi
26422    public View getTooltipView() {
26423        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26424            return null;
26425        }
26426        return mTooltipInfo.mTooltipPopup.getContentView();
26427    }
26428}
26429