View.java revision f4af35a5fe6298e6ea8d70377b18b0124145986a
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import static java.lang.Math.max;
20
21import android.animation.AnimatorInflater;
22import android.animation.StateListAnimator;
23import android.annotation.CallSuper;
24import android.annotation.ColorInt;
25import android.annotation.DrawableRes;
26import android.annotation.FloatRange;
27import android.annotation.IdRes;
28import android.annotation.IntDef;
29import android.annotation.IntRange;
30import android.annotation.LayoutRes;
31import android.annotation.NonNull;
32import android.annotation.Nullable;
33import android.annotation.Size;
34import android.annotation.TestApi;
35import android.annotation.UiThread;
36import android.content.ClipData;
37import android.content.Context;
38import android.content.ContextWrapper;
39import android.content.Intent;
40import android.content.res.ColorStateList;
41import android.content.res.Configuration;
42import android.content.res.Resources;
43import android.content.res.TypedArray;
44import android.graphics.Bitmap;
45import android.graphics.Canvas;
46import android.graphics.Color;
47import android.graphics.Insets;
48import android.graphics.Interpolator;
49import android.graphics.LinearGradient;
50import android.graphics.Matrix;
51import android.graphics.Outline;
52import android.graphics.Paint;
53import android.graphics.PixelFormat;
54import android.graphics.Point;
55import android.graphics.PorterDuff;
56import android.graphics.PorterDuffXfermode;
57import android.graphics.Rect;
58import android.graphics.RectF;
59import android.graphics.Region;
60import android.graphics.Shader;
61import android.graphics.drawable.ColorDrawable;
62import android.graphics.drawable.Drawable;
63import android.hardware.display.DisplayManagerGlobal;
64import android.net.Uri;
65import android.os.Build;
66import android.os.Bundle;
67import android.os.Handler;
68import android.os.IBinder;
69import android.os.Message;
70import android.os.Parcel;
71import android.os.Parcelable;
72import android.os.RemoteException;
73import android.os.SystemClock;
74import android.os.SystemProperties;
75import android.os.Trace;
76import android.text.TextUtils;
77import android.util.AttributeSet;
78import android.util.FloatProperty;
79import android.util.LayoutDirection;
80import android.util.Log;
81import android.util.LongSparseLongArray;
82import android.util.Pools.SynchronizedPool;
83import android.util.Property;
84import android.util.SparseArray;
85import android.util.StateSet;
86import android.util.SuperNotCalledException;
87import android.util.TypedValue;
88import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
89import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
90import android.view.AccessibilityIterators.TextSegmentIterator;
91import android.view.AccessibilityIterators.WordTextSegmentIterator;
92import android.view.ContextMenu.ContextMenuInfo;
93import android.view.accessibility.AccessibilityEvent;
94import android.view.accessibility.AccessibilityEventSource;
95import android.view.accessibility.AccessibilityManager;
96import android.view.accessibility.AccessibilityNodeInfo;
97import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
98import android.view.accessibility.AccessibilityNodeProvider;
99import android.view.accessibility.AccessibilityWindowInfo;
100import android.view.animation.Animation;
101import android.view.animation.AnimationUtils;
102import android.view.animation.Transformation;
103import android.view.autofill.AutofillManager;
104import android.view.autofill.AutofillValue;
105import android.view.inputmethod.EditorInfo;
106import android.view.inputmethod.InputConnection;
107import android.view.inputmethod.InputMethodManager;
108import android.widget.Checkable;
109import android.widget.FrameLayout;
110import android.widget.ScrollBarDrawable;
111
112import com.android.internal.R;
113import com.android.internal.view.TooltipPopup;
114import com.android.internal.view.menu.MenuBuilder;
115import com.android.internal.widget.ScrollBarUtils;
116
117import com.google.android.collect.Lists;
118import com.google.android.collect.Maps;
119
120import java.lang.annotation.Retention;
121import java.lang.annotation.RetentionPolicy;
122import java.lang.ref.WeakReference;
123import java.lang.reflect.Field;
124import java.lang.reflect.InvocationTargetException;
125import java.lang.reflect.Method;
126import java.lang.reflect.Modifier;
127import java.util.ArrayList;
128import java.util.Arrays;
129import java.util.Collection;
130import java.util.Collections;
131import java.util.HashMap;
132import java.util.List;
133import java.util.Locale;
134import java.util.Map;
135import java.util.concurrent.CopyOnWriteArrayList;
136import java.util.concurrent.atomic.AtomicInteger;
137import java.util.function.Predicate;
138
139/**
140 * <p>
141 * This class represents the basic building block for user interface components. A View
142 * occupies a rectangular area on the screen and is responsible for drawing and
143 * event handling. View is the base class for <em>widgets</em>, which are
144 * used to create interactive UI components (buttons, text fields, etc.). The
145 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
146 * are invisible containers that hold other Views (or other ViewGroups) and define
147 * their layout properties.
148 * </p>
149 *
150 * <div class="special reference">
151 * <h3>Developer Guides</h3>
152 * <p>For information about using this class to develop your application's user interface,
153 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
154 * </div>
155 *
156 * <a name="Using"></a>
157 * <h3>Using Views</h3>
158 * <p>
159 * All of the views in a window are arranged in a single tree. You can add views
160 * either from code or by specifying a tree of views in one or more XML layout
161 * files. There are many specialized subclasses of views that act as controls or
162 * are capable of displaying text, images, or other content.
163 * </p>
164 * <p>
165 * Once you have created a tree of views, there are typically a few types of
166 * common operations you may wish to perform:
167 * <ul>
168 * <li><strong>Set properties:</strong> for example setting the text of a
169 * {@link android.widget.TextView}. The available properties and the methods
170 * that set them will vary among the different subclasses of views. Note that
171 * properties that are known at build time can be set in the XML layout
172 * files.</li>
173 * <li><strong>Set focus:</strong> The framework will handle moving focus in
174 * response to user input. To force focus to a specific view, call
175 * {@link #requestFocus}.</li>
176 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
177 * that will be notified when something interesting happens to the view. For
178 * example, all views will let you set a listener to be notified when the view
179 * gains or loses focus. You can register such a listener using
180 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
181 * Other view subclasses offer more specialized listeners. For example, a Button
182 * exposes a listener to notify clients when the button is clicked.</li>
183 * <li><strong>Set visibility:</strong> You can hide or show views using
184 * {@link #setVisibility(int)}.</li>
185 * </ul>
186 * </p>
187 * <p><em>
188 * Note: The Android framework is responsible for measuring, laying out and
189 * drawing views. You should not call methods that perform these actions on
190 * views yourself unless you are actually implementing a
191 * {@link android.view.ViewGroup}.
192 * </em></p>
193 *
194 * <a name="Lifecycle"></a>
195 * <h3>Implementing a Custom View</h3>
196 *
197 * <p>
198 * To implement a custom view, you will usually begin by providing overrides for
199 * some of the standard methods that the framework calls on all views. You do
200 * not need to override all of these methods. In fact, you can start by just
201 * overriding {@link #onDraw(android.graphics.Canvas)}.
202 * <table border="2" width="85%" align="center" cellpadding="5">
203 *     <thead>
204 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
205 *     </thead>
206 *
207 *     <tbody>
208 *     <tr>
209 *         <td rowspan="2">Creation</td>
210 *         <td>Constructors</td>
211 *         <td>There is a form of the constructor that are called when the view
212 *         is created from code and a form that is called when the view is
213 *         inflated from a layout file. The second form should parse and apply
214 *         any attributes defined in the layout file.
215 *         </td>
216 *     </tr>
217 *     <tr>
218 *         <td><code>{@link #onFinishInflate()}</code></td>
219 *         <td>Called after a view and all of its children has been inflated
220 *         from XML.</td>
221 *     </tr>
222 *
223 *     <tr>
224 *         <td rowspan="3">Layout</td>
225 *         <td><code>{@link #onMeasure(int, int)}</code></td>
226 *         <td>Called to determine the size requirements for this view and all
227 *         of its children.
228 *         </td>
229 *     </tr>
230 *     <tr>
231 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
232 *         <td>Called when this view should assign a size and position to all
233 *         of its children.
234 *         </td>
235 *     </tr>
236 *     <tr>
237 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
238 *         <td>Called when the size of this view has changed.
239 *         </td>
240 *     </tr>
241 *
242 *     <tr>
243 *         <td>Drawing</td>
244 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
245 *         <td>Called when the view should render its content.
246 *         </td>
247 *     </tr>
248 *
249 *     <tr>
250 *         <td rowspan="4">Event processing</td>
251 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
252 *         <td>Called when a new hardware key event occurs.
253 *         </td>
254 *     </tr>
255 *     <tr>
256 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
257 *         <td>Called when a hardware key up event occurs.
258 *         </td>
259 *     </tr>
260 *     <tr>
261 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
262 *         <td>Called when a trackball motion event occurs.
263 *         </td>
264 *     </tr>
265 *     <tr>
266 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
267 *         <td>Called when a touch screen motion event occurs.
268 *         </td>
269 *     </tr>
270 *
271 *     <tr>
272 *         <td rowspan="2">Focus</td>
273 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
274 *         <td>Called when the view gains or loses focus.
275 *         </td>
276 *     </tr>
277 *
278 *     <tr>
279 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
280 *         <td>Called when the window containing the view gains or loses focus.
281 *         </td>
282 *     </tr>
283 *
284 *     <tr>
285 *         <td rowspan="3">Attaching</td>
286 *         <td><code>{@link #onAttachedToWindow()}</code></td>
287 *         <td>Called when the view is attached to a window.
288 *         </td>
289 *     </tr>
290 *
291 *     <tr>
292 *         <td><code>{@link #onDetachedFromWindow}</code></td>
293 *         <td>Called when the view is detached from its window.
294 *         </td>
295 *     </tr>
296 *
297 *     <tr>
298 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
299 *         <td>Called when the visibility of the window containing the view
300 *         has changed.
301 *         </td>
302 *     </tr>
303 *     </tbody>
304 *
305 * </table>
306 * </p>
307 *
308 * <a name="IDs"></a>
309 * <h3>IDs</h3>
310 * Views may have an integer id associated with them. These ids are typically
311 * assigned in the layout XML files, and are used to find specific views within
312 * the view tree. A common pattern is to:
313 * <ul>
314 * <li>Define a Button in the layout file and assign it a unique ID.
315 * <pre>
316 * &lt;Button
317 *     android:id="@+id/my_button"
318 *     android:layout_width="wrap_content"
319 *     android:layout_height="wrap_content"
320 *     android:text="@string/my_button_text"/&gt;
321 * </pre></li>
322 * <li>From the onCreate method of an Activity, find the Button
323 * <pre class="prettyprint">
324 *      Button myButton = findViewById(R.id.my_button);
325 * </pre></li>
326 * </ul>
327 * <p>
328 * View IDs need not be unique throughout the tree, but it is good practice to
329 * ensure that they are at least unique within the part of the tree you are
330 * searching.
331 * </p>
332 *
333 * <a name="Position"></a>
334 * <h3>Position</h3>
335 * <p>
336 * The geometry of a view is that of a rectangle. A view has a location,
337 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
338 * two dimensions, expressed as a width and a height. The unit for location
339 * and dimensions is the pixel.
340 * </p>
341 *
342 * <p>
343 * It is possible to retrieve the location of a view by invoking the methods
344 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
345 * coordinate of the rectangle representing the view. The latter returns the
346 * top, or Y, coordinate of the rectangle representing the view. These methods
347 * both return the location of the view relative to its parent. For instance,
348 * when getLeft() returns 20, that means the view is located 20 pixels to the
349 * right of the left edge of its direct parent.
350 * </p>
351 *
352 * <p>
353 * In addition, several convenience methods are offered to avoid unnecessary
354 * computations, namely {@link #getRight()} and {@link #getBottom()}.
355 * These methods return the coordinates of the right and bottom edges of the
356 * rectangle representing the view. For instance, calling {@link #getRight()}
357 * is similar to the following computation: <code>getLeft() + getWidth()</code>
358 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
359 * </p>
360 *
361 * <a name="SizePaddingMargins"></a>
362 * <h3>Size, padding and margins</h3>
363 * <p>
364 * The size of a view is expressed with a width and a height. A view actually
365 * possess two pairs of width and height values.
366 * </p>
367 *
368 * <p>
369 * The first pair is known as <em>measured width</em> and
370 * <em>measured height</em>. These dimensions define how big a view wants to be
371 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
372 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
373 * and {@link #getMeasuredHeight()}.
374 * </p>
375 *
376 * <p>
377 * The second pair is simply known as <em>width</em> and <em>height</em>, or
378 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
379 * dimensions define the actual size of the view on screen, at drawing time and
380 * after layout. These values may, but do not have to, be different from the
381 * measured width and height. The width and height can be obtained by calling
382 * {@link #getWidth()} and {@link #getHeight()}.
383 * </p>
384 *
385 * <p>
386 * To measure its dimensions, a view takes into account its padding. The padding
387 * is expressed in pixels for the left, top, right and bottom parts of the view.
388 * Padding can be used to offset the content of the view by a specific amount of
389 * pixels. For instance, a left padding of 2 will push the view's content by
390 * 2 pixels to the right of the left edge. Padding can be set using the
391 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
392 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
393 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
394 * {@link #getPaddingEnd()}.
395 * </p>
396 *
397 * <p>
398 * Even though a view can define a padding, it does not provide any support for
399 * margins. However, view groups provide such a support. Refer to
400 * {@link android.view.ViewGroup} and
401 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
402 * </p>
403 *
404 * <a name="Layout"></a>
405 * <h3>Layout</h3>
406 * <p>
407 * Layout is a two pass process: a measure pass and a layout pass. The measuring
408 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
409 * of the view tree. Each view pushes dimension specifications down the tree
410 * during the recursion. At the end of the measure pass, every view has stored
411 * its measurements. The second pass happens in
412 * {@link #layout(int,int,int,int)} and is also top-down. During
413 * this pass each parent is responsible for positioning all of its children
414 * using the sizes computed in the measure pass.
415 * </p>
416 *
417 * <p>
418 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
419 * {@link #getMeasuredHeight()} values must be set, along with those for all of
420 * that view's descendants. A view's measured width and measured height values
421 * must respect the constraints imposed by the view's parents. This guarantees
422 * that at the end of the measure pass, all parents accept all of their
423 * children's measurements. A parent view may call measure() more than once on
424 * its children. For example, the parent may measure each child once with
425 * unspecified dimensions to find out how big they want to be, then call
426 * measure() on them again with actual numbers if the sum of all the children's
427 * unconstrained sizes is too big or too small.
428 * </p>
429 *
430 * <p>
431 * The measure pass uses two classes to communicate dimensions. The
432 * {@link MeasureSpec} class is used by views to tell their parents how they
433 * want to be measured and positioned. The base LayoutParams class just
434 * describes how big the view wants to be for both width and height. For each
435 * dimension, it can specify one of:
436 * <ul>
437 * <li> an exact number
438 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
439 * (minus padding)
440 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
441 * enclose its content (plus padding).
442 * </ul>
443 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
444 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
445 * an X and Y value.
446 * </p>
447 *
448 * <p>
449 * MeasureSpecs are used to push requirements down the tree from parent to
450 * child. A MeasureSpec can be in one of three modes:
451 * <ul>
452 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
453 * of a child view. For example, a LinearLayout may call measure() on its child
454 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
455 * tall the child view wants to be given a width of 240 pixels.
456 * <li>EXACTLY: This is used by the parent to impose an exact size on the
457 * child. The child must use this size, and guarantee that all of its
458 * descendants will fit within this size.
459 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
460 * child. The child must guarantee that it and all of its descendants will fit
461 * within this size.
462 * </ul>
463 * </p>
464 *
465 * <p>
466 * To initiate a layout, call {@link #requestLayout}. This method is typically
467 * called by a view on itself when it believes that is can no longer fit within
468 * its current bounds.
469 * </p>
470 *
471 * <a name="Drawing"></a>
472 * <h3>Drawing</h3>
473 * <p>
474 * Drawing is handled by walking the tree and recording the drawing commands of
475 * any View that needs to update. After this, the drawing commands of the
476 * entire tree are issued to screen, clipped to the newly damaged area.
477 * </p>
478 *
479 * <p>
480 * The tree is largely recorded and drawn in order, with parents drawn before
481 * (i.e., behind) their children, with siblings drawn in the order they appear
482 * in the tree. If you set a background drawable for a View, then the View will
483 * draw it before calling back to its <code>onDraw()</code> method. The child
484 * drawing order can be overridden with
485 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
486 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
487 * </p>
488 *
489 * <p>
490 * To force a view to draw, call {@link #invalidate()}.
491 * </p>
492 *
493 * <a name="EventHandlingThreading"></a>
494 * <h3>Event Handling and Threading</h3>
495 * <p>
496 * The basic cycle of a view is as follows:
497 * <ol>
498 * <li>An event comes in and is dispatched to the appropriate view. The view
499 * handles the event and notifies any listeners.</li>
500 * <li>If in the course of processing the event, the view's bounds may need
501 * to be changed, the view will call {@link #requestLayout()}.</li>
502 * <li>Similarly, if in the course of processing the event the view's appearance
503 * may need to be changed, the view will call {@link #invalidate()}.</li>
504 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
505 * the framework will take care of measuring, laying out, and drawing the tree
506 * as appropriate.</li>
507 * </ol>
508 * </p>
509 *
510 * <p><em>Note: The entire view tree is single threaded. You must always be on
511 * the UI thread when calling any method on any view.</em>
512 * If you are doing work on other threads and want to update the state of a view
513 * from that thread, you should use a {@link Handler}.
514 * </p>
515 *
516 * <a name="FocusHandling"></a>
517 * <h3>Focus Handling</h3>
518 * <p>
519 * The framework will handle routine focus movement in response to user input.
520 * This includes changing the focus as views are removed or hidden, or as new
521 * views become available. Views indicate their willingness to take focus
522 * through the {@link #isFocusable} method. To change whether a view can take
523 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
524 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
525 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
526 * </p>
527 * <p>
528 * Focus movement is based on an algorithm which finds the nearest neighbor in a
529 * given direction. In rare cases, the default algorithm may not match the
530 * intended behavior of the developer. In these situations, you can provide
531 * explicit overrides by using these XML attributes in the layout file:
532 * <pre>
533 * nextFocusDown
534 * nextFocusLeft
535 * nextFocusRight
536 * nextFocusUp
537 * </pre>
538 * </p>
539 *
540 *
541 * <p>
542 * To get a particular view to take focus, call {@link #requestFocus()}.
543 * </p>
544 *
545 * <a name="TouchMode"></a>
546 * <h3>Touch Mode</h3>
547 * <p>
548 * When a user is navigating a user interface via directional keys such as a D-pad, it is
549 * necessary to give focus to actionable items such as buttons so the user can see
550 * what will take input.  If the device has touch capabilities, however, and the user
551 * begins interacting with the interface by touching it, it is no longer necessary to
552 * always highlight, or give focus to, a particular view.  This motivates a mode
553 * for interaction named 'touch mode'.
554 * </p>
555 * <p>
556 * For a touch capable device, once the user touches the screen, the device
557 * will enter touch mode.  From this point onward, only views for which
558 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
559 * Other views that are touchable, like buttons, will not take focus when touched; they will
560 * only fire the on click listeners.
561 * </p>
562 * <p>
563 * Any time a user hits a directional key, such as a D-pad direction, the view device will
564 * exit touch mode, and find a view to take focus, so that the user may resume interacting
565 * with the user interface without touching the screen again.
566 * </p>
567 * <p>
568 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
569 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
570 * </p>
571 *
572 * <a name="Scrolling"></a>
573 * <h3>Scrolling</h3>
574 * <p>
575 * The framework provides basic support for views that wish to internally
576 * scroll their content. This includes keeping track of the X and Y scroll
577 * offset as well as mechanisms for drawing scrollbars. See
578 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
579 * {@link #awakenScrollBars()} for more details.
580 * </p>
581 *
582 * <a name="Tags"></a>
583 * <h3>Tags</h3>
584 * <p>
585 * Unlike IDs, tags are not used to identify views. Tags are essentially an
586 * extra piece of information that can be associated with a view. They are most
587 * often used as a convenience to store data related to views in the views
588 * themselves rather than by putting them in a separate structure.
589 * </p>
590 * <p>
591 * Tags may be specified with character sequence values in layout XML as either
592 * a single tag using the {@link android.R.styleable#View_tag android:tag}
593 * attribute or multiple tags using the {@code <tag>} child element:
594 * <pre>
595 *     &ltView ...
596 *           android:tag="@string/mytag_value" /&gt;
597 *     &ltView ...&gt;
598 *         &lttag android:id="@+id/mytag"
599 *              android:value="@string/mytag_value" /&gt;
600 *     &lt/View>
601 * </pre>
602 * </p>
603 * <p>
604 * Tags may also be specified with arbitrary objects from code using
605 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
606 * </p>
607 *
608 * <a name="Themes"></a>
609 * <h3>Themes</h3>
610 * <p>
611 * By default, Views are created using the theme of the Context object supplied
612 * to their constructor; however, a different theme may be specified by using
613 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
614 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
615 * code.
616 * </p>
617 * <p>
618 * When the {@link android.R.styleable#View_theme android:theme} attribute is
619 * used in XML, the specified theme is applied on top of the inflation
620 * context's theme (see {@link LayoutInflater}) and used for the view itself as
621 * well as any child elements.
622 * </p>
623 * <p>
624 * In the following example, both views will be created using the Material dark
625 * color scheme; however, because an overlay theme is used which only defines a
626 * subset of attributes, the value of
627 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
628 * the inflation context's theme (e.g. the Activity theme) will be preserved.
629 * <pre>
630 *     &ltLinearLayout
631 *             ...
632 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
633 *         &ltView ...&gt;
634 *     &lt/LinearLayout&gt;
635 * </pre>
636 * </p>
637 *
638 * <a name="Properties"></a>
639 * <h3>Properties</h3>
640 * <p>
641 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
642 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
643 * available both in the {@link Property} form as well as in similarly-named setter/getter
644 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
645 * be used to set persistent state associated with these rendering-related properties on the view.
646 * The properties and methods can also be used in conjunction with
647 * {@link android.animation.Animator Animator}-based animations, described more in the
648 * <a href="#Animation">Animation</a> section.
649 * </p>
650 *
651 * <a name="Animation"></a>
652 * <h3>Animation</h3>
653 * <p>
654 * Starting with Android 3.0, the preferred way of animating views is to use the
655 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
656 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
657 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
658 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
659 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
660 * makes animating these View properties particularly easy and efficient.
661 * </p>
662 * <p>
663 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
664 * You can attach an {@link Animation} object to a view using
665 * {@link #setAnimation(Animation)} or
666 * {@link #startAnimation(Animation)}. The animation can alter the scale,
667 * rotation, translation and alpha of a view over time. If the animation is
668 * attached to a view that has children, the animation will affect the entire
669 * subtree rooted by that node. When an animation is started, the framework will
670 * take care of redrawing the appropriate views until the animation completes.
671 * </p>
672 *
673 * <a name="Security"></a>
674 * <h3>Security</h3>
675 * <p>
676 * Sometimes it is essential that an application be able to verify that an action
677 * is being performed with the full knowledge and consent of the user, such as
678 * granting a permission request, making a purchase or clicking on an advertisement.
679 * Unfortunately, a malicious application could try to spoof the user into
680 * performing these actions, unaware, by concealing the intended purpose of the view.
681 * As a remedy, the framework offers a touch filtering mechanism that can be used to
682 * improve the security of views that provide access to sensitive functionality.
683 * </p><p>
684 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
685 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
686 * will discard touches that are received whenever the view's window is obscured by
687 * another visible window.  As a result, the view will not receive touches whenever a
688 * toast, dialog or other window appears above the view's window.
689 * </p><p>
690 * For more fine-grained control over security, consider overriding the
691 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
692 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
693 * </p>
694 *
695 * @attr ref android.R.styleable#View_alpha
696 * @attr ref android.R.styleable#View_background
697 * @attr ref android.R.styleable#View_clickable
698 * @attr ref android.R.styleable#View_contentDescription
699 * @attr ref android.R.styleable#View_drawingCacheQuality
700 * @attr ref android.R.styleable#View_duplicateParentState
701 * @attr ref android.R.styleable#View_id
702 * @attr ref android.R.styleable#View_requiresFadingEdge
703 * @attr ref android.R.styleable#View_fadeScrollbars
704 * @attr ref android.R.styleable#View_fadingEdgeLength
705 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
706 * @attr ref android.R.styleable#View_fitsSystemWindows
707 * @attr ref android.R.styleable#View_isScrollContainer
708 * @attr ref android.R.styleable#View_focusable
709 * @attr ref android.R.styleable#View_focusableInTouchMode
710 * @attr ref android.R.styleable#View_focusedByDefault
711 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
712 * @attr ref android.R.styleable#View_keepScreenOn
713 * @attr ref android.R.styleable#View_keyboardNavigationCluster
714 * @attr ref android.R.styleable#View_layerType
715 * @attr ref android.R.styleable#View_layoutDirection
716 * @attr ref android.R.styleable#View_longClickable
717 * @attr ref android.R.styleable#View_minHeight
718 * @attr ref android.R.styleable#View_minWidth
719 * @attr ref android.R.styleable#View_nextClusterForward
720 * @attr ref android.R.styleable#View_nextFocusDown
721 * @attr ref android.R.styleable#View_nextFocusLeft
722 * @attr ref android.R.styleable#View_nextFocusRight
723 * @attr ref android.R.styleable#View_nextFocusUp
724 * @attr ref android.R.styleable#View_onClick
725 * @attr ref android.R.styleable#View_padding
726 * @attr ref android.R.styleable#View_paddingBottom
727 * @attr ref android.R.styleable#View_paddingLeft
728 * @attr ref android.R.styleable#View_paddingRight
729 * @attr ref android.R.styleable#View_paddingTop
730 * @attr ref android.R.styleable#View_paddingStart
731 * @attr ref android.R.styleable#View_paddingEnd
732 * @attr ref android.R.styleable#View_saveEnabled
733 * @attr ref android.R.styleable#View_rotation
734 * @attr ref android.R.styleable#View_rotationX
735 * @attr ref android.R.styleable#View_rotationY
736 * @attr ref android.R.styleable#View_scaleX
737 * @attr ref android.R.styleable#View_scaleY
738 * @attr ref android.R.styleable#View_scrollX
739 * @attr ref android.R.styleable#View_scrollY
740 * @attr ref android.R.styleable#View_scrollbarSize
741 * @attr ref android.R.styleable#View_scrollbarStyle
742 * @attr ref android.R.styleable#View_scrollbars
743 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
744 * @attr ref android.R.styleable#View_scrollbarFadeDuration
745 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
746 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
747 * @attr ref android.R.styleable#View_scrollbarThumbVertical
748 * @attr ref android.R.styleable#View_scrollbarTrackVertical
749 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
750 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
751 * @attr ref android.R.styleable#View_stateListAnimator
752 * @attr ref android.R.styleable#View_transitionName
753 * @attr ref android.R.styleable#View_soundEffectsEnabled
754 * @attr ref android.R.styleable#View_tag
755 * @attr ref android.R.styleable#View_textAlignment
756 * @attr ref android.R.styleable#View_textDirection
757 * @attr ref android.R.styleable#View_transformPivotX
758 * @attr ref android.R.styleable#View_transformPivotY
759 * @attr ref android.R.styleable#View_translationX
760 * @attr ref android.R.styleable#View_translationY
761 * @attr ref android.R.styleable#View_translationZ
762 * @attr ref android.R.styleable#View_visibility
763 * @attr ref android.R.styleable#View_theme
764 *
765 * @see android.view.ViewGroup
766 */
767@UiThread
768public class View implements Drawable.Callback, KeyEvent.Callback,
769        AccessibilityEventSource {
770    private static final boolean DBG = false;
771
772    /** @hide */
773    public static boolean DEBUG_DRAW = false;
774
775    /**
776     * The logging tag used by this class with android.util.Log.
777     */
778    protected static final String VIEW_LOG_TAG = "View";
779
780    /**
781     * When set to true, apps will draw debugging information about their layouts.
782     *
783     * @hide
784     */
785    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
786
787    /**
788     * When set to true, this view will save its attribute data.
789     *
790     * @hide
791     */
792    public static boolean mDebugViewAttributes = false;
793
794    /**
795     * Used to mark a View that has no ID.
796     */
797    public static final int NO_ID = -1;
798
799    /**
800     * Last ID that is given to Views that are no part of activities.
801     *
802     * {@hide}
803     */
804    public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
805
806    /**
807     * Signals that compatibility booleans have been initialized according to
808     * target SDK versions.
809     */
810    private static boolean sCompatibilityDone = false;
811
812    /**
813     * Use the old (broken) way of building MeasureSpecs.
814     */
815    private static boolean sUseBrokenMakeMeasureSpec = false;
816
817    /**
818     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
819     */
820    static boolean sUseZeroUnspecifiedMeasureSpec = false;
821
822    /**
823     * Ignore any optimizations using the measure cache.
824     */
825    private static boolean sIgnoreMeasureCache = false;
826
827    /**
828     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
829     */
830    private static boolean sAlwaysRemeasureExactly = false;
831
832    /**
833     * Relax constraints around whether setLayoutParams() must be called after
834     * modifying the layout params.
835     */
836    private static boolean sLayoutParamsAlwaysChanged = false;
837
838    /**
839     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
840     * without throwing
841     */
842    static boolean sTextureViewIgnoresDrawableSetters = false;
843
844    /**
845     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
846     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
847     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
848     * check is implemented for backwards compatibility.
849     *
850     * {@hide}
851     */
852    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
853
854    /**
855     * Prior to N, when drag enters into child of a view that has already received an
856     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
857     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
858     * false from its event handler for these events.
859     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
860     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
861     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
862     */
863    static boolean sCascadedDragDrop;
864
865    /**
866     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
867     * to determine things like whether or not to permit item click events. We can't break
868     * apps that do this just because more things (clickable things) are now auto-focusable
869     * and they would get different results, so give old behavior to old apps.
870     */
871    static boolean sHasFocusableExcludeAutoFocusable;
872
873    /**
874     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
875     * made focusable by default. As a result, apps could (incorrectly) change the clickable
876     * setting of views off the UI thread. Now that clickable can effect the focusable state,
877     * changing the clickable attribute off the UI thread will cause an exception (since changing
878     * the focusable state checks). In order to prevent apps from crashing, we will handle this
879     * specific case and just not notify parents on new focusables resulting from marking views
880     * clickable from outside the UI thread.
881     */
882    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
883
884    /** @hide */
885    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
886    @Retention(RetentionPolicy.SOURCE)
887    public @interface Focusable {}
888
889    /**
890     * This view does not want keystrokes.
891     * <p>
892     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
893     * android:focusable}.
894     */
895    public static final int NOT_FOCUSABLE = 0x00000000;
896
897    /**
898     * This view wants keystrokes.
899     * <p>
900     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
901     * android:focusable}.
902     */
903    public static final int FOCUSABLE = 0x00000001;
904
905    /**
906     * This view determines focusability automatically. This is the default.
907     * <p>
908     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
909     * android:focusable}.
910     */
911    public static final int FOCUSABLE_AUTO = 0x00000010;
912
913    /**
914     * Mask for use with setFlags indicating bits used for focus.
915     */
916    private static final int FOCUSABLE_MASK = 0x00000011;
917
918    /**
919     * This view will adjust its padding to fit sytem windows (e.g. status bar)
920     */
921    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
922
923    /** @hide */
924    @IntDef({VISIBLE, INVISIBLE, GONE})
925    @Retention(RetentionPolicy.SOURCE)
926    public @interface Visibility {}
927
928    /**
929     * This view is visible.
930     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
931     * android:visibility}.
932     */
933    public static final int VISIBLE = 0x00000000;
934
935    /**
936     * This view is invisible, but it still takes up space for layout purposes.
937     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
938     * android:visibility}.
939     */
940    public static final int INVISIBLE = 0x00000004;
941
942    /**
943     * This view is invisible, and it doesn't take any space for layout
944     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
945     * android:visibility}.
946     */
947    public static final int GONE = 0x00000008;
948
949    /**
950     * Mask for use with setFlags indicating bits used for visibility.
951     * {@hide}
952     */
953    static final int VISIBILITY_MASK = 0x0000000C;
954
955    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
956
957    /**
958     * This view contains an email address.
959     *
960     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_EMAIL_ADDRESS}"
961     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
962     */
963    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
964
965    /**
966     * The view contains a real name.
967     *
968     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_NAME}" to
969     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
970     */
971    public static final String AUTOFILL_HINT_NAME = "name";
972
973    /**
974     * The view contains a user name.
975     *
976     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_USERNAME}" to
977     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
978     */
979    public static final String AUTOFILL_HINT_USERNAME = "username";
980
981    /**
982     * The view contains a password.
983     *
984     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PASSWORD}" to
985     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
986     */
987    public static final String AUTOFILL_HINT_PASSWORD = "password";
988
989    /**
990     * The view contains a phone number.
991     *
992     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PHONE}" to
993     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
994     */
995    public static final String AUTOFILL_HINT_PHONE = "phone";
996
997    /**
998     * The view contains a postal address.
999     *
1000     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_ADDRESS}"
1001     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1002     */
1003    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1004
1005    /**
1006     * The view contains a postal code.
1007     *
1008     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_CODE}" to
1009     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1010     */
1011    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1012
1013    /**
1014     * The view contains a credit card number.
1015     *
1016     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1017     * #AUTOFILL_HINT_CREDIT_CARD_NUMBER}" to <a href="#attr_android:autofillHint"> {@code
1018     * android:autofillHint}.
1019     */
1020    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1021
1022    /**
1023     * The view contains a credit card security code.
1024     *
1025     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1026     * #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}" to <a href="#attr_android:autofillHint"> {@code
1027     * android:autofillHint}.
1028     */
1029    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1030
1031    /**
1032     * The view contains a credit card expiration date.
1033     *
1034     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1035     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}" to <a href="#attr_android:autofillHint"> {@code
1036     * android:autofillHint}.
1037     */
1038    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1039            "creditCardExpirationDate";
1040
1041    /**
1042     * The view contains the month a credit card expires.
1043     *
1044     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1045     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}" to <a href="#attr_android:autofillHint"> {@code
1046     * android:autofillHint}.
1047     */
1048    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1049            "creditCardExpirationMonth";
1050
1051    /**
1052     * The view contains the year a credit card expires.
1053     *
1054     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1055     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}" to <a href="#attr_android:autofillHint"> {@code
1056     * android:autofillHint}.
1057     */
1058    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1059            "creditCardExpirationYear";
1060
1061    /**
1062     * The view contains the day a credit card expires.
1063     *
1064     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1065     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}" to <a href="#attr_android:autofillHint"> {@code
1066     * android:autofillHint}.
1067     */
1068    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1069
1070    /**
1071     * Hintd for the autofill services that describes the content of the view.
1072     */
1073    private @Nullable String[] mAutofillHints;
1074
1075    /** @hide */
1076    @IntDef({
1077            AUTOFILL_TYPE_NONE,
1078            AUTOFILL_TYPE_TEXT,
1079            AUTOFILL_TYPE_TOGGLE,
1080            AUTOFILL_TYPE_LIST,
1081            AUTOFILL_TYPE_DATE
1082    })
1083    @Retention(RetentionPolicy.SOURCE)
1084    public @interface AutofillType {}
1085
1086    /**
1087     * Autofill type for views that cannot be autofilled.
1088     */
1089    public static final int AUTOFILL_TYPE_NONE = 0;
1090
1091    /**
1092     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1093     *
1094     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1095     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1096     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1097     */
1098    public static final int AUTOFILL_TYPE_TEXT = 1;
1099
1100    /**
1101     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1102     *
1103     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1104     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1105     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1106     */
1107    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1108
1109    /**
1110     * Autofill type for a selection list field, which is filled by an {@code int}
1111     * representing the element index inside the list (starting at {@code 0}).
1112     *
1113     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1114     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1115     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1116     *
1117     * <p>The available options in the selection list are typically provided by
1118     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1119     */
1120    public static final int AUTOFILL_TYPE_LIST = 3;
1121
1122
1123    /**
1124     * Autofill type for a field that contains a date, which is represented by a long representing
1125     * the number of milliseconds since the standard base time known as "the epoch", namely
1126     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1127     *
1128     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1129     * {@link AutofillValue#forDate(long)}, and the values passed to
1130     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1131     */
1132    public static final int AUTOFILL_TYPE_DATE = 4;
1133
1134    /** @hide */
1135    @IntDef({
1136            IMPORTANT_FOR_AUTOFILL_AUTO,
1137            IMPORTANT_FOR_AUTOFILL_YES,
1138            IMPORTANT_FOR_AUTOFILL_NO,
1139            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1140            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1141    })
1142    @Retention(RetentionPolicy.SOURCE)
1143    public @interface AutofillImportance {}
1144
1145    /**
1146     * Automatically determine whether a view is important for autofill.
1147     */
1148    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1149
1150    /**
1151     * The view is important for autofill, and its children (if any) will be traversed.
1152     */
1153    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1154
1155    /**
1156     * The view is not important for autofill, and its children (if any) will be traversed.
1157     */
1158    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1159
1160    /**
1161     * The view is important for autofill, but its children (if any) will not be traversed.
1162     */
1163    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1164
1165    /**
1166     * The view is not important for autofill, and its children (if any) will not be traversed.
1167     */
1168    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1169
1170    /**
1171     * This view is enabled. Interpretation varies by subclass.
1172     * Use with ENABLED_MASK when calling setFlags.
1173     * {@hide}
1174     */
1175    static final int ENABLED = 0x00000000;
1176
1177    /**
1178     * This view is disabled. Interpretation varies by subclass.
1179     * Use with ENABLED_MASK when calling setFlags.
1180     * {@hide}
1181     */
1182    static final int DISABLED = 0x00000020;
1183
1184   /**
1185    * Mask for use with setFlags indicating bits used for indicating whether
1186    * this view is enabled
1187    * {@hide}
1188    */
1189    static final int ENABLED_MASK = 0x00000020;
1190
1191    /**
1192     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1193     * called and further optimizations will be performed. It is okay to have
1194     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1195     * {@hide}
1196     */
1197    static final int WILL_NOT_DRAW = 0x00000080;
1198
1199    /**
1200     * Mask for use with setFlags indicating bits used for indicating whether
1201     * this view is will draw
1202     * {@hide}
1203     */
1204    static final int DRAW_MASK = 0x00000080;
1205
1206    /**
1207     * <p>This view doesn't show scrollbars.</p>
1208     * {@hide}
1209     */
1210    static final int SCROLLBARS_NONE = 0x00000000;
1211
1212    /**
1213     * <p>This view shows horizontal scrollbars.</p>
1214     * {@hide}
1215     */
1216    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1217
1218    /**
1219     * <p>This view shows vertical scrollbars.</p>
1220     * {@hide}
1221     */
1222    static final int SCROLLBARS_VERTICAL = 0x00000200;
1223
1224    /**
1225     * <p>Mask for use with setFlags indicating bits used for indicating which
1226     * scrollbars are enabled.</p>
1227     * {@hide}
1228     */
1229    static final int SCROLLBARS_MASK = 0x00000300;
1230
1231    /**
1232     * Indicates that the view should filter touches when its window is obscured.
1233     * Refer to the class comments for more information about this security feature.
1234     * {@hide}
1235     */
1236    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1237
1238    /**
1239     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1240     * that they are optional and should be skipped if the window has
1241     * requested system UI flags that ignore those insets for layout.
1242     */
1243    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1244
1245    /**
1246     * <p>This view doesn't show fading edges.</p>
1247     * {@hide}
1248     */
1249    static final int FADING_EDGE_NONE = 0x00000000;
1250
1251    /**
1252     * <p>This view shows horizontal fading edges.</p>
1253     * {@hide}
1254     */
1255    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1256
1257    /**
1258     * <p>This view shows vertical fading edges.</p>
1259     * {@hide}
1260     */
1261    static final int FADING_EDGE_VERTICAL = 0x00002000;
1262
1263    /**
1264     * <p>Mask for use with setFlags indicating bits used for indicating which
1265     * fading edges are enabled.</p>
1266     * {@hide}
1267     */
1268    static final int FADING_EDGE_MASK = 0x00003000;
1269
1270    /**
1271     * <p>Indicates this view can be clicked. When clickable, a View reacts
1272     * to clicks by notifying the OnClickListener.<p>
1273     * {@hide}
1274     */
1275    static final int CLICKABLE = 0x00004000;
1276
1277    /**
1278     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1279     * {@hide}
1280     */
1281    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1282
1283    /**
1284     * <p>Indicates that no icicle should be saved for this view.<p>
1285     * {@hide}
1286     */
1287    static final int SAVE_DISABLED = 0x000010000;
1288
1289    /**
1290     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1291     * property.</p>
1292     * {@hide}
1293     */
1294    static final int SAVE_DISABLED_MASK = 0x000010000;
1295
1296    /**
1297     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1298     * {@hide}
1299     */
1300    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1301
1302    /**
1303     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1304     * {@hide}
1305     */
1306    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1307
1308    /** @hide */
1309    @Retention(RetentionPolicy.SOURCE)
1310    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1311    public @interface DrawingCacheQuality {}
1312
1313    /**
1314     * <p>Enables low quality mode for the drawing cache.</p>
1315     */
1316    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1317
1318    /**
1319     * <p>Enables high quality mode for the drawing cache.</p>
1320     */
1321    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1322
1323    /**
1324     * <p>Enables automatic quality mode for the drawing cache.</p>
1325     */
1326    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1327
1328    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1329            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1330    };
1331
1332    /**
1333     * <p>Mask for use with setFlags indicating bits used for the cache
1334     * quality property.</p>
1335     * {@hide}
1336     */
1337    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1338
1339    /**
1340     * <p>
1341     * Indicates this view can be long clicked. When long clickable, a View
1342     * reacts to long clicks by notifying the OnLongClickListener or showing a
1343     * context menu.
1344     * </p>
1345     * {@hide}
1346     */
1347    static final int LONG_CLICKABLE = 0x00200000;
1348
1349    /**
1350     * <p>Indicates that this view gets its drawable states from its direct parent
1351     * and ignores its original internal states.</p>
1352     *
1353     * @hide
1354     */
1355    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1356
1357    /**
1358     * <p>
1359     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1360     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1361     * OnContextClickListener.
1362     * </p>
1363     * {@hide}
1364     */
1365    static final int CONTEXT_CLICKABLE = 0x00800000;
1366
1367
1368    /** @hide */
1369    @IntDef({
1370        SCROLLBARS_INSIDE_OVERLAY,
1371        SCROLLBARS_INSIDE_INSET,
1372        SCROLLBARS_OUTSIDE_OVERLAY,
1373        SCROLLBARS_OUTSIDE_INSET
1374    })
1375    @Retention(RetentionPolicy.SOURCE)
1376    public @interface ScrollBarStyle {}
1377
1378    /**
1379     * The scrollbar style to display the scrollbars inside the content area,
1380     * without increasing the padding. The scrollbars will be overlaid with
1381     * translucency on the view's content.
1382     */
1383    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1384
1385    /**
1386     * The scrollbar style to display the scrollbars inside the padded area,
1387     * increasing the padding of the view. The scrollbars will not overlap the
1388     * content area of the view.
1389     */
1390    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1391
1392    /**
1393     * The scrollbar style to display the scrollbars at the edge of the view,
1394     * without increasing the padding. The scrollbars will be overlaid with
1395     * translucency.
1396     */
1397    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1398
1399    /**
1400     * The scrollbar style to display the scrollbars at the edge of the view,
1401     * increasing the padding of the view. The scrollbars will only overlap the
1402     * background, if any.
1403     */
1404    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1405
1406    /**
1407     * Mask to check if the scrollbar style is overlay or inset.
1408     * {@hide}
1409     */
1410    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1411
1412    /**
1413     * Mask to check if the scrollbar style is inside or outside.
1414     * {@hide}
1415     */
1416    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1417
1418    /**
1419     * Mask for scrollbar style.
1420     * {@hide}
1421     */
1422    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1423
1424    /**
1425     * View flag indicating that the screen should remain on while the
1426     * window containing this view is visible to the user.  This effectively
1427     * takes care of automatically setting the WindowManager's
1428     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1429     */
1430    public static final int KEEP_SCREEN_ON = 0x04000000;
1431
1432    /**
1433     * View flag indicating whether this view should have sound effects enabled
1434     * for events such as clicking and touching.
1435     */
1436    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1437
1438    /**
1439     * View flag indicating whether this view should have haptic feedback
1440     * enabled for events such as long presses.
1441     */
1442    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1443
1444    /**
1445     * <p>Indicates that the view hierarchy should stop saving state when
1446     * it reaches this view.  If state saving is initiated immediately at
1447     * the view, it will be allowed.
1448     * {@hide}
1449     */
1450    static final int PARENT_SAVE_DISABLED = 0x20000000;
1451
1452    /**
1453     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1454     * {@hide}
1455     */
1456    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1457
1458    private static Paint sDebugPaint;
1459
1460    /**
1461     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1462     * {@hide}
1463     */
1464    static final int TOOLTIP = 0x40000000;
1465
1466    /** @hide */
1467    @IntDef(flag = true,
1468            value = {
1469                FOCUSABLES_ALL,
1470                FOCUSABLES_TOUCH_MODE
1471            })
1472    @Retention(RetentionPolicy.SOURCE)
1473    public @interface FocusableMode {}
1474
1475    /**
1476     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1477     * should add all focusable Views regardless if they are focusable in touch mode.
1478     */
1479    public static final int FOCUSABLES_ALL = 0x00000000;
1480
1481    /**
1482     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1483     * should add only Views focusable in touch mode.
1484     */
1485    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1486
1487    /** @hide */
1488    @IntDef({
1489            FOCUS_BACKWARD,
1490            FOCUS_FORWARD,
1491            FOCUS_LEFT,
1492            FOCUS_UP,
1493            FOCUS_RIGHT,
1494            FOCUS_DOWN
1495    })
1496    @Retention(RetentionPolicy.SOURCE)
1497    public @interface FocusDirection {}
1498
1499    /** @hide */
1500    @IntDef({
1501            FOCUS_LEFT,
1502            FOCUS_UP,
1503            FOCUS_RIGHT,
1504            FOCUS_DOWN
1505    })
1506    @Retention(RetentionPolicy.SOURCE)
1507    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1508
1509    /**
1510     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1511     * item.
1512     */
1513    public static final int FOCUS_BACKWARD = 0x00000001;
1514
1515    /**
1516     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1517     * item.
1518     */
1519    public static final int FOCUS_FORWARD = 0x00000002;
1520
1521    /**
1522     * Use with {@link #focusSearch(int)}. Move focus to the left.
1523     */
1524    public static final int FOCUS_LEFT = 0x00000011;
1525
1526    /**
1527     * Use with {@link #focusSearch(int)}. Move focus up.
1528     */
1529    public static final int FOCUS_UP = 0x00000021;
1530
1531    /**
1532     * Use with {@link #focusSearch(int)}. Move focus to the right.
1533     */
1534    public static final int FOCUS_RIGHT = 0x00000042;
1535
1536    /**
1537     * Use with {@link #focusSearch(int)}. Move focus down.
1538     */
1539    public static final int FOCUS_DOWN = 0x00000082;
1540
1541    /**
1542     * Bits of {@link #getMeasuredWidthAndState()} and
1543     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1544     */
1545    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1546
1547    /**
1548     * Bits of {@link #getMeasuredWidthAndState()} and
1549     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1550     */
1551    public static final int MEASURED_STATE_MASK = 0xff000000;
1552
1553    /**
1554     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1555     * for functions that combine both width and height into a single int,
1556     * such as {@link #getMeasuredState()} and the childState argument of
1557     * {@link #resolveSizeAndState(int, int, int)}.
1558     */
1559    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1560
1561    /**
1562     * Bit of {@link #getMeasuredWidthAndState()} and
1563     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1564     * is smaller that the space the view would like to have.
1565     */
1566    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1567
1568    /**
1569     * Base View state sets
1570     */
1571    // Singles
1572    /**
1573     * Indicates the view has no states set. States are used with
1574     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1575     * view depending on its state.
1576     *
1577     * @see android.graphics.drawable.Drawable
1578     * @see #getDrawableState()
1579     */
1580    protected static final int[] EMPTY_STATE_SET;
1581    /**
1582     * Indicates the view is enabled. States are used with
1583     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1584     * view depending on its state.
1585     *
1586     * @see android.graphics.drawable.Drawable
1587     * @see #getDrawableState()
1588     */
1589    protected static final int[] ENABLED_STATE_SET;
1590    /**
1591     * Indicates the view is focused. States are used with
1592     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1593     * view depending on its state.
1594     *
1595     * @see android.graphics.drawable.Drawable
1596     * @see #getDrawableState()
1597     */
1598    protected static final int[] FOCUSED_STATE_SET;
1599    /**
1600     * Indicates the view is selected. States are used with
1601     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1602     * view depending on its state.
1603     *
1604     * @see android.graphics.drawable.Drawable
1605     * @see #getDrawableState()
1606     */
1607    protected static final int[] SELECTED_STATE_SET;
1608    /**
1609     * Indicates the view is pressed. States are used with
1610     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1611     * view depending on its state.
1612     *
1613     * @see android.graphics.drawable.Drawable
1614     * @see #getDrawableState()
1615     */
1616    protected static final int[] PRESSED_STATE_SET;
1617    /**
1618     * Indicates the view's window has focus. States are used with
1619     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1620     * view depending on its state.
1621     *
1622     * @see android.graphics.drawable.Drawable
1623     * @see #getDrawableState()
1624     */
1625    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1626    // Doubles
1627    /**
1628     * Indicates the view is enabled and has the focus.
1629     *
1630     * @see #ENABLED_STATE_SET
1631     * @see #FOCUSED_STATE_SET
1632     */
1633    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1634    /**
1635     * Indicates the view is enabled and selected.
1636     *
1637     * @see #ENABLED_STATE_SET
1638     * @see #SELECTED_STATE_SET
1639     */
1640    protected static final int[] ENABLED_SELECTED_STATE_SET;
1641    /**
1642     * Indicates the view is enabled and that its window has focus.
1643     *
1644     * @see #ENABLED_STATE_SET
1645     * @see #WINDOW_FOCUSED_STATE_SET
1646     */
1647    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1648    /**
1649     * Indicates the view is focused and selected.
1650     *
1651     * @see #FOCUSED_STATE_SET
1652     * @see #SELECTED_STATE_SET
1653     */
1654    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1655    /**
1656     * Indicates the view has the focus and that its window has the focus.
1657     *
1658     * @see #FOCUSED_STATE_SET
1659     * @see #WINDOW_FOCUSED_STATE_SET
1660     */
1661    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1662    /**
1663     * Indicates the view is selected and that its window has the focus.
1664     *
1665     * @see #SELECTED_STATE_SET
1666     * @see #WINDOW_FOCUSED_STATE_SET
1667     */
1668    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1669    // Triples
1670    /**
1671     * Indicates the view is enabled, focused and selected.
1672     *
1673     * @see #ENABLED_STATE_SET
1674     * @see #FOCUSED_STATE_SET
1675     * @see #SELECTED_STATE_SET
1676     */
1677    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1678    /**
1679     * Indicates the view is enabled, focused and its window has the focus.
1680     *
1681     * @see #ENABLED_STATE_SET
1682     * @see #FOCUSED_STATE_SET
1683     * @see #WINDOW_FOCUSED_STATE_SET
1684     */
1685    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1686    /**
1687     * Indicates the view is enabled, selected and its window has the focus.
1688     *
1689     * @see #ENABLED_STATE_SET
1690     * @see #SELECTED_STATE_SET
1691     * @see #WINDOW_FOCUSED_STATE_SET
1692     */
1693    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1694    /**
1695     * Indicates the view is focused, selected and its window has the focus.
1696     *
1697     * @see #FOCUSED_STATE_SET
1698     * @see #SELECTED_STATE_SET
1699     * @see #WINDOW_FOCUSED_STATE_SET
1700     */
1701    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1702    /**
1703     * Indicates the view is enabled, focused, selected and its window
1704     * has the focus.
1705     *
1706     * @see #ENABLED_STATE_SET
1707     * @see #FOCUSED_STATE_SET
1708     * @see #SELECTED_STATE_SET
1709     * @see #WINDOW_FOCUSED_STATE_SET
1710     */
1711    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1712    /**
1713     * Indicates the view is pressed and its window has the focus.
1714     *
1715     * @see #PRESSED_STATE_SET
1716     * @see #WINDOW_FOCUSED_STATE_SET
1717     */
1718    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1719    /**
1720     * Indicates the view is pressed and selected.
1721     *
1722     * @see #PRESSED_STATE_SET
1723     * @see #SELECTED_STATE_SET
1724     */
1725    protected static final int[] PRESSED_SELECTED_STATE_SET;
1726    /**
1727     * Indicates the view is pressed, selected and its window has the focus.
1728     *
1729     * @see #PRESSED_STATE_SET
1730     * @see #SELECTED_STATE_SET
1731     * @see #WINDOW_FOCUSED_STATE_SET
1732     */
1733    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1734    /**
1735     * Indicates the view is pressed and focused.
1736     *
1737     * @see #PRESSED_STATE_SET
1738     * @see #FOCUSED_STATE_SET
1739     */
1740    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1741    /**
1742     * Indicates the view is pressed, focused and its window has the focus.
1743     *
1744     * @see #PRESSED_STATE_SET
1745     * @see #FOCUSED_STATE_SET
1746     * @see #WINDOW_FOCUSED_STATE_SET
1747     */
1748    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1749    /**
1750     * Indicates the view is pressed, focused and selected.
1751     *
1752     * @see #PRESSED_STATE_SET
1753     * @see #SELECTED_STATE_SET
1754     * @see #FOCUSED_STATE_SET
1755     */
1756    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1757    /**
1758     * Indicates the view is pressed, focused, selected and its window has the focus.
1759     *
1760     * @see #PRESSED_STATE_SET
1761     * @see #FOCUSED_STATE_SET
1762     * @see #SELECTED_STATE_SET
1763     * @see #WINDOW_FOCUSED_STATE_SET
1764     */
1765    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1766    /**
1767     * Indicates the view is pressed and enabled.
1768     *
1769     * @see #PRESSED_STATE_SET
1770     * @see #ENABLED_STATE_SET
1771     */
1772    protected static final int[] PRESSED_ENABLED_STATE_SET;
1773    /**
1774     * Indicates the view is pressed, enabled and its window has the focus.
1775     *
1776     * @see #PRESSED_STATE_SET
1777     * @see #ENABLED_STATE_SET
1778     * @see #WINDOW_FOCUSED_STATE_SET
1779     */
1780    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1781    /**
1782     * Indicates the view is pressed, enabled and selected.
1783     *
1784     * @see #PRESSED_STATE_SET
1785     * @see #ENABLED_STATE_SET
1786     * @see #SELECTED_STATE_SET
1787     */
1788    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1789    /**
1790     * Indicates the view is pressed, enabled, selected and its window has the
1791     * focus.
1792     *
1793     * @see #PRESSED_STATE_SET
1794     * @see #ENABLED_STATE_SET
1795     * @see #SELECTED_STATE_SET
1796     * @see #WINDOW_FOCUSED_STATE_SET
1797     */
1798    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1799    /**
1800     * Indicates the view is pressed, enabled and focused.
1801     *
1802     * @see #PRESSED_STATE_SET
1803     * @see #ENABLED_STATE_SET
1804     * @see #FOCUSED_STATE_SET
1805     */
1806    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1807    /**
1808     * Indicates the view is pressed, enabled, focused and its window has the
1809     * focus.
1810     *
1811     * @see #PRESSED_STATE_SET
1812     * @see #ENABLED_STATE_SET
1813     * @see #FOCUSED_STATE_SET
1814     * @see #WINDOW_FOCUSED_STATE_SET
1815     */
1816    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1817    /**
1818     * Indicates the view is pressed, enabled, focused and selected.
1819     *
1820     * @see #PRESSED_STATE_SET
1821     * @see #ENABLED_STATE_SET
1822     * @see #SELECTED_STATE_SET
1823     * @see #FOCUSED_STATE_SET
1824     */
1825    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1826    /**
1827     * Indicates the view is pressed, enabled, focused, selected and its window
1828     * has the focus.
1829     *
1830     * @see #PRESSED_STATE_SET
1831     * @see #ENABLED_STATE_SET
1832     * @see #SELECTED_STATE_SET
1833     * @see #FOCUSED_STATE_SET
1834     * @see #WINDOW_FOCUSED_STATE_SET
1835     */
1836    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1837
1838    static {
1839        EMPTY_STATE_SET = StateSet.get(0);
1840
1841        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1842
1843        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1844        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1845                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1846
1847        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1848        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1849                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1850        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1851                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1852        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1853                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1854                        | StateSet.VIEW_STATE_FOCUSED);
1855
1856        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1857        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1858                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1859        ENABLED_SELECTED_STATE_SET = StateSet.get(
1860                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1861        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1862                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1863                        | StateSet.VIEW_STATE_ENABLED);
1864        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1865                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1866        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1867                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1868                        | StateSet.VIEW_STATE_ENABLED);
1869        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1870                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1871                        | StateSet.VIEW_STATE_ENABLED);
1872        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1873                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1874                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1875
1876        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1877        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1878                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1879        PRESSED_SELECTED_STATE_SET = StateSet.get(
1880                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1881        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1882                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1883                        | StateSet.VIEW_STATE_PRESSED);
1884        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1885                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1886        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1887                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1888                        | StateSet.VIEW_STATE_PRESSED);
1889        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1890                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1891                        | StateSet.VIEW_STATE_PRESSED);
1892        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1893                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1894                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1895        PRESSED_ENABLED_STATE_SET = StateSet.get(
1896                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1897        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1898                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1899                        | StateSet.VIEW_STATE_PRESSED);
1900        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1901                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1902                        | StateSet.VIEW_STATE_PRESSED);
1903        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1904                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1905                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1906        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1907                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1908                        | StateSet.VIEW_STATE_PRESSED);
1909        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1910                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1911                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1912        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1913                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1914                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1915        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1916                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1917                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1918                        | StateSet.VIEW_STATE_PRESSED);
1919    }
1920
1921    /**
1922     * Accessibility event types that are dispatched for text population.
1923     */
1924    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1925            AccessibilityEvent.TYPE_VIEW_CLICKED
1926            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1927            | AccessibilityEvent.TYPE_VIEW_SELECTED
1928            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1929            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1930            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1931            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1932            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1933            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1934            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1935            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1936
1937    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1938
1939    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1940
1941    /**
1942     * Temporary Rect currently for use in setBackground().  This will probably
1943     * be extended in the future to hold our own class with more than just
1944     * a Rect. :)
1945     */
1946    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1947
1948    /**
1949     * Map used to store views' tags.
1950     */
1951    private SparseArray<Object> mKeyedTags;
1952
1953    /**
1954     * The animation currently associated with this view.
1955     * @hide
1956     */
1957    protected Animation mCurrentAnimation = null;
1958
1959    /**
1960     * Width as measured during measure pass.
1961     * {@hide}
1962     */
1963    @ViewDebug.ExportedProperty(category = "measurement")
1964    int mMeasuredWidth;
1965
1966    /**
1967     * Height as measured during measure pass.
1968     * {@hide}
1969     */
1970    @ViewDebug.ExportedProperty(category = "measurement")
1971    int mMeasuredHeight;
1972
1973    /**
1974     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1975     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1976     * its display list. This flag, used only when hw accelerated, allows us to clear the
1977     * flag while retaining this information until it's needed (at getDisplayList() time and
1978     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1979     *
1980     * {@hide}
1981     */
1982    boolean mRecreateDisplayList = false;
1983
1984    /**
1985     * The view's identifier.
1986     * {@hide}
1987     *
1988     * @see #setId(int)
1989     * @see #getId()
1990     */
1991    @IdRes
1992    @ViewDebug.ExportedProperty(resolveId = true)
1993    int mID = NO_ID;
1994
1995    /** The ID of this view for accessibility and autofill purposes.
1996     * <ul>
1997     *     <li>== {@link #NO_ID}: ID has not been assigned yet
1998     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
1999     *                                                  unique in the process. This might change
2000     *                                                  over activity lifecycle events.
2001     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
2002     *                                                  unique in the activity. This stays the same
2003     *                                                  over activity lifecycle events.
2004     */
2005    private int mAccessibilityViewId = NO_ID;
2006
2007    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2008
2009    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2010
2011    /**
2012     * The view's tag.
2013     * {@hide}
2014     *
2015     * @see #setTag(Object)
2016     * @see #getTag()
2017     */
2018    protected Object mTag = null;
2019
2020    // for mPrivateFlags:
2021    /** {@hide} */
2022    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2023    /** {@hide} */
2024    static final int PFLAG_FOCUSED                     = 0x00000002;
2025    /** {@hide} */
2026    static final int PFLAG_SELECTED                    = 0x00000004;
2027    /** {@hide} */
2028    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2029    /** {@hide} */
2030    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2031    /** {@hide} */
2032    static final int PFLAG_DRAWN                       = 0x00000020;
2033    /**
2034     * When this flag is set, this view is running an animation on behalf of its
2035     * children and should therefore not cancel invalidate requests, even if they
2036     * lie outside of this view's bounds.
2037     *
2038     * {@hide}
2039     */
2040    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2041    /** {@hide} */
2042    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2043    /** {@hide} */
2044    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2045    /** {@hide} */
2046    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2047    /** {@hide} */
2048    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2049    /** {@hide} */
2050    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2051    /** {@hide} */
2052    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2053
2054    private static final int PFLAG_PRESSED             = 0x00004000;
2055
2056    /** {@hide} */
2057    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2058    /**
2059     * Flag used to indicate that this view should be drawn once more (and only once
2060     * more) after its animation has completed.
2061     * {@hide}
2062     */
2063    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2064
2065    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2066
2067    /**
2068     * Indicates that the View returned true when onSetAlpha() was called and that
2069     * the alpha must be restored.
2070     * {@hide}
2071     */
2072    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2073
2074    /**
2075     * Set by {@link #setScrollContainer(boolean)}.
2076     */
2077    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2078
2079    /**
2080     * Set by {@link #setScrollContainer(boolean)}.
2081     */
2082    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2083
2084    /**
2085     * View flag indicating whether this view was invalidated (fully or partially.)
2086     *
2087     * @hide
2088     */
2089    static final int PFLAG_DIRTY                       = 0x00200000;
2090
2091    /**
2092     * View flag indicating whether this view was invalidated by an opaque
2093     * invalidate request.
2094     *
2095     * @hide
2096     */
2097    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2098
2099    /**
2100     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2101     *
2102     * @hide
2103     */
2104    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2105
2106    /**
2107     * Indicates whether the background is opaque.
2108     *
2109     * @hide
2110     */
2111    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2112
2113    /**
2114     * Indicates whether the scrollbars are opaque.
2115     *
2116     * @hide
2117     */
2118    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2119
2120    /**
2121     * Indicates whether the view is opaque.
2122     *
2123     * @hide
2124     */
2125    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2126
2127    /**
2128     * Indicates a prepressed state;
2129     * the short time between ACTION_DOWN and recognizing
2130     * a 'real' press. Prepressed is used to recognize quick taps
2131     * even when they are shorter than ViewConfiguration.getTapTimeout().
2132     *
2133     * @hide
2134     */
2135    private static final int PFLAG_PREPRESSED          = 0x02000000;
2136
2137    /**
2138     * Indicates whether the view is temporarily detached.
2139     *
2140     * @hide
2141     */
2142    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2143
2144    /**
2145     * Indicates that we should awaken scroll bars once attached
2146     *
2147     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2148     * during window attachment and it is no longer needed. Feel free to repurpose it.
2149     *
2150     * @hide
2151     */
2152    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2153
2154    /**
2155     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2156     * @hide
2157     */
2158    private static final int PFLAG_HOVERED             = 0x10000000;
2159
2160    /**
2161     * no longer needed, should be reused
2162     */
2163    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2164
2165    /** {@hide} */
2166    static final int PFLAG_ACTIVATED                   = 0x40000000;
2167
2168    /**
2169     * Indicates that this view was specifically invalidated, not just dirtied because some
2170     * child view was invalidated. The flag is used to determine when we need to recreate
2171     * a view's display list (as opposed to just returning a reference to its existing
2172     * display list).
2173     *
2174     * @hide
2175     */
2176    static final int PFLAG_INVALIDATED                 = 0x80000000;
2177
2178    /**
2179     * Masks for mPrivateFlags2, as generated by dumpFlags():
2180     *
2181     * |-------|-------|-------|-------|
2182     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2183     *                                1  PFLAG2_DRAG_HOVERED
2184     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2185     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2186     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2187     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2188     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2189     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2190     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2191     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2192     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2193     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2194     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2195     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2196     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2197     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2198     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2199     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2200     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2201     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2202     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2203     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2204     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2205     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2206     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2207     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2208     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2209     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2210     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2211     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2212     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2213     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2214     *    1                              PFLAG2_PADDING_RESOLVED
2215     *   1                               PFLAG2_DRAWABLE_RESOLVED
2216     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2217     * |-------|-------|-------|-------|
2218     */
2219
2220    /**
2221     * Indicates that this view has reported that it can accept the current drag's content.
2222     * Cleared when the drag operation concludes.
2223     * @hide
2224     */
2225    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2226
2227    /**
2228     * Indicates that this view is currently directly under the drag location in a
2229     * drag-and-drop operation involving content that it can accept.  Cleared when
2230     * the drag exits the view, or when the drag operation concludes.
2231     * @hide
2232     */
2233    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2234
2235    /** @hide */
2236    @IntDef({
2237        LAYOUT_DIRECTION_LTR,
2238        LAYOUT_DIRECTION_RTL,
2239        LAYOUT_DIRECTION_INHERIT,
2240        LAYOUT_DIRECTION_LOCALE
2241    })
2242    @Retention(RetentionPolicy.SOURCE)
2243    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2244    public @interface LayoutDir {}
2245
2246    /** @hide */
2247    @IntDef({
2248        LAYOUT_DIRECTION_LTR,
2249        LAYOUT_DIRECTION_RTL
2250    })
2251    @Retention(RetentionPolicy.SOURCE)
2252    public @interface ResolvedLayoutDir {}
2253
2254    /**
2255     * A flag to indicate that the layout direction of this view has not been defined yet.
2256     * @hide
2257     */
2258    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2259
2260    /**
2261     * Horizontal layout direction of this view is from Left to Right.
2262     * Use with {@link #setLayoutDirection}.
2263     */
2264    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2265
2266    /**
2267     * Horizontal layout direction of this view is from Right to Left.
2268     * Use with {@link #setLayoutDirection}.
2269     */
2270    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2271
2272    /**
2273     * Horizontal layout direction of this view is inherited from its parent.
2274     * Use with {@link #setLayoutDirection}.
2275     */
2276    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2277
2278    /**
2279     * Horizontal layout direction of this view is from deduced from the default language
2280     * script for the locale. Use with {@link #setLayoutDirection}.
2281     */
2282    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2283
2284    /**
2285     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2286     * @hide
2287     */
2288    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2289
2290    /**
2291     * Mask for use with private flags indicating bits used for horizontal layout direction.
2292     * @hide
2293     */
2294    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2295
2296    /**
2297     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2298     * right-to-left direction.
2299     * @hide
2300     */
2301    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2302
2303    /**
2304     * Indicates whether the view horizontal layout direction has been resolved.
2305     * @hide
2306     */
2307    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2308
2309    /**
2310     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2311     * @hide
2312     */
2313    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2314            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2315
2316    /*
2317     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2318     * flag value.
2319     * @hide
2320     */
2321    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2322            LAYOUT_DIRECTION_LTR,
2323            LAYOUT_DIRECTION_RTL,
2324            LAYOUT_DIRECTION_INHERIT,
2325            LAYOUT_DIRECTION_LOCALE
2326    };
2327
2328    /**
2329     * Default horizontal layout direction.
2330     */
2331    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2332
2333    /**
2334     * Default horizontal layout direction.
2335     * @hide
2336     */
2337    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2338
2339    /**
2340     * Text direction is inherited through {@link ViewGroup}
2341     */
2342    public static final int TEXT_DIRECTION_INHERIT = 0;
2343
2344    /**
2345     * Text direction is using "first strong algorithm". The first strong directional character
2346     * determines the paragraph direction. If there is no strong directional character, the
2347     * paragraph direction is the view's resolved layout direction.
2348     */
2349    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2350
2351    /**
2352     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2353     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2354     * If there are neither, the paragraph direction is the view's resolved layout direction.
2355     */
2356    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2357
2358    /**
2359     * Text direction is forced to LTR.
2360     */
2361    public static final int TEXT_DIRECTION_LTR = 3;
2362
2363    /**
2364     * Text direction is forced to RTL.
2365     */
2366    public static final int TEXT_DIRECTION_RTL = 4;
2367
2368    /**
2369     * Text direction is coming from the system Locale.
2370     */
2371    public static final int TEXT_DIRECTION_LOCALE = 5;
2372
2373    /**
2374     * Text direction is using "first strong algorithm". The first strong directional character
2375     * determines the paragraph direction. If there is no strong directional character, the
2376     * paragraph direction is LTR.
2377     */
2378    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2379
2380    /**
2381     * Text direction is using "first strong algorithm". The first strong directional character
2382     * determines the paragraph direction. If there is no strong directional character, the
2383     * paragraph direction is RTL.
2384     */
2385    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2386
2387    /**
2388     * Default text direction is inherited
2389     */
2390    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2391
2392    /**
2393     * Default resolved text direction
2394     * @hide
2395     */
2396    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2397
2398    /**
2399     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2400     * @hide
2401     */
2402    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2403
2404    /**
2405     * Mask for use with private flags indicating bits used for text direction.
2406     * @hide
2407     */
2408    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2409            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2410
2411    /**
2412     * Array of text direction flags for mapping attribute "textDirection" to correct
2413     * flag value.
2414     * @hide
2415     */
2416    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2417            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2418            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2419            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2420            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2421            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2422            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2423            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2424            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2425    };
2426
2427    /**
2428     * Indicates whether the view text direction has been resolved.
2429     * @hide
2430     */
2431    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2432            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2433
2434    /**
2435     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2436     * @hide
2437     */
2438    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2439
2440    /**
2441     * Mask for use with private flags indicating bits used for resolved text direction.
2442     * @hide
2443     */
2444    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2445            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2446
2447    /**
2448     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2449     * @hide
2450     */
2451    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2452            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2453
2454    /** @hide */
2455    @IntDef({
2456        TEXT_ALIGNMENT_INHERIT,
2457        TEXT_ALIGNMENT_GRAVITY,
2458        TEXT_ALIGNMENT_CENTER,
2459        TEXT_ALIGNMENT_TEXT_START,
2460        TEXT_ALIGNMENT_TEXT_END,
2461        TEXT_ALIGNMENT_VIEW_START,
2462        TEXT_ALIGNMENT_VIEW_END
2463    })
2464    @Retention(RetentionPolicy.SOURCE)
2465    public @interface TextAlignment {}
2466
2467    /**
2468     * Default text alignment. The text alignment of this View is inherited from its parent.
2469     * Use with {@link #setTextAlignment(int)}
2470     */
2471    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2472
2473    /**
2474     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2475     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2476     *
2477     * Use with {@link #setTextAlignment(int)}
2478     */
2479    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2480
2481    /**
2482     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2483     *
2484     * Use with {@link #setTextAlignment(int)}
2485     */
2486    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2487
2488    /**
2489     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2490     *
2491     * Use with {@link #setTextAlignment(int)}
2492     */
2493    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2494
2495    /**
2496     * Center the paragraph, e.g. ALIGN_CENTER.
2497     *
2498     * Use with {@link #setTextAlignment(int)}
2499     */
2500    public static final int TEXT_ALIGNMENT_CENTER = 4;
2501
2502    /**
2503     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2504     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2505     *
2506     * Use with {@link #setTextAlignment(int)}
2507     */
2508    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2509
2510    /**
2511     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2512     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2513     *
2514     * Use with {@link #setTextAlignment(int)}
2515     */
2516    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2517
2518    /**
2519     * Default text alignment is inherited
2520     */
2521    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2522
2523    /**
2524     * Default resolved text alignment
2525     * @hide
2526     */
2527    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2528
2529    /**
2530      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2531      * @hide
2532      */
2533    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2534
2535    /**
2536      * Mask for use with private flags indicating bits used for text alignment.
2537      * @hide
2538      */
2539    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2540
2541    /**
2542     * Array of text direction flags for mapping attribute "textAlignment" to correct
2543     * flag value.
2544     * @hide
2545     */
2546    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2547            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2548            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2549            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2550            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2551            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2552            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2553            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2554    };
2555
2556    /**
2557     * Indicates whether the view text alignment has been resolved.
2558     * @hide
2559     */
2560    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2561
2562    /**
2563     * Bit shift to get the resolved text alignment.
2564     * @hide
2565     */
2566    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2567
2568    /**
2569     * Mask for use with private flags indicating bits used for text alignment.
2570     * @hide
2571     */
2572    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2573            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2574
2575    /**
2576     * Indicates whether if the view text alignment has been resolved to gravity
2577     */
2578    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2579            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2580
2581    // Accessiblity constants for mPrivateFlags2
2582
2583    /**
2584     * Shift for the bits in {@link #mPrivateFlags2} related to the
2585     * "importantForAccessibility" attribute.
2586     */
2587    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2588
2589    /**
2590     * Automatically determine whether a view is important for accessibility.
2591     */
2592    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2593
2594    /**
2595     * The view is important for accessibility.
2596     */
2597    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2598
2599    /**
2600     * The view is not important for accessibility.
2601     */
2602    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2603
2604    /**
2605     * The view is not important for accessibility, nor are any of its
2606     * descendant views.
2607     */
2608    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2609
2610    /**
2611     * The default whether the view is important for accessibility.
2612     */
2613    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2614
2615    /**
2616     * Mask for obtaining the bits which specify how to determine
2617     * whether a view is important for accessibility.
2618     */
2619    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2620        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2621        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2622        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2623
2624    /**
2625     * Shift for the bits in {@link #mPrivateFlags2} related to the
2626     * "accessibilityLiveRegion" attribute.
2627     */
2628    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2629
2630    /**
2631     * Live region mode specifying that accessibility services should not
2632     * automatically announce changes to this view. This is the default live
2633     * region mode for most views.
2634     * <p>
2635     * Use with {@link #setAccessibilityLiveRegion(int)}.
2636     */
2637    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2638
2639    /**
2640     * Live region mode specifying that accessibility services should announce
2641     * changes to this view.
2642     * <p>
2643     * Use with {@link #setAccessibilityLiveRegion(int)}.
2644     */
2645    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2646
2647    /**
2648     * Live region mode specifying that accessibility services should interrupt
2649     * ongoing speech to immediately announce changes to this view.
2650     * <p>
2651     * Use with {@link #setAccessibilityLiveRegion(int)}.
2652     */
2653    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2654
2655    /**
2656     * The default whether the view is important for accessibility.
2657     */
2658    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2659
2660    /**
2661     * Mask for obtaining the bits which specify a view's accessibility live
2662     * region mode.
2663     */
2664    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2665            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2666            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2667
2668    /**
2669     * Flag indicating whether a view has accessibility focus.
2670     */
2671    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2672
2673    /**
2674     * Flag whether the accessibility state of the subtree rooted at this view changed.
2675     */
2676    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2677
2678    /**
2679     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2680     * is used to check whether later changes to the view's transform should invalidate the
2681     * view to force the quickReject test to run again.
2682     */
2683    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2684
2685    /**
2686     * Flag indicating that start/end padding has been resolved into left/right padding
2687     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2688     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2689     * during measurement. In some special cases this is required such as when an adapter-based
2690     * view measures prospective children without attaching them to a window.
2691     */
2692    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2693
2694    /**
2695     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2696     */
2697    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2698
2699    /**
2700     * Indicates that the view is tracking some sort of transient state
2701     * that the app should not need to be aware of, but that the framework
2702     * should take special care to preserve.
2703     */
2704    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2705
2706    /**
2707     * Group of bits indicating that RTL properties resolution is done.
2708     */
2709    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2710            PFLAG2_TEXT_DIRECTION_RESOLVED |
2711            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2712            PFLAG2_PADDING_RESOLVED |
2713            PFLAG2_DRAWABLE_RESOLVED;
2714
2715    // There are a couple of flags left in mPrivateFlags2
2716
2717    /* End of masks for mPrivateFlags2 */
2718
2719    /**
2720     * Masks for mPrivateFlags3, as generated by dumpFlags():
2721     *
2722     * |-------|-------|-------|-------|
2723     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2724     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2725     *                               1   PFLAG3_IS_LAID_OUT
2726     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2727     *                             1     PFLAG3_CALLED_SUPER
2728     *                            1      PFLAG3_APPLYING_INSETS
2729     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2730     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2731     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2732     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2733     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2734     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2735     *                     1             PFLAG3_SCROLL_INDICATOR_START
2736     *                    1              PFLAG3_SCROLL_INDICATOR_END
2737     *                   1               PFLAG3_ASSIST_BLOCKED
2738     *                  1                PFLAG3_CLUSTER
2739     *                 1                 PFLAG3_IS_AUTOFILLED
2740     *                1                  PFLAG3_FINGER_DOWN
2741     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2742     *             __                    unused
2743     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
2744     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2745     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2746     *        1                          PFLAG3_TEMPORARY_DETACH
2747     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2748     * |-------|-------|-------|-------|
2749     */
2750
2751    /**
2752     * Flag indicating that view has a transform animation set on it. This is used to track whether
2753     * an animation is cleared between successive frames, in order to tell the associated
2754     * DisplayList to clear its animation matrix.
2755     */
2756    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2757
2758    /**
2759     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2760     * animation is cleared between successive frames, in order to tell the associated
2761     * DisplayList to restore its alpha value.
2762     */
2763    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2764
2765    /**
2766     * Flag indicating that the view has been through at least one layout since it
2767     * was last attached to a window.
2768     */
2769    static final int PFLAG3_IS_LAID_OUT = 0x4;
2770
2771    /**
2772     * Flag indicating that a call to measure() was skipped and should be done
2773     * instead when layout() is invoked.
2774     */
2775    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2776
2777    /**
2778     * Flag indicating that an overridden method correctly called down to
2779     * the superclass implementation as required by the API spec.
2780     */
2781    static final int PFLAG3_CALLED_SUPER = 0x10;
2782
2783    /**
2784     * Flag indicating that we're in the process of applying window insets.
2785     */
2786    static final int PFLAG3_APPLYING_INSETS = 0x20;
2787
2788    /**
2789     * Flag indicating that we're in the process of fitting system windows using the old method.
2790     */
2791    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2792
2793    /**
2794     * Flag indicating that nested scrolling is enabled for this view.
2795     * The view will optionally cooperate with views up its parent chain to allow for
2796     * integrated nested scrolling along the same axis.
2797     */
2798    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2799
2800    /**
2801     * Flag indicating that the bottom scroll indicator should be displayed
2802     * when this view can scroll up.
2803     */
2804    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2805
2806    /**
2807     * Flag indicating that the bottom scroll indicator should be displayed
2808     * when this view can scroll down.
2809     */
2810    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2811
2812    /**
2813     * Flag indicating that the left scroll indicator should be displayed
2814     * when this view can scroll left.
2815     */
2816    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2817
2818    /**
2819     * Flag indicating that the right scroll indicator should be displayed
2820     * when this view can scroll right.
2821     */
2822    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2823
2824    /**
2825     * Flag indicating that the start scroll indicator should be displayed
2826     * when this view can scroll in the start direction.
2827     */
2828    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2829
2830    /**
2831     * Flag indicating that the end scroll indicator should be displayed
2832     * when this view can scroll in the end direction.
2833     */
2834    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2835
2836    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2837
2838    static final int SCROLL_INDICATORS_NONE = 0x0000;
2839
2840    /**
2841     * Mask for use with setFlags indicating bits used for indicating which
2842     * scroll indicators are enabled.
2843     */
2844    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2845            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2846            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2847            | PFLAG3_SCROLL_INDICATOR_END;
2848
2849    /**
2850     * Left-shift required to translate between public scroll indicator flags
2851     * and internal PFLAGS3 flags. When used as a right-shift, translates
2852     * PFLAGS3 flags to public flags.
2853     */
2854    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2855
2856    /** @hide */
2857    @Retention(RetentionPolicy.SOURCE)
2858    @IntDef(flag = true,
2859            value = {
2860                    SCROLL_INDICATOR_TOP,
2861                    SCROLL_INDICATOR_BOTTOM,
2862                    SCROLL_INDICATOR_LEFT,
2863                    SCROLL_INDICATOR_RIGHT,
2864                    SCROLL_INDICATOR_START,
2865                    SCROLL_INDICATOR_END,
2866            })
2867    public @interface ScrollIndicators {}
2868
2869    /**
2870     * Scroll indicator direction for the top edge of the view.
2871     *
2872     * @see #setScrollIndicators(int)
2873     * @see #setScrollIndicators(int, int)
2874     * @see #getScrollIndicators()
2875     */
2876    public static final int SCROLL_INDICATOR_TOP =
2877            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2878
2879    /**
2880     * Scroll indicator direction for the bottom edge of the view.
2881     *
2882     * @see #setScrollIndicators(int)
2883     * @see #setScrollIndicators(int, int)
2884     * @see #getScrollIndicators()
2885     */
2886    public static final int SCROLL_INDICATOR_BOTTOM =
2887            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2888
2889    /**
2890     * Scroll indicator direction for the left edge of the view.
2891     *
2892     * @see #setScrollIndicators(int)
2893     * @see #setScrollIndicators(int, int)
2894     * @see #getScrollIndicators()
2895     */
2896    public static final int SCROLL_INDICATOR_LEFT =
2897            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2898
2899    /**
2900     * Scroll indicator direction for the right edge of the view.
2901     *
2902     * @see #setScrollIndicators(int)
2903     * @see #setScrollIndicators(int, int)
2904     * @see #getScrollIndicators()
2905     */
2906    public static final int SCROLL_INDICATOR_RIGHT =
2907            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2908
2909    /**
2910     * Scroll indicator direction for the starting edge of the view.
2911     * <p>
2912     * Resolved according to the view's layout direction, see
2913     * {@link #getLayoutDirection()} for more information.
2914     *
2915     * @see #setScrollIndicators(int)
2916     * @see #setScrollIndicators(int, int)
2917     * @see #getScrollIndicators()
2918     */
2919    public static final int SCROLL_INDICATOR_START =
2920            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2921
2922    /**
2923     * Scroll indicator direction for the ending edge of the view.
2924     * <p>
2925     * Resolved according to the view's layout direction, see
2926     * {@link #getLayoutDirection()} for more information.
2927     *
2928     * @see #setScrollIndicators(int)
2929     * @see #setScrollIndicators(int, int)
2930     * @see #getScrollIndicators()
2931     */
2932    public static final int SCROLL_INDICATOR_END =
2933            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2934
2935    /**
2936     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2937     * into this view.<p>
2938     */
2939    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2940
2941    /**
2942     * Flag indicating that the view is a root of a keyboard navigation cluster.
2943     *
2944     * @see #isKeyboardNavigationCluster()
2945     * @see #setKeyboardNavigationCluster(boolean)
2946     */
2947    private static final int PFLAG3_CLUSTER = 0x8000;
2948
2949    /**
2950     * Flag indicating that the view is autofilled
2951     *
2952     * @see #isAutofilled()
2953     * @see #setAutofilled(boolean)
2954     */
2955    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
2956
2957    /**
2958     * Indicates that the user is currently touching the screen.
2959     * Currently used for the tooltip positioning only.
2960     */
2961    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2962
2963    /**
2964     * Flag indicating that this view is the default-focus view.
2965     *
2966     * @see #isFocusedByDefault()
2967     * @see #setFocusedByDefault(boolean)
2968     */
2969    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2970
2971    /**
2972     * Shift for the bits in {@link #mPrivateFlags3} related to the
2973     * "importantForAutofill" attribute.
2974     */
2975    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
2976
2977    /**
2978     * Mask for obtaining the bits which specify how to determine
2979     * whether a view is important for autofill.
2980     */
2981    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
2982            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
2983            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
2984
2985    /**
2986     * Whether this view has rendered elements that overlap (see {@link
2987     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2988     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2989     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2990     * determined by whatever {@link #hasOverlappingRendering()} returns.
2991     */
2992    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2993
2994    /**
2995     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2996     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2997     */
2998    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2999
3000    /**
3001     * Flag indicating that the view is temporarily detached from the parent view.
3002     *
3003     * @see #onStartTemporaryDetach()
3004     * @see #onFinishTemporaryDetach()
3005     */
3006    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3007
3008    /**
3009     * Flag indicating that the view does not wish to be revealed within its parent
3010     * hierarchy when it gains focus. Expressed in the negative since the historical
3011     * default behavior is to reveal on focus; this flag suppresses that behavior.
3012     *
3013     * @see #setRevealOnFocusHint(boolean)
3014     * @see #getRevealOnFocusHint()
3015     */
3016    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3017
3018    /* End of masks for mPrivateFlags3 */
3019
3020    /**
3021     * Always allow a user to over-scroll this view, provided it is a
3022     * view that can scroll.
3023     *
3024     * @see #getOverScrollMode()
3025     * @see #setOverScrollMode(int)
3026     */
3027    public static final int OVER_SCROLL_ALWAYS = 0;
3028
3029    /**
3030     * Allow a user to over-scroll this view only if the content is large
3031     * enough to meaningfully scroll, provided it is a view that can scroll.
3032     *
3033     * @see #getOverScrollMode()
3034     * @see #setOverScrollMode(int)
3035     */
3036    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3037
3038    /**
3039     * Never allow a user to over-scroll this view.
3040     *
3041     * @see #getOverScrollMode()
3042     * @see #setOverScrollMode(int)
3043     */
3044    public static final int OVER_SCROLL_NEVER = 2;
3045
3046    /**
3047     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3048     * requested the system UI (status bar) to be visible (the default).
3049     *
3050     * @see #setSystemUiVisibility(int)
3051     */
3052    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3053
3054    /**
3055     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3056     * system UI to enter an unobtrusive "low profile" mode.
3057     *
3058     * <p>This is for use in games, book readers, video players, or any other
3059     * "immersive" application where the usual system chrome is deemed too distracting.
3060     *
3061     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3062     *
3063     * @see #setSystemUiVisibility(int)
3064     */
3065    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3066
3067    /**
3068     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3069     * system navigation be temporarily hidden.
3070     *
3071     * <p>This is an even less obtrusive state than that called for by
3072     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3073     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3074     * those to disappear. This is useful (in conjunction with the
3075     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3076     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3077     * window flags) for displaying content using every last pixel on the display.
3078     *
3079     * <p>There is a limitation: because navigation controls are so important, the least user
3080     * interaction will cause them to reappear immediately.  When this happens, both
3081     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3082     * so that both elements reappear at the same time.
3083     *
3084     * @see #setSystemUiVisibility(int)
3085     */
3086    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3087
3088    /**
3089     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3090     * into the normal fullscreen mode so that its content can take over the screen
3091     * while still allowing the user to interact with the application.
3092     *
3093     * <p>This has the same visual effect as
3094     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3095     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3096     * meaning that non-critical screen decorations (such as the status bar) will be
3097     * hidden while the user is in the View's window, focusing the experience on
3098     * that content.  Unlike the window flag, if you are using ActionBar in
3099     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3100     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3101     * hide the action bar.
3102     *
3103     * <p>This approach to going fullscreen is best used over the window flag when
3104     * it is a transient state -- that is, the application does this at certain
3105     * points in its user interaction where it wants to allow the user to focus
3106     * on content, but not as a continuous state.  For situations where the application
3107     * would like to simply stay full screen the entire time (such as a game that
3108     * wants to take over the screen), the
3109     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3110     * is usually a better approach.  The state set here will be removed by the system
3111     * in various situations (such as the user moving to another application) like
3112     * the other system UI states.
3113     *
3114     * <p>When using this flag, the application should provide some easy facility
3115     * for the user to go out of it.  A common example would be in an e-book
3116     * reader, where tapping on the screen brings back whatever screen and UI
3117     * decorations that had been hidden while the user was immersed in reading
3118     * the book.
3119     *
3120     * @see #setSystemUiVisibility(int)
3121     */
3122    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3123
3124    /**
3125     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3126     * flags, we would like a stable view of the content insets given to
3127     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3128     * will always represent the worst case that the application can expect
3129     * as a continuous state.  In the stock Android UI this is the space for
3130     * the system bar, nav bar, and status bar, but not more transient elements
3131     * such as an input method.
3132     *
3133     * The stable layout your UI sees is based on the system UI modes you can
3134     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3135     * then you will get a stable layout for changes of the
3136     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3137     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3138     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3139     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3140     * with a stable layout.  (Note that you should avoid using
3141     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3142     *
3143     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3144     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3145     * then a hidden status bar will be considered a "stable" state for purposes
3146     * here.  This allows your UI to continually hide the status bar, while still
3147     * using the system UI flags to hide the action bar while still retaining
3148     * a stable layout.  Note that changing the window fullscreen flag will never
3149     * provide a stable layout for a clean transition.
3150     *
3151     * <p>If you are using ActionBar in
3152     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3153     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3154     * insets it adds to those given to the application.
3155     */
3156    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3157
3158    /**
3159     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3160     * to be laid out as if it has requested
3161     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3162     * allows it to avoid artifacts when switching in and out of that mode, at
3163     * the expense that some of its user interface may be covered by screen
3164     * decorations when they are shown.  You can perform layout of your inner
3165     * UI elements to account for the navigation system UI through the
3166     * {@link #fitSystemWindows(Rect)} method.
3167     */
3168    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3169
3170    /**
3171     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3172     * to be laid out as if it has requested
3173     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3174     * allows it to avoid artifacts when switching in and out of that mode, at
3175     * the expense that some of its user interface may be covered by screen
3176     * decorations when they are shown.  You can perform layout of your inner
3177     * UI elements to account for non-fullscreen system UI through the
3178     * {@link #fitSystemWindows(Rect)} method.
3179     */
3180    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3181
3182    /**
3183     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3184     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3185     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3186     * user interaction.
3187     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3188     * has an effect when used in combination with that flag.</p>
3189     */
3190    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3191
3192    /**
3193     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3194     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3195     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3196     * experience while also hiding the system bars.  If this flag is not set,
3197     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3198     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3199     * if the user swipes from the top of the screen.
3200     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3201     * system gestures, such as swiping from the top of the screen.  These transient system bars
3202     * will overlay app’s content, may have some degree of transparency, and will automatically
3203     * hide after a short timeout.
3204     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3205     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3206     * with one or both of those flags.</p>
3207     */
3208    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3209
3210    /**
3211     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3212     * is compatible with light status bar backgrounds.
3213     *
3214     * <p>For this to take effect, the window must request
3215     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3216     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3217     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3218     *         FLAG_TRANSLUCENT_STATUS}.
3219     *
3220     * @see android.R.attr#windowLightStatusBar
3221     */
3222    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3223
3224    /**
3225     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3226     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3227     */
3228    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3229
3230    /**
3231     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3232     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3233     */
3234    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3235
3236    /**
3237     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3238     * that is compatible with light navigation bar backgrounds.
3239     *
3240     * <p>For this to take effect, the window must request
3241     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3242     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3243     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3244     *         FLAG_TRANSLUCENT_NAVIGATION}.
3245     */
3246    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3247
3248    /**
3249     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3250     */
3251    @Deprecated
3252    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3253
3254    /**
3255     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3256     */
3257    @Deprecated
3258    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3259
3260    /**
3261     * @hide
3262     *
3263     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3264     * out of the public fields to keep the undefined bits out of the developer's way.
3265     *
3266     * Flag to make the status bar not expandable.  Unless you also
3267     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3268     */
3269    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3270
3271    /**
3272     * @hide
3273     *
3274     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3275     * out of the public fields to keep the undefined bits out of the developer's way.
3276     *
3277     * Flag to hide notification icons and scrolling ticker text.
3278     */
3279    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3280
3281    /**
3282     * @hide
3283     *
3284     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3285     * out of the public fields to keep the undefined bits out of the developer's way.
3286     *
3287     * Flag to disable incoming notification alerts.  This will not block
3288     * icons, but it will block sound, vibrating and other visual or aural notifications.
3289     */
3290    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3291
3292    /**
3293     * @hide
3294     *
3295     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3296     * out of the public fields to keep the undefined bits out of the developer's way.
3297     *
3298     * Flag to hide only the scrolling ticker.  Note that
3299     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3300     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3301     */
3302    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3303
3304    /**
3305     * @hide
3306     *
3307     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3308     * out of the public fields to keep the undefined bits out of the developer's way.
3309     *
3310     * Flag to hide the center system info area.
3311     */
3312    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3313
3314    /**
3315     * @hide
3316     *
3317     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3318     * out of the public fields to keep the undefined bits out of the developer's way.
3319     *
3320     * Flag to hide only the home button.  Don't use this
3321     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3322     */
3323    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3324
3325    /**
3326     * @hide
3327     *
3328     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3329     * out of the public fields to keep the undefined bits out of the developer's way.
3330     *
3331     * Flag to hide only the back button. Don't use this
3332     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3333     */
3334    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3335
3336    /**
3337     * @hide
3338     *
3339     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3340     * out of the public fields to keep the undefined bits out of the developer's way.
3341     *
3342     * Flag to hide only the clock.  You might use this if your activity has
3343     * its own clock making the status bar's clock redundant.
3344     */
3345    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3346
3347    /**
3348     * @hide
3349     *
3350     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3351     * out of the public fields to keep the undefined bits out of the developer's way.
3352     *
3353     * Flag to hide only the recent apps button. Don't use this
3354     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3355     */
3356    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3357
3358    /**
3359     * @hide
3360     *
3361     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3362     * out of the public fields to keep the undefined bits out of the developer's way.
3363     *
3364     * Flag to disable the global search gesture. Don't use this
3365     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3366     */
3367    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3368
3369    /**
3370     * @hide
3371     *
3372     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3373     * out of the public fields to keep the undefined bits out of the developer's way.
3374     *
3375     * Flag to specify that the status bar is displayed in transient mode.
3376     */
3377    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3378
3379    /**
3380     * @hide
3381     *
3382     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3383     * out of the public fields to keep the undefined bits out of the developer's way.
3384     *
3385     * Flag to specify that the navigation bar is displayed in transient mode.
3386     */
3387    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3388
3389    /**
3390     * @hide
3391     *
3392     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3393     * out of the public fields to keep the undefined bits out of the developer's way.
3394     *
3395     * Flag to specify that the hidden status bar would like to be shown.
3396     */
3397    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3398
3399    /**
3400     * @hide
3401     *
3402     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3403     * out of the public fields to keep the undefined bits out of the developer's way.
3404     *
3405     * Flag to specify that the hidden navigation bar would like to be shown.
3406     */
3407    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3408
3409    /**
3410     * @hide
3411     *
3412     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3413     * out of the public fields to keep the undefined bits out of the developer's way.
3414     *
3415     * Flag to specify that the status bar is displayed in translucent mode.
3416     */
3417    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3418
3419    /**
3420     * @hide
3421     *
3422     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3423     * out of the public fields to keep the undefined bits out of the developer's way.
3424     *
3425     * Flag to specify that the navigation bar is displayed in translucent mode.
3426     */
3427    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3428
3429    /**
3430     * @hide
3431     *
3432     * Makes navigation bar transparent (but not the status bar).
3433     */
3434    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3435
3436    /**
3437     * @hide
3438     *
3439     * Makes status bar transparent (but not the navigation bar).
3440     */
3441    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3442
3443    /**
3444     * @hide
3445     *
3446     * Makes both status bar and navigation bar transparent.
3447     */
3448    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3449            | STATUS_BAR_TRANSPARENT;
3450
3451    /**
3452     * @hide
3453     */
3454    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3455
3456    /**
3457     * These are the system UI flags that can be cleared by events outside
3458     * of an application.  Currently this is just the ability to tap on the
3459     * screen while hiding the navigation bar to have it return.
3460     * @hide
3461     */
3462    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3463            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3464            | SYSTEM_UI_FLAG_FULLSCREEN;
3465
3466    /**
3467     * Flags that can impact the layout in relation to system UI.
3468     */
3469    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3470            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3471            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3472
3473    /** @hide */
3474    @IntDef(flag = true,
3475            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3476    @Retention(RetentionPolicy.SOURCE)
3477    public @interface FindViewFlags {}
3478
3479    /**
3480     * Find views that render the specified text.
3481     *
3482     * @see #findViewsWithText(ArrayList, CharSequence, int)
3483     */
3484    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3485
3486    /**
3487     * Find find views that contain the specified content description.
3488     *
3489     * @see #findViewsWithText(ArrayList, CharSequence, int)
3490     */
3491    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3492
3493    /**
3494     * Find views that contain {@link AccessibilityNodeProvider}. Such
3495     * a View is a root of virtual view hierarchy and may contain the searched
3496     * text. If this flag is set Views with providers are automatically
3497     * added and it is a responsibility of the client to call the APIs of
3498     * the provider to determine whether the virtual tree rooted at this View
3499     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3500     * representing the virtual views with this text.
3501     *
3502     * @see #findViewsWithText(ArrayList, CharSequence, int)
3503     *
3504     * @hide
3505     */
3506    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3507
3508    /**
3509     * The undefined cursor position.
3510     *
3511     * @hide
3512     */
3513    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3514
3515    /**
3516     * Indicates that the screen has changed state and is now off.
3517     *
3518     * @see #onScreenStateChanged(int)
3519     */
3520    public static final int SCREEN_STATE_OFF = 0x0;
3521
3522    /**
3523     * Indicates that the screen has changed state and is now on.
3524     *
3525     * @see #onScreenStateChanged(int)
3526     */
3527    public static final int SCREEN_STATE_ON = 0x1;
3528
3529    /**
3530     * Indicates no axis of view scrolling.
3531     */
3532    public static final int SCROLL_AXIS_NONE = 0;
3533
3534    /**
3535     * Indicates scrolling along the horizontal axis.
3536     */
3537    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3538
3539    /**
3540     * Indicates scrolling along the vertical axis.
3541     */
3542    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3543
3544    /**
3545     * Controls the over-scroll mode for this view.
3546     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3547     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3548     * and {@link #OVER_SCROLL_NEVER}.
3549     */
3550    private int mOverScrollMode;
3551
3552    /**
3553     * The parent this view is attached to.
3554     * {@hide}
3555     *
3556     * @see #getParent()
3557     */
3558    protected ViewParent mParent;
3559
3560    /**
3561     * {@hide}
3562     */
3563    AttachInfo mAttachInfo;
3564
3565    /**
3566     * {@hide}
3567     */
3568    @ViewDebug.ExportedProperty(flagMapping = {
3569        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3570                name = "FORCE_LAYOUT"),
3571        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3572                name = "LAYOUT_REQUIRED"),
3573        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3574            name = "DRAWING_CACHE_INVALID", outputIf = false),
3575        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3576        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3577        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3578        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3579    }, formatToHexString = true)
3580
3581    /* @hide */
3582    public int mPrivateFlags;
3583    int mPrivateFlags2;
3584    int mPrivateFlags3;
3585
3586    /**
3587     * This view's request for the visibility of the status bar.
3588     * @hide
3589     */
3590    @ViewDebug.ExportedProperty(flagMapping = {
3591        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3592                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3593                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3594        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3595                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3596                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3597        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3598                                equals = SYSTEM_UI_FLAG_VISIBLE,
3599                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3600    }, formatToHexString = true)
3601    int mSystemUiVisibility;
3602
3603    /**
3604     * Reference count for transient state.
3605     * @see #setHasTransientState(boolean)
3606     */
3607    int mTransientStateCount = 0;
3608
3609    /**
3610     * Count of how many windows this view has been attached to.
3611     */
3612    int mWindowAttachCount;
3613
3614    /**
3615     * The layout parameters associated with this view and used by the parent
3616     * {@link android.view.ViewGroup} to determine how this view should be
3617     * laid out.
3618     * {@hide}
3619     */
3620    protected ViewGroup.LayoutParams mLayoutParams;
3621
3622    /**
3623     * The view flags hold various views states.
3624     * {@hide}
3625     */
3626    @ViewDebug.ExportedProperty(formatToHexString = true)
3627    int mViewFlags;
3628
3629    static class TransformationInfo {
3630        /**
3631         * The transform matrix for the View. This transform is calculated internally
3632         * based on the translation, rotation, and scale properties.
3633         *
3634         * Do *not* use this variable directly; instead call getMatrix(), which will
3635         * load the value from the View's RenderNode.
3636         */
3637        private final Matrix mMatrix = new Matrix();
3638
3639        /**
3640         * The inverse transform matrix for the View. This transform is calculated
3641         * internally based on the translation, rotation, and scale properties.
3642         *
3643         * Do *not* use this variable directly; instead call getInverseMatrix(),
3644         * which will load the value from the View's RenderNode.
3645         */
3646        private Matrix mInverseMatrix;
3647
3648        /**
3649         * The opacity of the View. This is a value from 0 to 1, where 0 means
3650         * completely transparent and 1 means completely opaque.
3651         */
3652        @ViewDebug.ExportedProperty
3653        float mAlpha = 1f;
3654
3655        /**
3656         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3657         * property only used by transitions, which is composited with the other alpha
3658         * values to calculate the final visual alpha value.
3659         */
3660        float mTransitionAlpha = 1f;
3661    }
3662
3663    /** @hide */
3664    public TransformationInfo mTransformationInfo;
3665
3666    /**
3667     * Current clip bounds. to which all drawing of this view are constrained.
3668     */
3669    Rect mClipBounds = null;
3670
3671    private boolean mLastIsOpaque;
3672
3673    /**
3674     * The distance in pixels from the left edge of this view's parent
3675     * to the left edge of this view.
3676     * {@hide}
3677     */
3678    @ViewDebug.ExportedProperty(category = "layout")
3679    protected int mLeft;
3680    /**
3681     * The distance in pixels from the left edge of this view's parent
3682     * to the right edge of this view.
3683     * {@hide}
3684     */
3685    @ViewDebug.ExportedProperty(category = "layout")
3686    protected int mRight;
3687    /**
3688     * The distance in pixels from the top edge of this view's parent
3689     * to the top edge of this view.
3690     * {@hide}
3691     */
3692    @ViewDebug.ExportedProperty(category = "layout")
3693    protected int mTop;
3694    /**
3695     * The distance in pixels from the top edge of this view's parent
3696     * to the bottom edge of this view.
3697     * {@hide}
3698     */
3699    @ViewDebug.ExportedProperty(category = "layout")
3700    protected int mBottom;
3701
3702    /**
3703     * The offset, in pixels, by which the content of this view is scrolled
3704     * horizontally.
3705     * {@hide}
3706     */
3707    @ViewDebug.ExportedProperty(category = "scrolling")
3708    protected int mScrollX;
3709    /**
3710     * The offset, in pixels, by which the content of this view is scrolled
3711     * vertically.
3712     * {@hide}
3713     */
3714    @ViewDebug.ExportedProperty(category = "scrolling")
3715    protected int mScrollY;
3716
3717    /**
3718     * The left padding in pixels, that is the distance in pixels between the
3719     * left edge of this view and the left edge of its content.
3720     * {@hide}
3721     */
3722    @ViewDebug.ExportedProperty(category = "padding")
3723    protected int mPaddingLeft = 0;
3724    /**
3725     * The right padding in pixels, that is the distance in pixels between the
3726     * right edge of this view and the right edge of its content.
3727     * {@hide}
3728     */
3729    @ViewDebug.ExportedProperty(category = "padding")
3730    protected int mPaddingRight = 0;
3731    /**
3732     * The top padding in pixels, that is the distance in pixels between the
3733     * top edge of this view and the top edge of its content.
3734     * {@hide}
3735     */
3736    @ViewDebug.ExportedProperty(category = "padding")
3737    protected int mPaddingTop;
3738    /**
3739     * The bottom padding in pixels, that is the distance in pixels between the
3740     * bottom edge of this view and the bottom edge of its content.
3741     * {@hide}
3742     */
3743    @ViewDebug.ExportedProperty(category = "padding")
3744    protected int mPaddingBottom;
3745
3746    /**
3747     * The layout insets in pixels, that is the distance in pixels between the
3748     * visible edges of this view its bounds.
3749     */
3750    private Insets mLayoutInsets;
3751
3752    /**
3753     * Briefly describes the view and is primarily used for accessibility support.
3754     */
3755    private CharSequence mContentDescription;
3756
3757    /**
3758     * Specifies the id of a view for which this view serves as a label for
3759     * accessibility purposes.
3760     */
3761    private int mLabelForId = View.NO_ID;
3762
3763    /**
3764     * Predicate for matching labeled view id with its label for
3765     * accessibility purposes.
3766     */
3767    private MatchLabelForPredicate mMatchLabelForPredicate;
3768
3769    /**
3770     * Specifies a view before which this one is visited in accessibility traversal.
3771     */
3772    private int mAccessibilityTraversalBeforeId = NO_ID;
3773
3774    /**
3775     * Specifies a view after which this one is visited in accessibility traversal.
3776     */
3777    private int mAccessibilityTraversalAfterId = NO_ID;
3778
3779    /**
3780     * Predicate for matching a view by its id.
3781     */
3782    private MatchIdPredicate mMatchIdPredicate;
3783
3784    /**
3785     * Cache the paddingRight set by the user to append to the scrollbar's size.
3786     *
3787     * @hide
3788     */
3789    @ViewDebug.ExportedProperty(category = "padding")
3790    protected int mUserPaddingRight;
3791
3792    /**
3793     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3794     *
3795     * @hide
3796     */
3797    @ViewDebug.ExportedProperty(category = "padding")
3798    protected int mUserPaddingBottom;
3799
3800    /**
3801     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3802     *
3803     * @hide
3804     */
3805    @ViewDebug.ExportedProperty(category = "padding")
3806    protected int mUserPaddingLeft;
3807
3808    /**
3809     * Cache the paddingStart set by the user to append to the scrollbar's size.
3810     *
3811     */
3812    @ViewDebug.ExportedProperty(category = "padding")
3813    int mUserPaddingStart;
3814
3815    /**
3816     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3817     *
3818     */
3819    @ViewDebug.ExportedProperty(category = "padding")
3820    int mUserPaddingEnd;
3821
3822    /**
3823     * Cache initial left padding.
3824     *
3825     * @hide
3826     */
3827    int mUserPaddingLeftInitial;
3828
3829    /**
3830     * Cache initial right padding.
3831     *
3832     * @hide
3833     */
3834    int mUserPaddingRightInitial;
3835
3836    /**
3837     * Default undefined padding
3838     */
3839    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3840
3841    /**
3842     * Cache if a left padding has been defined
3843     */
3844    private boolean mLeftPaddingDefined = false;
3845
3846    /**
3847     * Cache if a right padding has been defined
3848     */
3849    private boolean mRightPaddingDefined = false;
3850
3851    /**
3852     * @hide
3853     */
3854    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3855    /**
3856     * @hide
3857     */
3858    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3859
3860    private LongSparseLongArray mMeasureCache;
3861
3862    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3863    private Drawable mBackground;
3864    private TintInfo mBackgroundTint;
3865
3866    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3867    private ForegroundInfo mForegroundInfo;
3868
3869    private Drawable mScrollIndicatorDrawable;
3870
3871    /**
3872     * RenderNode used for backgrounds.
3873     * <p>
3874     * When non-null and valid, this is expected to contain an up-to-date copy
3875     * of the background drawable. It is cleared on temporary detach, and reset
3876     * on cleanup.
3877     */
3878    private RenderNode mBackgroundRenderNode;
3879
3880    private int mBackgroundResource;
3881    private boolean mBackgroundSizeChanged;
3882
3883    /** The default focus highlight.
3884     * @see #mDefaultFocusHighlightEnabled
3885     * @see Drawable#hasFocusStateSpecified()
3886     */
3887    private Drawable mDefaultFocusHighlight;
3888    private Drawable mDefaultFocusHighlightCache;
3889    private boolean mDefaultFocusHighlightSizeChanged;
3890    /**
3891     * True if the default focus highlight is needed on the target device.
3892     */
3893    private static boolean sUseDefaultFocusHighlight;
3894
3895    private String mTransitionName;
3896
3897    static class TintInfo {
3898        ColorStateList mTintList;
3899        PorterDuff.Mode mTintMode;
3900        boolean mHasTintMode;
3901        boolean mHasTintList;
3902    }
3903
3904    private static class ForegroundInfo {
3905        private Drawable mDrawable;
3906        private TintInfo mTintInfo;
3907        private int mGravity = Gravity.FILL;
3908        private boolean mInsidePadding = true;
3909        private boolean mBoundsChanged = true;
3910        private final Rect mSelfBounds = new Rect();
3911        private final Rect mOverlayBounds = new Rect();
3912    }
3913
3914    static class ListenerInfo {
3915        /**
3916         * Listener used to dispatch focus change events.
3917         * This field should be made private, so it is hidden from the SDK.
3918         * {@hide}
3919         */
3920        protected OnFocusChangeListener mOnFocusChangeListener;
3921
3922        /**
3923         * Listeners for layout change events.
3924         */
3925        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3926
3927        protected OnScrollChangeListener mOnScrollChangeListener;
3928
3929        /**
3930         * Listeners for attach events.
3931         */
3932        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3933
3934        /**
3935         * Listener used to dispatch click events.
3936         * This field should be made private, so it is hidden from the SDK.
3937         * {@hide}
3938         */
3939        public OnClickListener mOnClickListener;
3940
3941        /**
3942         * Listener used to dispatch long click events.
3943         * This field should be made private, so it is hidden from the SDK.
3944         * {@hide}
3945         */
3946        protected OnLongClickListener mOnLongClickListener;
3947
3948        /**
3949         * Listener used to dispatch context click events. This field should be made private, so it
3950         * is hidden from the SDK.
3951         * {@hide}
3952         */
3953        protected OnContextClickListener mOnContextClickListener;
3954
3955        /**
3956         * Listener used to build the context menu.
3957         * This field should be made private, so it is hidden from the SDK.
3958         * {@hide}
3959         */
3960        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3961
3962        private OnKeyListener mOnKeyListener;
3963
3964        private OnTouchListener mOnTouchListener;
3965
3966        private OnHoverListener mOnHoverListener;
3967
3968        private OnGenericMotionListener mOnGenericMotionListener;
3969
3970        private OnDragListener mOnDragListener;
3971
3972        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3973
3974        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3975
3976        OnCapturedPointerListener mOnCapturedPointerListener;
3977    }
3978
3979    ListenerInfo mListenerInfo;
3980
3981    private static class TooltipInfo {
3982        /**
3983         * Text to be displayed in a tooltip popup.
3984         */
3985        @Nullable
3986        CharSequence mTooltipText;
3987
3988        /**
3989         * View-relative position of the tooltip anchor point.
3990         */
3991        int mAnchorX;
3992        int mAnchorY;
3993
3994        /**
3995         * The tooltip popup.
3996         */
3997        @Nullable
3998        TooltipPopup mTooltipPopup;
3999
4000        /**
4001         * Set to true if the tooltip was shown as a result of a long click.
4002         */
4003        boolean mTooltipFromLongClick;
4004
4005        /**
4006         * Keep these Runnables so that they can be used to reschedule.
4007         */
4008        Runnable mShowTooltipRunnable;
4009        Runnable mHideTooltipRunnable;
4010    }
4011
4012    TooltipInfo mTooltipInfo;
4013
4014    // Temporary values used to hold (x,y) coordinates when delegating from the
4015    // two-arg performLongClick() method to the legacy no-arg version.
4016    private float mLongClickX = Float.NaN;
4017    private float mLongClickY = Float.NaN;
4018
4019    /**
4020     * The application environment this view lives in.
4021     * This field should be made private, so it is hidden from the SDK.
4022     * {@hide}
4023     */
4024    @ViewDebug.ExportedProperty(deepExport = true)
4025    protected Context mContext;
4026
4027    private final Resources mResources;
4028
4029    private ScrollabilityCache mScrollCache;
4030
4031    private int[] mDrawableState = null;
4032
4033    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4034
4035    /**
4036     * Animator that automatically runs based on state changes.
4037     */
4038    private StateListAnimator mStateListAnimator;
4039
4040    /**
4041     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4042     * the user may specify which view to go to next.
4043     */
4044    private int mNextFocusLeftId = View.NO_ID;
4045
4046    /**
4047     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4048     * the user may specify which view to go to next.
4049     */
4050    private int mNextFocusRightId = View.NO_ID;
4051
4052    /**
4053     * When this view has focus and the next focus is {@link #FOCUS_UP},
4054     * the user may specify which view to go to next.
4055     */
4056    private int mNextFocusUpId = View.NO_ID;
4057
4058    /**
4059     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4060     * the user may specify which view to go to next.
4061     */
4062    private int mNextFocusDownId = View.NO_ID;
4063
4064    /**
4065     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4066     * the user may specify which view to go to next.
4067     */
4068    int mNextFocusForwardId = View.NO_ID;
4069
4070    /**
4071     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4072     *
4073     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4074     */
4075    int mNextClusterForwardId = View.NO_ID;
4076
4077    /**
4078     * Whether this View should use a default focus highlight when it gets focused but doesn't
4079     * have {@link android.R.attr#state_focused} defined in its background.
4080     */
4081    boolean mDefaultFocusHighlightEnabled = true;
4082
4083    private CheckForLongPress mPendingCheckForLongPress;
4084    private CheckForTap mPendingCheckForTap = null;
4085    private PerformClick mPerformClick;
4086    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4087
4088    private UnsetPressedState mUnsetPressedState;
4089
4090    /**
4091     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4092     * up event while a long press is invoked as soon as the long press duration is reached, so
4093     * a long press could be performed before the tap is checked, in which case the tap's action
4094     * should not be invoked.
4095     */
4096    private boolean mHasPerformedLongPress;
4097
4098    /**
4099     * Whether a context click button is currently pressed down. This is true when the stylus is
4100     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4101     * pressed. This is false once the button is released or if the stylus has been lifted.
4102     */
4103    private boolean mInContextButtonPress;
4104
4105    /**
4106     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4107     * true after a stylus button press has occured, when the next up event should not be recognized
4108     * as a tap.
4109     */
4110    private boolean mIgnoreNextUpEvent;
4111
4112    /**
4113     * The minimum height of the view. We'll try our best to have the height
4114     * of this view to at least this amount.
4115     */
4116    @ViewDebug.ExportedProperty(category = "measurement")
4117    private int mMinHeight;
4118
4119    /**
4120     * The minimum width of the view. We'll try our best to have the width
4121     * of this view to at least this amount.
4122     */
4123    @ViewDebug.ExportedProperty(category = "measurement")
4124    private int mMinWidth;
4125
4126    /**
4127     * The delegate to handle touch events that are physically in this view
4128     * but should be handled by another view.
4129     */
4130    private TouchDelegate mTouchDelegate = null;
4131
4132    /**
4133     * Solid color to use as a background when creating the drawing cache. Enables
4134     * the cache to use 16 bit bitmaps instead of 32 bit.
4135     */
4136    private int mDrawingCacheBackgroundColor = 0;
4137
4138    /**
4139     * Special tree observer used when mAttachInfo is null.
4140     */
4141    private ViewTreeObserver mFloatingTreeObserver;
4142
4143    /**
4144     * Cache the touch slop from the context that created the view.
4145     */
4146    private int mTouchSlop;
4147
4148    /**
4149     * Object that handles automatic animation of view properties.
4150     */
4151    private ViewPropertyAnimator mAnimator = null;
4152
4153    /**
4154     * List of registered FrameMetricsObservers.
4155     */
4156    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4157
4158    /**
4159     * Flag indicating that a drag can cross window boundaries.  When
4160     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4161     * with this flag set, all visible applications with targetSdkVersion >=
4162     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4163     * in the drag operation and receive the dragged content.
4164     *
4165     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4166     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4167     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4168     */
4169    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4170
4171    /**
4172     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4173     * request read access to the content URI(s) contained in the {@link ClipData} object.
4174     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4175     */
4176    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4177
4178    /**
4179     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4180     * request write access to the content URI(s) contained in the {@link ClipData} object.
4181     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4182     */
4183    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4184
4185    /**
4186     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4187     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4188     * reboots until explicitly revoked with
4189     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4190     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4191     */
4192    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4193            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4194
4195    /**
4196     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4197     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4198     * match against the original granted URI.
4199     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4200     */
4201    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4202            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4203
4204    /**
4205     * Flag indicating that the drag shadow will be opaque.  When
4206     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4207     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4208     */
4209    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4210
4211    /**
4212     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4213     */
4214    private float mVerticalScrollFactor;
4215
4216    /**
4217     * Position of the vertical scroll bar.
4218     */
4219    private int mVerticalScrollbarPosition;
4220
4221    /**
4222     * Position the scroll bar at the default position as determined by the system.
4223     */
4224    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4225
4226    /**
4227     * Position the scroll bar along the left edge.
4228     */
4229    public static final int SCROLLBAR_POSITION_LEFT = 1;
4230
4231    /**
4232     * Position the scroll bar along the right edge.
4233     */
4234    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4235
4236    /**
4237     * Indicates that the view does not have a layer.
4238     *
4239     * @see #getLayerType()
4240     * @see #setLayerType(int, android.graphics.Paint)
4241     * @see #LAYER_TYPE_SOFTWARE
4242     * @see #LAYER_TYPE_HARDWARE
4243     */
4244    public static final int LAYER_TYPE_NONE = 0;
4245
4246    /**
4247     * <p>Indicates that the view has a software layer. A software layer is backed
4248     * by a bitmap and causes the view to be rendered using Android's software
4249     * rendering pipeline, even if hardware acceleration is enabled.</p>
4250     *
4251     * <p>Software layers have various usages:</p>
4252     * <p>When the application is not using hardware acceleration, a software layer
4253     * is useful to apply a specific color filter and/or blending mode and/or
4254     * translucency to a view and all its children.</p>
4255     * <p>When the application is using hardware acceleration, a software layer
4256     * is useful to render drawing primitives not supported by the hardware
4257     * accelerated pipeline. It can also be used to cache a complex view tree
4258     * into a texture and reduce the complexity of drawing operations. For instance,
4259     * when animating a complex view tree with a translation, a software layer can
4260     * be used to render the view tree only once.</p>
4261     * <p>Software layers should be avoided when the affected view tree updates
4262     * often. Every update will require to re-render the software layer, which can
4263     * potentially be slow (particularly when hardware acceleration is turned on
4264     * since the layer will have to be uploaded into a hardware texture after every
4265     * update.)</p>
4266     *
4267     * @see #getLayerType()
4268     * @see #setLayerType(int, android.graphics.Paint)
4269     * @see #LAYER_TYPE_NONE
4270     * @see #LAYER_TYPE_HARDWARE
4271     */
4272    public static final int LAYER_TYPE_SOFTWARE = 1;
4273
4274    /**
4275     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4276     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4277     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4278     * rendering pipeline, but only if hardware acceleration is turned on for the
4279     * view hierarchy. When hardware acceleration is turned off, hardware layers
4280     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4281     *
4282     * <p>A hardware layer is useful to apply a specific color filter and/or
4283     * blending mode and/or translucency to a view and all its children.</p>
4284     * <p>A hardware layer can be used to cache a complex view tree into a
4285     * texture and reduce the complexity of drawing operations. For instance,
4286     * when animating a complex view tree with a translation, a hardware layer can
4287     * be used to render the view tree only once.</p>
4288     * <p>A hardware layer can also be used to increase the rendering quality when
4289     * rotation transformations are applied on a view. It can also be used to
4290     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4291     *
4292     * @see #getLayerType()
4293     * @see #setLayerType(int, android.graphics.Paint)
4294     * @see #LAYER_TYPE_NONE
4295     * @see #LAYER_TYPE_SOFTWARE
4296     */
4297    public static final int LAYER_TYPE_HARDWARE = 2;
4298
4299    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4300            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4301            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4302            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4303    })
4304    int mLayerType = LAYER_TYPE_NONE;
4305    Paint mLayerPaint;
4306
4307    /**
4308     * Set to true when drawing cache is enabled and cannot be created.
4309     *
4310     * @hide
4311     */
4312    public boolean mCachingFailed;
4313    private Bitmap mDrawingCache;
4314    private Bitmap mUnscaledDrawingCache;
4315
4316    /**
4317     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4318     * <p>
4319     * When non-null and valid, this is expected to contain an up-to-date copy
4320     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4321     * cleanup.
4322     */
4323    final RenderNode mRenderNode;
4324
4325    /**
4326     * Set to true when the view is sending hover accessibility events because it
4327     * is the innermost hovered view.
4328     */
4329    private boolean mSendingHoverAccessibilityEvents;
4330
4331    /**
4332     * Delegate for injecting accessibility functionality.
4333     */
4334    AccessibilityDelegate mAccessibilityDelegate;
4335
4336    /**
4337     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4338     * and add/remove objects to/from the overlay directly through the Overlay methods.
4339     */
4340    ViewOverlay mOverlay;
4341
4342    /**
4343     * The currently active parent view for receiving delegated nested scrolling events.
4344     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4345     * by {@link #stopNestedScroll()} at the same point where we clear
4346     * requestDisallowInterceptTouchEvent.
4347     */
4348    private ViewParent mNestedScrollingParent;
4349
4350    /**
4351     * Consistency verifier for debugging purposes.
4352     * @hide
4353     */
4354    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4355            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4356                    new InputEventConsistencyVerifier(this, 0) : null;
4357
4358    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4359
4360    private int[] mTempNestedScrollConsumed;
4361
4362    /**
4363     * An overlay is going to draw this View instead of being drawn as part of this
4364     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4365     * when this view is invalidated.
4366     */
4367    GhostView mGhostView;
4368
4369    /**
4370     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4371     * @hide
4372     */
4373    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4374    public String[] mAttributes;
4375
4376    /**
4377     * Maps a Resource id to its name.
4378     */
4379    private static SparseArray<String> mAttributeMap;
4380
4381    /**
4382     * Queue of pending runnables. Used to postpone calls to post() until this
4383     * view is attached and has a handler.
4384     */
4385    private HandlerActionQueue mRunQueue;
4386
4387    /**
4388     * The pointer icon when the mouse hovers on this view. The default is null.
4389     */
4390    private PointerIcon mPointerIcon;
4391
4392    /**
4393     * @hide
4394     */
4395    String mStartActivityRequestWho;
4396
4397    @Nullable
4398    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4399
4400    /** Used to delay visibility updates sent to the autofill manager */
4401    private Handler mVisibilityChangeForAutofillHandler;
4402
4403    /**
4404     * Simple constructor to use when creating a view from code.
4405     *
4406     * @param context The Context the view is running in, through which it can
4407     *        access the current theme, resources, etc.
4408     */
4409    public View(Context context) {
4410        mContext = context;
4411        mResources = context != null ? context.getResources() : null;
4412        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4413        // Set some flags defaults
4414        mPrivateFlags2 =
4415                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4416                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4417                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4418                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4419                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4420                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4421        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4422        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4423        mUserPaddingStart = UNDEFINED_PADDING;
4424        mUserPaddingEnd = UNDEFINED_PADDING;
4425        mRenderNode = RenderNode.create(getClass().getName(), this);
4426
4427        if (!sCompatibilityDone && context != null) {
4428            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4429
4430            // Older apps may need this compatibility hack for measurement.
4431            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4432
4433            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4434            // of whether a layout was requested on that View.
4435            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4436
4437            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4438
4439            // In M and newer, our widgets can pass a "hint" value in the size
4440            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4441            // know what the expected parent size is going to be, so e.g. list items can size
4442            // themselves at 1/3 the size of their container. It breaks older apps though,
4443            // specifically apps that use some popular open source libraries.
4444            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4445
4446            // Old versions of the platform would give different results from
4447            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4448            // modes, so we always need to run an additional EXACTLY pass.
4449            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4450
4451            // Prior to N, layout params could change without requiring a
4452            // subsequent call to setLayoutParams() and they would usually
4453            // work. Partial layout breaks this assumption.
4454            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4455
4456            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4457            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4458            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4459
4460            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4461            // in apps so we target check it to avoid breaking existing apps.
4462            sPreserveMarginParamsInLayoutParamConversion =
4463                    targetSdkVersion >= Build.VERSION_CODES.N;
4464
4465            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4466
4467            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4468
4469            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4470
4471            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4472                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4473
4474            sCompatibilityDone = true;
4475        }
4476    }
4477
4478    /**
4479     * Constructor that is called when inflating a view from XML. This is called
4480     * when a view is being constructed from an XML file, supplying attributes
4481     * that were specified in the XML file. This version uses a default style of
4482     * 0, so the only attribute values applied are those in the Context's Theme
4483     * and the given AttributeSet.
4484     *
4485     * <p>
4486     * The method onFinishInflate() will be called after all children have been
4487     * added.
4488     *
4489     * @param context The Context the view is running in, through which it can
4490     *        access the current theme, resources, etc.
4491     * @param attrs The attributes of the XML tag that is inflating the view.
4492     * @see #View(Context, AttributeSet, int)
4493     */
4494    public View(Context context, @Nullable AttributeSet attrs) {
4495        this(context, attrs, 0);
4496    }
4497
4498    /**
4499     * Perform inflation from XML and apply a class-specific base style from a
4500     * theme attribute. This constructor of View allows subclasses to use their
4501     * own base style when they are inflating. For example, a Button class's
4502     * constructor would call this version of the super class constructor and
4503     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4504     * allows the theme's button style to modify all of the base view attributes
4505     * (in particular its background) as well as the Button class's attributes.
4506     *
4507     * @param context The Context the view is running in, through which it can
4508     *        access the current theme, resources, etc.
4509     * @param attrs The attributes of the XML tag that is inflating the view.
4510     * @param defStyleAttr An attribute in the current theme that contains a
4511     *        reference to a style resource that supplies default values for
4512     *        the view. Can be 0 to not look for defaults.
4513     * @see #View(Context, AttributeSet)
4514     */
4515    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4516        this(context, attrs, defStyleAttr, 0);
4517    }
4518
4519    /**
4520     * Perform inflation from XML and apply a class-specific base style from a
4521     * theme attribute or style resource. This constructor of View allows
4522     * subclasses to use their own base style when they are inflating.
4523     * <p>
4524     * When determining the final value of a particular attribute, there are
4525     * four inputs that come into play:
4526     * <ol>
4527     * <li>Any attribute values in the given AttributeSet.
4528     * <li>The style resource specified in the AttributeSet (named "style").
4529     * <li>The default style specified by <var>defStyleAttr</var>.
4530     * <li>The default style specified by <var>defStyleRes</var>.
4531     * <li>The base values in this theme.
4532     * </ol>
4533     * <p>
4534     * Each of these inputs is considered in-order, with the first listed taking
4535     * precedence over the following ones. In other words, if in the
4536     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4537     * , then the button's text will <em>always</em> be black, regardless of
4538     * what is specified in any of the styles.
4539     *
4540     * @param context The Context the view is running in, through which it can
4541     *        access the current theme, resources, etc.
4542     * @param attrs The attributes of the XML tag that is inflating the view.
4543     * @param defStyleAttr An attribute in the current theme that contains a
4544     *        reference to a style resource that supplies default values for
4545     *        the view. Can be 0 to not look for defaults.
4546     * @param defStyleRes A resource identifier of a style resource that
4547     *        supplies default values for the view, used only if
4548     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4549     *        to not look for defaults.
4550     * @see #View(Context, AttributeSet, int)
4551     */
4552    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4553        this(context);
4554
4555        final TypedArray a = context.obtainStyledAttributes(
4556                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4557
4558        if (mDebugViewAttributes) {
4559            saveAttributeData(attrs, a);
4560        }
4561
4562        Drawable background = null;
4563
4564        int leftPadding = -1;
4565        int topPadding = -1;
4566        int rightPadding = -1;
4567        int bottomPadding = -1;
4568        int startPadding = UNDEFINED_PADDING;
4569        int endPadding = UNDEFINED_PADDING;
4570
4571        int padding = -1;
4572        int paddingHorizontal = -1;
4573        int paddingVertical = -1;
4574
4575        int viewFlagValues = 0;
4576        int viewFlagMasks = 0;
4577
4578        boolean setScrollContainer = false;
4579
4580        int x = 0;
4581        int y = 0;
4582
4583        float tx = 0;
4584        float ty = 0;
4585        float tz = 0;
4586        float elevation = 0;
4587        float rotation = 0;
4588        float rotationX = 0;
4589        float rotationY = 0;
4590        float sx = 1f;
4591        float sy = 1f;
4592        boolean transformSet = false;
4593
4594        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4595        int overScrollMode = mOverScrollMode;
4596        boolean initializeScrollbars = false;
4597        boolean initializeScrollIndicators = false;
4598
4599        boolean startPaddingDefined = false;
4600        boolean endPaddingDefined = false;
4601        boolean leftPaddingDefined = false;
4602        boolean rightPaddingDefined = false;
4603
4604        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4605
4606        // Set default values.
4607        viewFlagValues |= FOCUSABLE_AUTO;
4608        viewFlagMasks |= FOCUSABLE_AUTO;
4609
4610        final int N = a.getIndexCount();
4611        for (int i = 0; i < N; i++) {
4612            int attr = a.getIndex(i);
4613            switch (attr) {
4614                case com.android.internal.R.styleable.View_background:
4615                    background = a.getDrawable(attr);
4616                    break;
4617                case com.android.internal.R.styleable.View_padding:
4618                    padding = a.getDimensionPixelSize(attr, -1);
4619                    mUserPaddingLeftInitial = padding;
4620                    mUserPaddingRightInitial = padding;
4621                    leftPaddingDefined = true;
4622                    rightPaddingDefined = true;
4623                    break;
4624                case com.android.internal.R.styleable.View_paddingHorizontal:
4625                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4626                    mUserPaddingLeftInitial = paddingHorizontal;
4627                    mUserPaddingRightInitial = paddingHorizontal;
4628                    leftPaddingDefined = true;
4629                    rightPaddingDefined = true;
4630                    break;
4631                case com.android.internal.R.styleable.View_paddingVertical:
4632                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4633                    break;
4634                 case com.android.internal.R.styleable.View_paddingLeft:
4635                    leftPadding = a.getDimensionPixelSize(attr, -1);
4636                    mUserPaddingLeftInitial = leftPadding;
4637                    leftPaddingDefined = true;
4638                    break;
4639                case com.android.internal.R.styleable.View_paddingTop:
4640                    topPadding = a.getDimensionPixelSize(attr, -1);
4641                    break;
4642                case com.android.internal.R.styleable.View_paddingRight:
4643                    rightPadding = a.getDimensionPixelSize(attr, -1);
4644                    mUserPaddingRightInitial = rightPadding;
4645                    rightPaddingDefined = true;
4646                    break;
4647                case com.android.internal.R.styleable.View_paddingBottom:
4648                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4649                    break;
4650                case com.android.internal.R.styleable.View_paddingStart:
4651                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4652                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4653                    break;
4654                case com.android.internal.R.styleable.View_paddingEnd:
4655                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4656                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4657                    break;
4658                case com.android.internal.R.styleable.View_scrollX:
4659                    x = a.getDimensionPixelOffset(attr, 0);
4660                    break;
4661                case com.android.internal.R.styleable.View_scrollY:
4662                    y = a.getDimensionPixelOffset(attr, 0);
4663                    break;
4664                case com.android.internal.R.styleable.View_alpha:
4665                    setAlpha(a.getFloat(attr, 1f));
4666                    break;
4667                case com.android.internal.R.styleable.View_transformPivotX:
4668                    setPivotX(a.getDimension(attr, 0));
4669                    break;
4670                case com.android.internal.R.styleable.View_transformPivotY:
4671                    setPivotY(a.getDimension(attr, 0));
4672                    break;
4673                case com.android.internal.R.styleable.View_translationX:
4674                    tx = a.getDimension(attr, 0);
4675                    transformSet = true;
4676                    break;
4677                case com.android.internal.R.styleable.View_translationY:
4678                    ty = a.getDimension(attr, 0);
4679                    transformSet = true;
4680                    break;
4681                case com.android.internal.R.styleable.View_translationZ:
4682                    tz = a.getDimension(attr, 0);
4683                    transformSet = true;
4684                    break;
4685                case com.android.internal.R.styleable.View_elevation:
4686                    elevation = a.getDimension(attr, 0);
4687                    transformSet = true;
4688                    break;
4689                case com.android.internal.R.styleable.View_rotation:
4690                    rotation = a.getFloat(attr, 0);
4691                    transformSet = true;
4692                    break;
4693                case com.android.internal.R.styleable.View_rotationX:
4694                    rotationX = a.getFloat(attr, 0);
4695                    transformSet = true;
4696                    break;
4697                case com.android.internal.R.styleable.View_rotationY:
4698                    rotationY = a.getFloat(attr, 0);
4699                    transformSet = true;
4700                    break;
4701                case com.android.internal.R.styleable.View_scaleX:
4702                    sx = a.getFloat(attr, 1f);
4703                    transformSet = true;
4704                    break;
4705                case com.android.internal.R.styleable.View_scaleY:
4706                    sy = a.getFloat(attr, 1f);
4707                    transformSet = true;
4708                    break;
4709                case com.android.internal.R.styleable.View_id:
4710                    mID = a.getResourceId(attr, NO_ID);
4711                    break;
4712                case com.android.internal.R.styleable.View_tag:
4713                    mTag = a.getText(attr);
4714                    break;
4715                case com.android.internal.R.styleable.View_fitsSystemWindows:
4716                    if (a.getBoolean(attr, false)) {
4717                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4718                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4719                    }
4720                    break;
4721                case com.android.internal.R.styleable.View_focusable:
4722                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4723                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4724                        viewFlagMasks |= FOCUSABLE_MASK;
4725                    }
4726                    break;
4727                case com.android.internal.R.styleable.View_focusableInTouchMode:
4728                    if (a.getBoolean(attr, false)) {
4729                        // unset auto focus since focusableInTouchMode implies explicit focusable
4730                        viewFlagValues &= ~FOCUSABLE_AUTO;
4731                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4732                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4733                    }
4734                    break;
4735                case com.android.internal.R.styleable.View_clickable:
4736                    if (a.getBoolean(attr, false)) {
4737                        viewFlagValues |= CLICKABLE;
4738                        viewFlagMasks |= CLICKABLE;
4739                    }
4740                    break;
4741                case com.android.internal.R.styleable.View_longClickable:
4742                    if (a.getBoolean(attr, false)) {
4743                        viewFlagValues |= LONG_CLICKABLE;
4744                        viewFlagMasks |= LONG_CLICKABLE;
4745                    }
4746                    break;
4747                case com.android.internal.R.styleable.View_contextClickable:
4748                    if (a.getBoolean(attr, false)) {
4749                        viewFlagValues |= CONTEXT_CLICKABLE;
4750                        viewFlagMasks |= CONTEXT_CLICKABLE;
4751                    }
4752                    break;
4753                case com.android.internal.R.styleable.View_saveEnabled:
4754                    if (!a.getBoolean(attr, true)) {
4755                        viewFlagValues |= SAVE_DISABLED;
4756                        viewFlagMasks |= SAVE_DISABLED_MASK;
4757                    }
4758                    break;
4759                case com.android.internal.R.styleable.View_duplicateParentState:
4760                    if (a.getBoolean(attr, false)) {
4761                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4762                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4763                    }
4764                    break;
4765                case com.android.internal.R.styleable.View_visibility:
4766                    final int visibility = a.getInt(attr, 0);
4767                    if (visibility != 0) {
4768                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4769                        viewFlagMasks |= VISIBILITY_MASK;
4770                    }
4771                    break;
4772                case com.android.internal.R.styleable.View_layoutDirection:
4773                    // Clear any layout direction flags (included resolved bits) already set
4774                    mPrivateFlags2 &=
4775                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4776                    // Set the layout direction flags depending on the value of the attribute
4777                    final int layoutDirection = a.getInt(attr, -1);
4778                    final int value = (layoutDirection != -1) ?
4779                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4780                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4781                    break;
4782                case com.android.internal.R.styleable.View_drawingCacheQuality:
4783                    final int cacheQuality = a.getInt(attr, 0);
4784                    if (cacheQuality != 0) {
4785                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4786                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4787                    }
4788                    break;
4789                case com.android.internal.R.styleable.View_contentDescription:
4790                    setContentDescription(a.getString(attr));
4791                    break;
4792                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4793                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4794                    break;
4795                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4796                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4797                    break;
4798                case com.android.internal.R.styleable.View_labelFor:
4799                    setLabelFor(a.getResourceId(attr, NO_ID));
4800                    break;
4801                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4802                    if (!a.getBoolean(attr, true)) {
4803                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4804                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4805                    }
4806                    break;
4807                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4808                    if (!a.getBoolean(attr, true)) {
4809                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4810                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4811                    }
4812                    break;
4813                case R.styleable.View_scrollbars:
4814                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4815                    if (scrollbars != SCROLLBARS_NONE) {
4816                        viewFlagValues |= scrollbars;
4817                        viewFlagMasks |= SCROLLBARS_MASK;
4818                        initializeScrollbars = true;
4819                    }
4820                    break;
4821                //noinspection deprecation
4822                case R.styleable.View_fadingEdge:
4823                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4824                        // Ignore the attribute starting with ICS
4825                        break;
4826                    }
4827                    // With builds < ICS, fall through and apply fading edges
4828                case R.styleable.View_requiresFadingEdge:
4829                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4830                    if (fadingEdge != FADING_EDGE_NONE) {
4831                        viewFlagValues |= fadingEdge;
4832                        viewFlagMasks |= FADING_EDGE_MASK;
4833                        initializeFadingEdgeInternal(a);
4834                    }
4835                    break;
4836                case R.styleable.View_scrollbarStyle:
4837                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4838                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4839                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4840                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4841                    }
4842                    break;
4843                case R.styleable.View_isScrollContainer:
4844                    setScrollContainer = true;
4845                    if (a.getBoolean(attr, false)) {
4846                        setScrollContainer(true);
4847                    }
4848                    break;
4849                case com.android.internal.R.styleable.View_keepScreenOn:
4850                    if (a.getBoolean(attr, false)) {
4851                        viewFlagValues |= KEEP_SCREEN_ON;
4852                        viewFlagMasks |= KEEP_SCREEN_ON;
4853                    }
4854                    break;
4855                case R.styleable.View_filterTouchesWhenObscured:
4856                    if (a.getBoolean(attr, false)) {
4857                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4858                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4859                    }
4860                    break;
4861                case R.styleable.View_nextFocusLeft:
4862                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4863                    break;
4864                case R.styleable.View_nextFocusRight:
4865                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4866                    break;
4867                case R.styleable.View_nextFocusUp:
4868                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4869                    break;
4870                case R.styleable.View_nextFocusDown:
4871                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4872                    break;
4873                case R.styleable.View_nextFocusForward:
4874                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4875                    break;
4876                case R.styleable.View_nextClusterForward:
4877                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4878                    break;
4879                case R.styleable.View_minWidth:
4880                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4881                    break;
4882                case R.styleable.View_minHeight:
4883                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4884                    break;
4885                case R.styleable.View_onClick:
4886                    if (context.isRestricted()) {
4887                        throw new IllegalStateException("The android:onClick attribute cannot "
4888                                + "be used within a restricted context");
4889                    }
4890
4891                    final String handlerName = a.getString(attr);
4892                    if (handlerName != null) {
4893                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4894                    }
4895                    break;
4896                case R.styleable.View_overScrollMode:
4897                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4898                    break;
4899                case R.styleable.View_verticalScrollbarPosition:
4900                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4901                    break;
4902                case R.styleable.View_layerType:
4903                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4904                    break;
4905                case R.styleable.View_textDirection:
4906                    // Clear any text direction flag already set
4907                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4908                    // Set the text direction flags depending on the value of the attribute
4909                    final int textDirection = a.getInt(attr, -1);
4910                    if (textDirection != -1) {
4911                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4912                    }
4913                    break;
4914                case R.styleable.View_textAlignment:
4915                    // Clear any text alignment flag already set
4916                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4917                    // Set the text alignment flag depending on the value of the attribute
4918                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4919                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4920                    break;
4921                case R.styleable.View_importantForAccessibility:
4922                    setImportantForAccessibility(a.getInt(attr,
4923                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4924                    break;
4925                case R.styleable.View_accessibilityLiveRegion:
4926                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4927                    break;
4928                case R.styleable.View_transitionName:
4929                    setTransitionName(a.getString(attr));
4930                    break;
4931                case R.styleable.View_nestedScrollingEnabled:
4932                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4933                    break;
4934                case R.styleable.View_stateListAnimator:
4935                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4936                            a.getResourceId(attr, 0)));
4937                    break;
4938                case R.styleable.View_backgroundTint:
4939                    // This will get applied later during setBackground().
4940                    if (mBackgroundTint == null) {
4941                        mBackgroundTint = new TintInfo();
4942                    }
4943                    mBackgroundTint.mTintList = a.getColorStateList(
4944                            R.styleable.View_backgroundTint);
4945                    mBackgroundTint.mHasTintList = true;
4946                    break;
4947                case R.styleable.View_backgroundTintMode:
4948                    // This will get applied later during setBackground().
4949                    if (mBackgroundTint == null) {
4950                        mBackgroundTint = new TintInfo();
4951                    }
4952                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4953                            R.styleable.View_backgroundTintMode, -1), null);
4954                    mBackgroundTint.mHasTintMode = true;
4955                    break;
4956                case R.styleable.View_outlineProvider:
4957                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4958                            PROVIDER_BACKGROUND));
4959                    break;
4960                case R.styleable.View_foreground:
4961                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4962                        setForeground(a.getDrawable(attr));
4963                    }
4964                    break;
4965                case R.styleable.View_foregroundGravity:
4966                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4967                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4968                    }
4969                    break;
4970                case R.styleable.View_foregroundTintMode:
4971                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4972                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4973                    }
4974                    break;
4975                case R.styleable.View_foregroundTint:
4976                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4977                        setForegroundTintList(a.getColorStateList(attr));
4978                    }
4979                    break;
4980                case R.styleable.View_foregroundInsidePadding:
4981                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4982                        if (mForegroundInfo == null) {
4983                            mForegroundInfo = new ForegroundInfo();
4984                        }
4985                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4986                                mForegroundInfo.mInsidePadding);
4987                    }
4988                    break;
4989                case R.styleable.View_scrollIndicators:
4990                    final int scrollIndicators =
4991                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4992                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4993                    if (scrollIndicators != 0) {
4994                        mPrivateFlags3 |= scrollIndicators;
4995                        initializeScrollIndicators = true;
4996                    }
4997                    break;
4998                case R.styleable.View_pointerIcon:
4999                    final int resourceId = a.getResourceId(attr, 0);
5000                    if (resourceId != 0) {
5001                        setPointerIcon(PointerIcon.load(
5002                                context.getResources(), resourceId));
5003                    } else {
5004                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5005                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5006                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5007                        }
5008                    }
5009                    break;
5010                case R.styleable.View_forceHasOverlappingRendering:
5011                    if (a.peekValue(attr) != null) {
5012                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5013                    }
5014                    break;
5015                case R.styleable.View_tooltipText:
5016                    setTooltipText(a.getText(attr));
5017                    break;
5018                case R.styleable.View_keyboardNavigationCluster:
5019                    if (a.peekValue(attr) != null) {
5020                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5021                    }
5022                    break;
5023                case R.styleable.View_focusedByDefault:
5024                    if (a.peekValue(attr) != null) {
5025                        setFocusedByDefault(a.getBoolean(attr, true));
5026                    }
5027                    break;
5028                case R.styleable.View_autofillHints:
5029                    if (a.peekValue(attr) != null) {
5030                        CharSequence[] rawHints = null;
5031                        String rawString = null;
5032
5033                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5034                            int resId = a.getResourceId(attr, 0);
5035
5036                            try {
5037                                rawHints = a.getTextArray(attr);
5038                            } catch (Resources.NotFoundException e) {
5039                                rawString = getResources().getString(resId);
5040                            }
5041                        } else {
5042                            rawString = a.getString(attr);
5043                        }
5044
5045                        if (rawHints == null) {
5046                            if (rawString == null) {
5047                                throw new IllegalArgumentException(
5048                                        "Could not resolve autofillHints");
5049                            } else {
5050                                rawHints = rawString.split(",");
5051                            }
5052                        }
5053
5054                        String[] hints = new String[rawHints.length];
5055
5056                        int numHints = rawHints.length;
5057                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5058                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5059                        }
5060                        setAutofillHints(hints);
5061                    }
5062                    break;
5063                case R.styleable.View_importantForAutofill:
5064                    if (a.peekValue(attr) != null) {
5065                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5066                    }
5067                    break;
5068                case R.styleable.View_defaultFocusHighlightEnabled:
5069                    if (a.peekValue(attr) != null) {
5070                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5071                    }
5072                    break;
5073            }
5074        }
5075
5076        setOverScrollMode(overScrollMode);
5077
5078        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5079        // the resolved layout direction). Those cached values will be used later during padding
5080        // resolution.
5081        mUserPaddingStart = startPadding;
5082        mUserPaddingEnd = endPadding;
5083
5084        if (background != null) {
5085            setBackground(background);
5086        }
5087
5088        // setBackground above will record that padding is currently provided by the background.
5089        // If we have padding specified via xml, record that here instead and use it.
5090        mLeftPaddingDefined = leftPaddingDefined;
5091        mRightPaddingDefined = rightPaddingDefined;
5092
5093        if (padding >= 0) {
5094            leftPadding = padding;
5095            topPadding = padding;
5096            rightPadding = padding;
5097            bottomPadding = padding;
5098            mUserPaddingLeftInitial = padding;
5099            mUserPaddingRightInitial = padding;
5100        } else {
5101            if (paddingHorizontal >= 0) {
5102                leftPadding = paddingHorizontal;
5103                rightPadding = paddingHorizontal;
5104                mUserPaddingLeftInitial = paddingHorizontal;
5105                mUserPaddingRightInitial = paddingHorizontal;
5106            }
5107            if (paddingVertical >= 0) {
5108                topPadding = paddingVertical;
5109                bottomPadding = paddingVertical;
5110            }
5111        }
5112
5113        if (isRtlCompatibilityMode()) {
5114            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5115            // left / right padding are used if defined (meaning here nothing to do). If they are not
5116            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5117            // start / end and resolve them as left / right (layout direction is not taken into account).
5118            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5119            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5120            // defined.
5121            if (!mLeftPaddingDefined && startPaddingDefined) {
5122                leftPadding = startPadding;
5123            }
5124            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5125            if (!mRightPaddingDefined && endPaddingDefined) {
5126                rightPadding = endPadding;
5127            }
5128            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5129        } else {
5130            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5131            // values defined. Otherwise, left /right values are used.
5132            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5133            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5134            // defined.
5135            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5136
5137            if (mLeftPaddingDefined && !hasRelativePadding) {
5138                mUserPaddingLeftInitial = leftPadding;
5139            }
5140            if (mRightPaddingDefined && !hasRelativePadding) {
5141                mUserPaddingRightInitial = rightPadding;
5142            }
5143        }
5144
5145        internalSetPadding(
5146                mUserPaddingLeftInitial,
5147                topPadding >= 0 ? topPadding : mPaddingTop,
5148                mUserPaddingRightInitial,
5149                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5150
5151        if (viewFlagMasks != 0) {
5152            setFlags(viewFlagValues, viewFlagMasks);
5153        }
5154
5155        if (initializeScrollbars) {
5156            initializeScrollbarsInternal(a);
5157        }
5158
5159        if (initializeScrollIndicators) {
5160            initializeScrollIndicatorsInternal();
5161        }
5162
5163        a.recycle();
5164
5165        // Needs to be called after mViewFlags is set
5166        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5167            recomputePadding();
5168        }
5169
5170        if (x != 0 || y != 0) {
5171            scrollTo(x, y);
5172        }
5173
5174        if (transformSet) {
5175            setTranslationX(tx);
5176            setTranslationY(ty);
5177            setTranslationZ(tz);
5178            setElevation(elevation);
5179            setRotation(rotation);
5180            setRotationX(rotationX);
5181            setRotationY(rotationY);
5182            setScaleX(sx);
5183            setScaleY(sy);
5184        }
5185
5186        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5187            setScrollContainer(true);
5188        }
5189
5190        computeOpaqueFlags();
5191    }
5192
5193    /**
5194     * An implementation of OnClickListener that attempts to lazily load a
5195     * named click handling method from a parent or ancestor context.
5196     */
5197    private static class DeclaredOnClickListener implements OnClickListener {
5198        private final View mHostView;
5199        private final String mMethodName;
5200
5201        private Method mResolvedMethod;
5202        private Context mResolvedContext;
5203
5204        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5205            mHostView = hostView;
5206            mMethodName = methodName;
5207        }
5208
5209        @Override
5210        public void onClick(@NonNull View v) {
5211            if (mResolvedMethod == null) {
5212                resolveMethod(mHostView.getContext(), mMethodName);
5213            }
5214
5215            try {
5216                mResolvedMethod.invoke(mResolvedContext, v);
5217            } catch (IllegalAccessException e) {
5218                throw new IllegalStateException(
5219                        "Could not execute non-public method for android:onClick", e);
5220            } catch (InvocationTargetException e) {
5221                throw new IllegalStateException(
5222                        "Could not execute method for android:onClick", e);
5223            }
5224        }
5225
5226        @NonNull
5227        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5228            while (context != null) {
5229                try {
5230                    if (!context.isRestricted()) {
5231                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5232                        if (method != null) {
5233                            mResolvedMethod = method;
5234                            mResolvedContext = context;
5235                            return;
5236                        }
5237                    }
5238                } catch (NoSuchMethodException e) {
5239                    // Failed to find method, keep searching up the hierarchy.
5240                }
5241
5242                if (context instanceof ContextWrapper) {
5243                    context = ((ContextWrapper) context).getBaseContext();
5244                } else {
5245                    // Can't search up the hierarchy, null out and fail.
5246                    context = null;
5247                }
5248            }
5249
5250            final int id = mHostView.getId();
5251            final String idText = id == NO_ID ? "" : " with id '"
5252                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5253            throw new IllegalStateException("Could not find method " + mMethodName
5254                    + "(View) in a parent or ancestor Context for android:onClick "
5255                    + "attribute defined on view " + mHostView.getClass() + idText);
5256        }
5257    }
5258
5259    /**
5260     * Non-public constructor for use in testing
5261     */
5262    View() {
5263        mResources = null;
5264        mRenderNode = RenderNode.create(getClass().getName(), this);
5265    }
5266
5267    final boolean debugDraw() {
5268        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5269    }
5270
5271    private static SparseArray<String> getAttributeMap() {
5272        if (mAttributeMap == null) {
5273            mAttributeMap = new SparseArray<>();
5274        }
5275        return mAttributeMap;
5276    }
5277
5278    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5279        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5280        final int indexCount = t.getIndexCount();
5281        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5282
5283        int i = 0;
5284
5285        // Store raw XML attributes.
5286        for (int j = 0; j < attrsCount; ++j) {
5287            attributes[i] = attrs.getAttributeName(j);
5288            attributes[i + 1] = attrs.getAttributeValue(j);
5289            i += 2;
5290        }
5291
5292        // Store resolved styleable attributes.
5293        final Resources res = t.getResources();
5294        final SparseArray<String> attributeMap = getAttributeMap();
5295        for (int j = 0; j < indexCount; ++j) {
5296            final int index = t.getIndex(j);
5297            if (!t.hasValueOrEmpty(index)) {
5298                // Value is undefined. Skip it.
5299                continue;
5300            }
5301
5302            final int resourceId = t.getResourceId(index, 0);
5303            if (resourceId == 0) {
5304                // Value is not a reference. Skip it.
5305                continue;
5306            }
5307
5308            String resourceName = attributeMap.get(resourceId);
5309            if (resourceName == null) {
5310                try {
5311                    resourceName = res.getResourceName(resourceId);
5312                } catch (Resources.NotFoundException e) {
5313                    resourceName = "0x" + Integer.toHexString(resourceId);
5314                }
5315                attributeMap.put(resourceId, resourceName);
5316            }
5317
5318            attributes[i] = resourceName;
5319            attributes[i + 1] = t.getString(index);
5320            i += 2;
5321        }
5322
5323        // Trim to fit contents.
5324        final String[] trimmed = new String[i];
5325        System.arraycopy(attributes, 0, trimmed, 0, i);
5326        mAttributes = trimmed;
5327    }
5328
5329    public String toString() {
5330        StringBuilder out = new StringBuilder(128);
5331        out.append(getClass().getName());
5332        out.append('{');
5333        out.append(Integer.toHexString(System.identityHashCode(this)));
5334        out.append(' ');
5335        switch (mViewFlags&VISIBILITY_MASK) {
5336            case VISIBLE: out.append('V'); break;
5337            case INVISIBLE: out.append('I'); break;
5338            case GONE: out.append('G'); break;
5339            default: out.append('.'); break;
5340        }
5341        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5342        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5343        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5344        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5345        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5346        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5347        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5348        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5349        out.append(' ');
5350        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5351        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5352        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5353        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5354            out.append('p');
5355        } else {
5356            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5357        }
5358        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5359        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5360        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5361        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5362        out.append(' ');
5363        out.append(mLeft);
5364        out.append(',');
5365        out.append(mTop);
5366        out.append('-');
5367        out.append(mRight);
5368        out.append(',');
5369        out.append(mBottom);
5370        final int id = getId();
5371        if (id != NO_ID) {
5372            out.append(" #");
5373            out.append(Integer.toHexString(id));
5374            final Resources r = mResources;
5375            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5376                try {
5377                    String pkgname;
5378                    switch (id&0xff000000) {
5379                        case 0x7f000000:
5380                            pkgname="app";
5381                            break;
5382                        case 0x01000000:
5383                            pkgname="android";
5384                            break;
5385                        default:
5386                            pkgname = r.getResourcePackageName(id);
5387                            break;
5388                    }
5389                    String typename = r.getResourceTypeName(id);
5390                    String entryname = r.getResourceEntryName(id);
5391                    out.append(" ");
5392                    out.append(pkgname);
5393                    out.append(":");
5394                    out.append(typename);
5395                    out.append("/");
5396                    out.append(entryname);
5397                } catch (Resources.NotFoundException e) {
5398                }
5399            }
5400        }
5401        out.append("}");
5402        return out.toString();
5403    }
5404
5405    /**
5406     * <p>
5407     * Initializes the fading edges from a given set of styled attributes. This
5408     * method should be called by subclasses that need fading edges and when an
5409     * instance of these subclasses is created programmatically rather than
5410     * being inflated from XML. This method is automatically called when the XML
5411     * is inflated.
5412     * </p>
5413     *
5414     * @param a the styled attributes set to initialize the fading edges from
5415     *
5416     * @removed
5417     */
5418    protected void initializeFadingEdge(TypedArray a) {
5419        // This method probably shouldn't have been included in the SDK to begin with.
5420        // It relies on 'a' having been initialized using an attribute filter array that is
5421        // not publicly available to the SDK. The old method has been renamed
5422        // to initializeFadingEdgeInternal and hidden for framework use only;
5423        // this one initializes using defaults to make it safe to call for apps.
5424
5425        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5426
5427        initializeFadingEdgeInternal(arr);
5428
5429        arr.recycle();
5430    }
5431
5432    /**
5433     * <p>
5434     * Initializes the fading edges from a given set of styled attributes. This
5435     * method should be called by subclasses that need fading edges and when an
5436     * instance of these subclasses is created programmatically rather than
5437     * being inflated from XML. This method is automatically called when the XML
5438     * is inflated.
5439     * </p>
5440     *
5441     * @param a the styled attributes set to initialize the fading edges from
5442     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5443     */
5444    protected void initializeFadingEdgeInternal(TypedArray a) {
5445        initScrollCache();
5446
5447        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5448                R.styleable.View_fadingEdgeLength,
5449                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5450    }
5451
5452    /**
5453     * Returns the size of the vertical faded edges used to indicate that more
5454     * content in this view is visible.
5455     *
5456     * @return The size in pixels of the vertical faded edge or 0 if vertical
5457     *         faded edges are not enabled for this view.
5458     * @attr ref android.R.styleable#View_fadingEdgeLength
5459     */
5460    public int getVerticalFadingEdgeLength() {
5461        if (isVerticalFadingEdgeEnabled()) {
5462            ScrollabilityCache cache = mScrollCache;
5463            if (cache != null) {
5464                return cache.fadingEdgeLength;
5465            }
5466        }
5467        return 0;
5468    }
5469
5470    /**
5471     * Set the size of the faded edge used to indicate that more content in this
5472     * view is available.  Will not change whether the fading edge is enabled; use
5473     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5474     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5475     * for the vertical or horizontal fading edges.
5476     *
5477     * @param length The size in pixels of the faded edge used to indicate that more
5478     *        content in this view is visible.
5479     */
5480    public void setFadingEdgeLength(int length) {
5481        initScrollCache();
5482        mScrollCache.fadingEdgeLength = length;
5483    }
5484
5485    /**
5486     * Returns the size of the horizontal faded edges used to indicate that more
5487     * content in this view is visible.
5488     *
5489     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5490     *         faded edges are not enabled for this view.
5491     * @attr ref android.R.styleable#View_fadingEdgeLength
5492     */
5493    public int getHorizontalFadingEdgeLength() {
5494        if (isHorizontalFadingEdgeEnabled()) {
5495            ScrollabilityCache cache = mScrollCache;
5496            if (cache != null) {
5497                return cache.fadingEdgeLength;
5498            }
5499        }
5500        return 0;
5501    }
5502
5503    /**
5504     * Returns the width of the vertical scrollbar.
5505     *
5506     * @return The width in pixels of the vertical scrollbar or 0 if there
5507     *         is no vertical scrollbar.
5508     */
5509    public int getVerticalScrollbarWidth() {
5510        ScrollabilityCache cache = mScrollCache;
5511        if (cache != null) {
5512            ScrollBarDrawable scrollBar = cache.scrollBar;
5513            if (scrollBar != null) {
5514                int size = scrollBar.getSize(true);
5515                if (size <= 0) {
5516                    size = cache.scrollBarSize;
5517                }
5518                return size;
5519            }
5520            return 0;
5521        }
5522        return 0;
5523    }
5524
5525    /**
5526     * Returns the height of the horizontal scrollbar.
5527     *
5528     * @return The height in pixels of the horizontal scrollbar or 0 if
5529     *         there is no horizontal scrollbar.
5530     */
5531    protected int getHorizontalScrollbarHeight() {
5532        ScrollabilityCache cache = mScrollCache;
5533        if (cache != null) {
5534            ScrollBarDrawable scrollBar = cache.scrollBar;
5535            if (scrollBar != null) {
5536                int size = scrollBar.getSize(false);
5537                if (size <= 0) {
5538                    size = cache.scrollBarSize;
5539                }
5540                return size;
5541            }
5542            return 0;
5543        }
5544        return 0;
5545    }
5546
5547    /**
5548     * <p>
5549     * Initializes the scrollbars from a given set of styled attributes. This
5550     * method should be called by subclasses that need scrollbars and when an
5551     * instance of these subclasses is created programmatically rather than
5552     * being inflated from XML. This method is automatically called when the XML
5553     * is inflated.
5554     * </p>
5555     *
5556     * @param a the styled attributes set to initialize the scrollbars from
5557     *
5558     * @removed
5559     */
5560    protected void initializeScrollbars(TypedArray a) {
5561        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5562        // using the View filter array which is not available to the SDK. As such, internal
5563        // framework usage now uses initializeScrollbarsInternal and we grab a default
5564        // TypedArray with the right filter instead here.
5565        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5566
5567        initializeScrollbarsInternal(arr);
5568
5569        // We ignored the method parameter. Recycle the one we actually did use.
5570        arr.recycle();
5571    }
5572
5573    /**
5574     * <p>
5575     * Initializes the scrollbars from a given set of styled attributes. This
5576     * method should be called by subclasses that need scrollbars and when an
5577     * instance of these subclasses is created programmatically rather than
5578     * being inflated from XML. This method is automatically called when the XML
5579     * is inflated.
5580     * </p>
5581     *
5582     * @param a the styled attributes set to initialize the scrollbars from
5583     * @hide
5584     */
5585    protected void initializeScrollbarsInternal(TypedArray a) {
5586        initScrollCache();
5587
5588        final ScrollabilityCache scrollabilityCache = mScrollCache;
5589
5590        if (scrollabilityCache.scrollBar == null) {
5591            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5592            scrollabilityCache.scrollBar.setState(getDrawableState());
5593            scrollabilityCache.scrollBar.setCallback(this);
5594        }
5595
5596        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5597
5598        if (!fadeScrollbars) {
5599            scrollabilityCache.state = ScrollabilityCache.ON;
5600        }
5601        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5602
5603
5604        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5605                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5606                        .getScrollBarFadeDuration());
5607        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5608                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5609                ViewConfiguration.getScrollDefaultDelay());
5610
5611
5612        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5613                com.android.internal.R.styleable.View_scrollbarSize,
5614                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5615
5616        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5617        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5618
5619        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5620        if (thumb != null) {
5621            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5622        }
5623
5624        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5625                false);
5626        if (alwaysDraw) {
5627            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5628        }
5629
5630        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5631        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5632
5633        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5634        if (thumb != null) {
5635            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5636        }
5637
5638        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5639                false);
5640        if (alwaysDraw) {
5641            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5642        }
5643
5644        // Apply layout direction to the new Drawables if needed
5645        final int layoutDirection = getLayoutDirection();
5646        if (track != null) {
5647            track.setLayoutDirection(layoutDirection);
5648        }
5649        if (thumb != null) {
5650            thumb.setLayoutDirection(layoutDirection);
5651        }
5652
5653        // Re-apply user/background padding so that scrollbar(s) get added
5654        resolvePadding();
5655    }
5656
5657    private void initializeScrollIndicatorsInternal() {
5658        // Some day maybe we'll break this into top/left/start/etc. and let the
5659        // client control it. Until then, you can have any scroll indicator you
5660        // want as long as it's a 1dp foreground-colored rectangle.
5661        if (mScrollIndicatorDrawable == null) {
5662            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5663        }
5664    }
5665
5666    /**
5667     * <p>
5668     * Initalizes the scrollability cache if necessary.
5669     * </p>
5670     */
5671    private void initScrollCache() {
5672        if (mScrollCache == null) {
5673            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5674        }
5675    }
5676
5677    private ScrollabilityCache getScrollCache() {
5678        initScrollCache();
5679        return mScrollCache;
5680    }
5681
5682    /**
5683     * Set the position of the vertical scroll bar. Should be one of
5684     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5685     * {@link #SCROLLBAR_POSITION_RIGHT}.
5686     *
5687     * @param position Where the vertical scroll bar should be positioned.
5688     */
5689    public void setVerticalScrollbarPosition(int position) {
5690        if (mVerticalScrollbarPosition != position) {
5691            mVerticalScrollbarPosition = position;
5692            computeOpaqueFlags();
5693            resolvePadding();
5694        }
5695    }
5696
5697    /**
5698     * @return The position where the vertical scroll bar will show, if applicable.
5699     * @see #setVerticalScrollbarPosition(int)
5700     */
5701    public int getVerticalScrollbarPosition() {
5702        return mVerticalScrollbarPosition;
5703    }
5704
5705    boolean isOnScrollbar(float x, float y) {
5706        if (mScrollCache == null) {
5707            return false;
5708        }
5709        x += getScrollX();
5710        y += getScrollY();
5711        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5712            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5713            getVerticalScrollBarBounds(null, touchBounds);
5714            if (touchBounds.contains((int) x, (int) y)) {
5715                return true;
5716            }
5717        }
5718        if (isHorizontalScrollBarEnabled()) {
5719            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5720            getHorizontalScrollBarBounds(null, touchBounds);
5721            if (touchBounds.contains((int) x, (int) y)) {
5722                return true;
5723            }
5724        }
5725        return false;
5726    }
5727
5728    boolean isOnScrollbarThumb(float x, float y) {
5729        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5730    }
5731
5732    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5733        if (mScrollCache == null) {
5734            return false;
5735        }
5736        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5737            x += getScrollX();
5738            y += getScrollY();
5739            final Rect bounds = mScrollCache.mScrollBarBounds;
5740            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5741            getVerticalScrollBarBounds(bounds, touchBounds);
5742            final int range = computeVerticalScrollRange();
5743            final int offset = computeVerticalScrollOffset();
5744            final int extent = computeVerticalScrollExtent();
5745            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5746                    extent, range);
5747            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5748                    extent, range, offset);
5749            final int thumbTop = bounds.top + thumbOffset;
5750            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5751            if (x >= touchBounds.left && x <= touchBounds.right
5752                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5753                return true;
5754            }
5755        }
5756        return false;
5757    }
5758
5759    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5760        if (mScrollCache == null) {
5761            return false;
5762        }
5763        if (isHorizontalScrollBarEnabled()) {
5764            x += getScrollX();
5765            y += getScrollY();
5766            final Rect bounds = mScrollCache.mScrollBarBounds;
5767            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5768            getHorizontalScrollBarBounds(bounds, touchBounds);
5769            final int range = computeHorizontalScrollRange();
5770            final int offset = computeHorizontalScrollOffset();
5771            final int extent = computeHorizontalScrollExtent();
5772            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5773                    extent, range);
5774            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5775                    extent, range, offset);
5776            final int thumbLeft = bounds.left + thumbOffset;
5777            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5778            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5779                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5780                return true;
5781            }
5782        }
5783        return false;
5784    }
5785
5786    boolean isDraggingScrollBar() {
5787        return mScrollCache != null
5788                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5789    }
5790
5791    /**
5792     * Sets the state of all scroll indicators.
5793     * <p>
5794     * See {@link #setScrollIndicators(int, int)} for usage information.
5795     *
5796     * @param indicators a bitmask of indicators that should be enabled, or
5797     *                   {@code 0} to disable all indicators
5798     * @see #setScrollIndicators(int, int)
5799     * @see #getScrollIndicators()
5800     * @attr ref android.R.styleable#View_scrollIndicators
5801     */
5802    public void setScrollIndicators(@ScrollIndicators int indicators) {
5803        setScrollIndicators(indicators,
5804                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5805    }
5806
5807    /**
5808     * Sets the state of the scroll indicators specified by the mask. To change
5809     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5810     * <p>
5811     * When a scroll indicator is enabled, it will be displayed if the view
5812     * can scroll in the direction of the indicator.
5813     * <p>
5814     * Multiple indicator types may be enabled or disabled by passing the
5815     * logical OR of the desired types. If multiple types are specified, they
5816     * will all be set to the same enabled state.
5817     * <p>
5818     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5819     *
5820     * @param indicators the indicator direction, or the logical OR of multiple
5821     *             indicator directions. One or more of:
5822     *             <ul>
5823     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5824     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5825     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5826     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5827     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5828     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5829     *             </ul>
5830     * @see #setScrollIndicators(int)
5831     * @see #getScrollIndicators()
5832     * @attr ref android.R.styleable#View_scrollIndicators
5833     */
5834    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5835        // Shift and sanitize mask.
5836        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5837        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5838
5839        // Shift and mask indicators.
5840        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5841        indicators &= mask;
5842
5843        // Merge with non-masked flags.
5844        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5845
5846        if (mPrivateFlags3 != updatedFlags) {
5847            mPrivateFlags3 = updatedFlags;
5848
5849            if (indicators != 0) {
5850                initializeScrollIndicatorsInternal();
5851            }
5852            invalidate();
5853        }
5854    }
5855
5856    /**
5857     * Returns a bitmask representing the enabled scroll indicators.
5858     * <p>
5859     * For example, if the top and left scroll indicators are enabled and all
5860     * other indicators are disabled, the return value will be
5861     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5862     * <p>
5863     * To check whether the bottom scroll indicator is enabled, use the value
5864     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5865     *
5866     * @return a bitmask representing the enabled scroll indicators
5867     */
5868    @ScrollIndicators
5869    public int getScrollIndicators() {
5870        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5871                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5872    }
5873
5874    ListenerInfo getListenerInfo() {
5875        if (mListenerInfo != null) {
5876            return mListenerInfo;
5877        }
5878        mListenerInfo = new ListenerInfo();
5879        return mListenerInfo;
5880    }
5881
5882    /**
5883     * Register a callback to be invoked when the scroll X or Y positions of
5884     * this view change.
5885     * <p>
5886     * <b>Note:</b> Some views handle scrolling independently from View and may
5887     * have their own separate listeners for scroll-type events. For example,
5888     * {@link android.widget.ListView ListView} allows clients to register an
5889     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5890     * to listen for changes in list scroll position.
5891     *
5892     * @param l The listener to notify when the scroll X or Y position changes.
5893     * @see android.view.View#getScrollX()
5894     * @see android.view.View#getScrollY()
5895     */
5896    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5897        getListenerInfo().mOnScrollChangeListener = l;
5898    }
5899
5900    /**
5901     * Register a callback to be invoked when focus of this view changed.
5902     *
5903     * @param l The callback that will run.
5904     */
5905    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5906        getListenerInfo().mOnFocusChangeListener = l;
5907    }
5908
5909    /**
5910     * Add a listener that will be called when the bounds of the view change due to
5911     * layout processing.
5912     *
5913     * @param listener The listener that will be called when layout bounds change.
5914     */
5915    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5916        ListenerInfo li = getListenerInfo();
5917        if (li.mOnLayoutChangeListeners == null) {
5918            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5919        }
5920        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5921            li.mOnLayoutChangeListeners.add(listener);
5922        }
5923    }
5924
5925    /**
5926     * Remove a listener for layout changes.
5927     *
5928     * @param listener The listener for layout bounds change.
5929     */
5930    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5931        ListenerInfo li = mListenerInfo;
5932        if (li == null || li.mOnLayoutChangeListeners == null) {
5933            return;
5934        }
5935        li.mOnLayoutChangeListeners.remove(listener);
5936    }
5937
5938    /**
5939     * Add a listener for attach state changes.
5940     *
5941     * This listener will be called whenever this view is attached or detached
5942     * from a window. Remove the listener using
5943     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5944     *
5945     * @param listener Listener to attach
5946     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5947     */
5948    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5949        ListenerInfo li = getListenerInfo();
5950        if (li.mOnAttachStateChangeListeners == null) {
5951            li.mOnAttachStateChangeListeners
5952                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5953        }
5954        li.mOnAttachStateChangeListeners.add(listener);
5955    }
5956
5957    /**
5958     * Remove a listener for attach state changes. The listener will receive no further
5959     * notification of window attach/detach events.
5960     *
5961     * @param listener Listener to remove
5962     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5963     */
5964    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5965        ListenerInfo li = mListenerInfo;
5966        if (li == null || li.mOnAttachStateChangeListeners == null) {
5967            return;
5968        }
5969        li.mOnAttachStateChangeListeners.remove(listener);
5970    }
5971
5972    /**
5973     * Returns the focus-change callback registered for this view.
5974     *
5975     * @return The callback, or null if one is not registered.
5976     */
5977    public OnFocusChangeListener getOnFocusChangeListener() {
5978        ListenerInfo li = mListenerInfo;
5979        return li != null ? li.mOnFocusChangeListener : null;
5980    }
5981
5982    /**
5983     * Register a callback to be invoked when this view is clicked. If this view is not
5984     * clickable, it becomes clickable.
5985     *
5986     * @param l The callback that will run
5987     *
5988     * @see #setClickable(boolean)
5989     */
5990    public void setOnClickListener(@Nullable OnClickListener l) {
5991        if (!isClickable()) {
5992            setClickable(true);
5993        }
5994        getListenerInfo().mOnClickListener = l;
5995    }
5996
5997    /**
5998     * Return whether this view has an attached OnClickListener.  Returns
5999     * true if there is a listener, false if there is none.
6000     */
6001    public boolean hasOnClickListeners() {
6002        ListenerInfo li = mListenerInfo;
6003        return (li != null && li.mOnClickListener != null);
6004    }
6005
6006    /**
6007     * Register a callback to be invoked when this view is clicked and held. If this view is not
6008     * long clickable, it becomes long clickable.
6009     *
6010     * @param l The callback that will run
6011     *
6012     * @see #setLongClickable(boolean)
6013     */
6014    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6015        if (!isLongClickable()) {
6016            setLongClickable(true);
6017        }
6018        getListenerInfo().mOnLongClickListener = l;
6019    }
6020
6021    /**
6022     * Register a callback to be invoked when this view is context clicked. If the view is not
6023     * context clickable, it becomes context clickable.
6024     *
6025     * @param l The callback that will run
6026     * @see #setContextClickable(boolean)
6027     */
6028    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6029        if (!isContextClickable()) {
6030            setContextClickable(true);
6031        }
6032        getListenerInfo().mOnContextClickListener = l;
6033    }
6034
6035    /**
6036     * Register a callback to be invoked when the context menu for this view is
6037     * being built. If this view is not long clickable, it becomes long clickable.
6038     *
6039     * @param l The callback that will run
6040     *
6041     */
6042    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6043        if (!isLongClickable()) {
6044            setLongClickable(true);
6045        }
6046        getListenerInfo().mOnCreateContextMenuListener = l;
6047    }
6048
6049    /**
6050     * Set an observer to collect stats for each frame rendered for this view.
6051     *
6052     * @hide
6053     */
6054    public void addFrameMetricsListener(Window window,
6055            Window.OnFrameMetricsAvailableListener listener,
6056            Handler handler) {
6057        if (mAttachInfo != null) {
6058            if (mAttachInfo.mThreadedRenderer != null) {
6059                if (mFrameMetricsObservers == null) {
6060                    mFrameMetricsObservers = new ArrayList<>();
6061                }
6062
6063                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6064                        handler.getLooper(), listener);
6065                mFrameMetricsObservers.add(fmo);
6066                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6067            } else {
6068                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6069            }
6070        } else {
6071            if (mFrameMetricsObservers == null) {
6072                mFrameMetricsObservers = new ArrayList<>();
6073            }
6074
6075            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6076                    handler.getLooper(), listener);
6077            mFrameMetricsObservers.add(fmo);
6078        }
6079    }
6080
6081    /**
6082     * Remove observer configured to collect frame stats for this view.
6083     *
6084     * @hide
6085     */
6086    public void removeFrameMetricsListener(
6087            Window.OnFrameMetricsAvailableListener listener) {
6088        ThreadedRenderer renderer = getThreadedRenderer();
6089        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6090        if (fmo == null) {
6091            throw new IllegalArgumentException(
6092                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6093        }
6094
6095        if (mFrameMetricsObservers != null) {
6096            mFrameMetricsObservers.remove(fmo);
6097            if (renderer != null) {
6098                renderer.removeFrameMetricsObserver(fmo);
6099            }
6100        }
6101    }
6102
6103    private void registerPendingFrameMetricsObservers() {
6104        if (mFrameMetricsObservers != null) {
6105            ThreadedRenderer renderer = getThreadedRenderer();
6106            if (renderer != null) {
6107                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6108                    renderer.addFrameMetricsObserver(fmo);
6109                }
6110            } else {
6111                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6112            }
6113        }
6114    }
6115
6116    private FrameMetricsObserver findFrameMetricsObserver(
6117            Window.OnFrameMetricsAvailableListener listener) {
6118        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6119            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6120            if (observer.mListener == listener) {
6121                return observer;
6122            }
6123        }
6124
6125        return null;
6126    }
6127
6128    /**
6129     * Call this view's OnClickListener, if it is defined.  Performs all normal
6130     * actions associated with clicking: reporting accessibility event, playing
6131     * a sound, etc.
6132     *
6133     * @return True there was an assigned OnClickListener that was called, false
6134     *         otherwise is returned.
6135     */
6136    public boolean performClick() {
6137        final boolean result;
6138        final ListenerInfo li = mListenerInfo;
6139        if (li != null && li.mOnClickListener != null) {
6140            playSoundEffect(SoundEffectConstants.CLICK);
6141            li.mOnClickListener.onClick(this);
6142            result = true;
6143        } else {
6144            result = false;
6145        }
6146
6147        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6148
6149        notifyEnterOrExitForAutoFillIfNeeded(true);
6150
6151        return result;
6152    }
6153
6154    /**
6155     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6156     * this only calls the listener, and does not do any associated clicking
6157     * actions like reporting an accessibility event.
6158     *
6159     * @return True there was an assigned OnClickListener that was called, false
6160     *         otherwise is returned.
6161     */
6162    public boolean callOnClick() {
6163        ListenerInfo li = mListenerInfo;
6164        if (li != null && li.mOnClickListener != null) {
6165            li.mOnClickListener.onClick(this);
6166            return true;
6167        }
6168        return false;
6169    }
6170
6171    /**
6172     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6173     * context menu if the OnLongClickListener did not consume the event.
6174     *
6175     * @return {@code true} if one of the above receivers consumed the event,
6176     *         {@code false} otherwise
6177     */
6178    public boolean performLongClick() {
6179        return performLongClickInternal(mLongClickX, mLongClickY);
6180    }
6181
6182    /**
6183     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6184     * context menu if the OnLongClickListener did not consume the event,
6185     * anchoring it to an (x,y) coordinate.
6186     *
6187     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6188     *          to disable anchoring
6189     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6190     *          to disable anchoring
6191     * @return {@code true} if one of the above receivers consumed the event,
6192     *         {@code false} otherwise
6193     */
6194    public boolean performLongClick(float x, float y) {
6195        mLongClickX = x;
6196        mLongClickY = y;
6197        final boolean handled = performLongClick();
6198        mLongClickX = Float.NaN;
6199        mLongClickY = Float.NaN;
6200        return handled;
6201    }
6202
6203    /**
6204     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6205     * context menu if the OnLongClickListener did not consume the event,
6206     * optionally anchoring it to an (x,y) coordinate.
6207     *
6208     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6209     *          to disable anchoring
6210     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6211     *          to disable anchoring
6212     * @return {@code true} if one of the above receivers consumed the event,
6213     *         {@code false} otherwise
6214     */
6215    private boolean performLongClickInternal(float x, float y) {
6216        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6217
6218        boolean handled = false;
6219        final ListenerInfo li = mListenerInfo;
6220        if (li != null && li.mOnLongClickListener != null) {
6221            handled = li.mOnLongClickListener.onLongClick(View.this);
6222        }
6223        if (!handled) {
6224            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6225            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6226        }
6227        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6228            if (!handled) {
6229                handled = showLongClickTooltip((int) x, (int) y);
6230            }
6231        }
6232        if (handled) {
6233            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6234        }
6235        return handled;
6236    }
6237
6238    /**
6239     * Call this view's OnContextClickListener, if it is defined.
6240     *
6241     * @param x the x coordinate of the context click
6242     * @param y the y coordinate of the context click
6243     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6244     *         otherwise.
6245     */
6246    public boolean performContextClick(float x, float y) {
6247        return performContextClick();
6248    }
6249
6250    /**
6251     * Call this view's OnContextClickListener, if it is defined.
6252     *
6253     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6254     *         otherwise.
6255     */
6256    public boolean performContextClick() {
6257        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6258
6259        boolean handled = false;
6260        ListenerInfo li = mListenerInfo;
6261        if (li != null && li.mOnContextClickListener != null) {
6262            handled = li.mOnContextClickListener.onContextClick(View.this);
6263        }
6264        if (handled) {
6265            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6266        }
6267        return handled;
6268    }
6269
6270    /**
6271     * Performs button-related actions during a touch down event.
6272     *
6273     * @param event The event.
6274     * @return True if the down was consumed.
6275     *
6276     * @hide
6277     */
6278    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6279        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6280            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6281            showContextMenu(event.getX(), event.getY());
6282            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6283            return true;
6284        }
6285        return false;
6286    }
6287
6288    /**
6289     * Shows the context menu for this view.
6290     *
6291     * @return {@code true} if the context menu was shown, {@code false}
6292     *         otherwise
6293     * @see #showContextMenu(float, float)
6294     */
6295    public boolean showContextMenu() {
6296        return getParent().showContextMenuForChild(this);
6297    }
6298
6299    /**
6300     * Shows the context menu for this view anchored to the specified
6301     * view-relative coordinate.
6302     *
6303     * @param x the X coordinate in pixels relative to the view to which the
6304     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6305     * @param y the Y coordinate in pixels relative to the view to which the
6306     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6307     * @return {@code true} if the context menu was shown, {@code false}
6308     *         otherwise
6309     */
6310    public boolean showContextMenu(float x, float y) {
6311        return getParent().showContextMenuForChild(this, x, y);
6312    }
6313
6314    /**
6315     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6316     *
6317     * @param callback Callback that will control the lifecycle of the action mode
6318     * @return The new action mode if it is started, null otherwise
6319     *
6320     * @see ActionMode
6321     * @see #startActionMode(android.view.ActionMode.Callback, int)
6322     */
6323    public ActionMode startActionMode(ActionMode.Callback callback) {
6324        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6325    }
6326
6327    /**
6328     * Start an action mode with the given type.
6329     *
6330     * @param callback Callback that will control the lifecycle of the action mode
6331     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6332     * @return The new action mode if it is started, null otherwise
6333     *
6334     * @see ActionMode
6335     */
6336    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6337        ViewParent parent = getParent();
6338        if (parent == null) return null;
6339        try {
6340            return parent.startActionModeForChild(this, callback, type);
6341        } catch (AbstractMethodError ame) {
6342            // Older implementations of custom views might not implement this.
6343            return parent.startActionModeForChild(this, callback);
6344        }
6345    }
6346
6347    /**
6348     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6349     * Context, creating a unique View identifier to retrieve the result.
6350     *
6351     * @param intent The Intent to be started.
6352     * @param requestCode The request code to use.
6353     * @hide
6354     */
6355    public void startActivityForResult(Intent intent, int requestCode) {
6356        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6357        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6358    }
6359
6360    /**
6361     * If this View corresponds to the calling who, dispatches the activity result.
6362     * @param who The identifier for the targeted View to receive the result.
6363     * @param requestCode The integer request code originally supplied to
6364     *                    startActivityForResult(), allowing you to identify who this
6365     *                    result came from.
6366     * @param resultCode The integer result code returned by the child activity
6367     *                   through its setResult().
6368     * @param data An Intent, which can return result data to the caller
6369     *               (various data can be attached to Intent "extras").
6370     * @return {@code true} if the activity result was dispatched.
6371     * @hide
6372     */
6373    public boolean dispatchActivityResult(
6374            String who, int requestCode, int resultCode, Intent data) {
6375        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6376            onActivityResult(requestCode, resultCode, data);
6377            mStartActivityRequestWho = null;
6378            return true;
6379        }
6380        return false;
6381    }
6382
6383    /**
6384     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6385     *
6386     * @param requestCode The integer request code originally supplied to
6387     *                    startActivityForResult(), allowing you to identify who this
6388     *                    result came from.
6389     * @param resultCode The integer result code returned by the child activity
6390     *                   through its setResult().
6391     * @param data An Intent, which can return result data to the caller
6392     *               (various data can be attached to Intent "extras").
6393     * @hide
6394     */
6395    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6396        // Do nothing.
6397    }
6398
6399    /**
6400     * Register a callback to be invoked when a hardware key is pressed in this view.
6401     * Key presses in software input methods will generally not trigger the methods of
6402     * this listener.
6403     * @param l the key listener to attach to this view
6404     */
6405    public void setOnKeyListener(OnKeyListener l) {
6406        getListenerInfo().mOnKeyListener = l;
6407    }
6408
6409    /**
6410     * Register a callback to be invoked when a touch event is sent to this view.
6411     * @param l the touch listener to attach to this view
6412     */
6413    public void setOnTouchListener(OnTouchListener l) {
6414        getListenerInfo().mOnTouchListener = l;
6415    }
6416
6417    /**
6418     * Register a callback to be invoked when a generic motion event is sent to this view.
6419     * @param l the generic motion listener to attach to this view
6420     */
6421    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6422        getListenerInfo().mOnGenericMotionListener = l;
6423    }
6424
6425    /**
6426     * Register a callback to be invoked when a hover event is sent to this view.
6427     * @param l the hover listener to attach to this view
6428     */
6429    public void setOnHoverListener(OnHoverListener l) {
6430        getListenerInfo().mOnHoverListener = l;
6431    }
6432
6433    /**
6434     * Register a drag event listener callback object for this View. The parameter is
6435     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6436     * View, the system calls the
6437     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6438     * @param l An implementation of {@link android.view.View.OnDragListener}.
6439     */
6440    public void setOnDragListener(OnDragListener l) {
6441        getListenerInfo().mOnDragListener = l;
6442    }
6443
6444    /**
6445     * Give this view focus. This will cause
6446     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6447     *
6448     * Note: this does not check whether this {@link View} should get focus, it just
6449     * gives it focus no matter what.  It should only be called internally by framework
6450     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6451     *
6452     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6453     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6454     *        focus moved when requestFocus() is called. It may not always
6455     *        apply, in which case use the default View.FOCUS_DOWN.
6456     * @param previouslyFocusedRect The rectangle of the view that had focus
6457     *        prior in this View's coordinate system.
6458     */
6459    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6460        if (DBG) {
6461            System.out.println(this + " requestFocus()");
6462        }
6463
6464        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6465            mPrivateFlags |= PFLAG_FOCUSED;
6466
6467            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6468
6469            if (mParent != null) {
6470                mParent.requestChildFocus(this, this);
6471                setFocusedInCluster();
6472            }
6473
6474            if (mAttachInfo != null) {
6475                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6476            }
6477
6478            onFocusChanged(true, direction, previouslyFocusedRect);
6479            refreshDrawableState();
6480        }
6481    }
6482
6483    /**
6484     * Sets this view's preference for reveal behavior when it gains focus.
6485     *
6486     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6487     * this view would prefer to be brought fully into view when it gains focus.
6488     * For example, a text field that a user is meant to type into. Other views such
6489     * as scrolling containers may prefer to opt-out of this behavior.</p>
6490     *
6491     * <p>The default value for views is true, though subclasses may change this
6492     * based on their preferred behavior.</p>
6493     *
6494     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6495     *
6496     * @see #getRevealOnFocusHint()
6497     */
6498    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6499        if (revealOnFocus) {
6500            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6501        } else {
6502            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6503        }
6504    }
6505
6506    /**
6507     * Returns this view's preference for reveal behavior when it gains focus.
6508     *
6509     * <p>When this method returns true for a child view requesting focus, ancestor
6510     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6511     * should make a best effort to make the newly focused child fully visible to the user.
6512     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6513     * other properties affecting visibility to the user as part of the focus change.</p>
6514     *
6515     * @return true if this view would prefer to become fully visible when it gains focus,
6516     *         false if it would prefer not to disrupt scroll positioning
6517     *
6518     * @see #setRevealOnFocusHint(boolean)
6519     */
6520    public final boolean getRevealOnFocusHint() {
6521        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6522    }
6523
6524    /**
6525     * Populates <code>outRect</code> with the hotspot bounds. By default,
6526     * the hotspot bounds are identical to the screen bounds.
6527     *
6528     * @param outRect rect to populate with hotspot bounds
6529     * @hide Only for internal use by views and widgets.
6530     */
6531    public void getHotspotBounds(Rect outRect) {
6532        final Drawable background = getBackground();
6533        if (background != null) {
6534            background.getHotspotBounds(outRect);
6535        } else {
6536            getBoundsOnScreen(outRect);
6537        }
6538    }
6539
6540    /**
6541     * Request that a rectangle of this view be visible on the screen,
6542     * scrolling if necessary just enough.
6543     *
6544     * <p>A View should call this if it maintains some notion of which part
6545     * of its content is interesting.  For example, a text editing view
6546     * should call this when its cursor moves.
6547     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6548     * It should not be affected by which part of the View is currently visible or its scroll
6549     * position.
6550     *
6551     * @param rectangle The rectangle in the View's content coordinate space
6552     * @return Whether any parent scrolled.
6553     */
6554    public boolean requestRectangleOnScreen(Rect rectangle) {
6555        return requestRectangleOnScreen(rectangle, false);
6556    }
6557
6558    /**
6559     * Request that a rectangle of this view be visible on the screen,
6560     * scrolling if necessary just enough.
6561     *
6562     * <p>A View should call this if it maintains some notion of which part
6563     * of its content is interesting.  For example, a text editing view
6564     * should call this when its cursor moves.
6565     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6566     * It should not be affected by which part of the View is currently visible or its scroll
6567     * position.
6568     * <p>When <code>immediate</code> is set to true, scrolling will not be
6569     * animated.
6570     *
6571     * @param rectangle The rectangle in the View's content coordinate space
6572     * @param immediate True to forbid animated scrolling, false otherwise
6573     * @return Whether any parent scrolled.
6574     */
6575    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6576        if (mParent == null) {
6577            return false;
6578        }
6579
6580        View child = this;
6581
6582        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6583        position.set(rectangle);
6584
6585        ViewParent parent = mParent;
6586        boolean scrolled = false;
6587        while (parent != null) {
6588            rectangle.set((int) position.left, (int) position.top,
6589                    (int) position.right, (int) position.bottom);
6590
6591            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6592
6593            if (!(parent instanceof View)) {
6594                break;
6595            }
6596
6597            // move it from child's content coordinate space to parent's content coordinate space
6598            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6599
6600            child = (View) parent;
6601            parent = child.getParent();
6602        }
6603
6604        return scrolled;
6605    }
6606
6607    /**
6608     * Called when this view wants to give up focus. If focus is cleared
6609     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6610     * <p>
6611     * <strong>Note:</strong> When a View clears focus the framework is trying
6612     * to give focus to the first focusable View from the top. Hence, if this
6613     * View is the first from the top that can take focus, then all callbacks
6614     * related to clearing focus will be invoked after which the framework will
6615     * give focus to this view.
6616     * </p>
6617     */
6618    public void clearFocus() {
6619        if (DBG) {
6620            System.out.println(this + " clearFocus()");
6621        }
6622
6623        clearFocusInternal(null, true, true);
6624    }
6625
6626    /**
6627     * Clears focus from the view, optionally propagating the change up through
6628     * the parent hierarchy and requesting that the root view place new focus.
6629     *
6630     * @param propagate whether to propagate the change up through the parent
6631     *            hierarchy
6632     * @param refocus when propagate is true, specifies whether to request the
6633     *            root view place new focus
6634     */
6635    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6636        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6637            mPrivateFlags &= ~PFLAG_FOCUSED;
6638
6639            if (propagate && mParent != null) {
6640                mParent.clearChildFocus(this);
6641            }
6642
6643            onFocusChanged(false, 0, null);
6644            refreshDrawableState();
6645
6646            if (propagate && (!refocus || !rootViewRequestFocus())) {
6647                notifyGlobalFocusCleared(this);
6648            }
6649        }
6650    }
6651
6652    void notifyGlobalFocusCleared(View oldFocus) {
6653        if (oldFocus != null && mAttachInfo != null) {
6654            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6655        }
6656    }
6657
6658    boolean rootViewRequestFocus() {
6659        final View root = getRootView();
6660        return root != null && root.requestFocus();
6661    }
6662
6663    /**
6664     * Called internally by the view system when a new view is getting focus.
6665     * This is what clears the old focus.
6666     * <p>
6667     * <b>NOTE:</b> The parent view's focused child must be updated manually
6668     * after calling this method. Otherwise, the view hierarchy may be left in
6669     * an inconstent state.
6670     */
6671    void unFocus(View focused) {
6672        if (DBG) {
6673            System.out.println(this + " unFocus()");
6674        }
6675
6676        clearFocusInternal(focused, false, false);
6677    }
6678
6679    /**
6680     * Returns true if this view has focus itself, or is the ancestor of the
6681     * view that has focus.
6682     *
6683     * @return True if this view has or contains focus, false otherwise.
6684     */
6685    @ViewDebug.ExportedProperty(category = "focus")
6686    public boolean hasFocus() {
6687        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6688    }
6689
6690    /**
6691     * Returns true if this view is focusable or if it contains a reachable View
6692     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6693     * is a view whose parents do not block descendants focus.
6694     * Only {@link #VISIBLE} views are considered focusable.
6695     *
6696     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6697     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6698     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6699     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6700     * {@code false} for views not explicitly marked as focusable.
6701     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6702     * behavior.</p>
6703     *
6704     * @return {@code true} if the view is focusable or if the view contains a focusable
6705     *         view, {@code false} otherwise
6706     *
6707     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6708     * @see ViewGroup#getTouchscreenBlocksFocus()
6709     * @see #hasExplicitFocusable()
6710     */
6711    public boolean hasFocusable() {
6712        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6713    }
6714
6715    /**
6716     * Returns true if this view is focusable or if it contains a reachable View
6717     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6718     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6719     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6720     * {@link #FOCUSABLE} are considered focusable.
6721     *
6722     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6723     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6724     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6725     * to focusable will not.</p>
6726     *
6727     * @return {@code true} if the view is focusable or if the view contains a focusable
6728     *         view, {@code false} otherwise
6729     *
6730     * @see #hasFocusable()
6731     */
6732    public boolean hasExplicitFocusable() {
6733        return hasFocusable(false, true);
6734    }
6735
6736    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6737        if (!isFocusableInTouchMode()) {
6738            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6739                final ViewGroup g = (ViewGroup) p;
6740                if (g.shouldBlockFocusForTouchscreen()) {
6741                    return false;
6742                }
6743            }
6744        }
6745
6746        // Invisible and gone views are never focusable.
6747        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6748            return false;
6749        }
6750
6751        // Only use effective focusable value when allowed.
6752        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6753            return true;
6754        }
6755
6756        return false;
6757    }
6758
6759    /**
6760     * Called by the view system when the focus state of this view changes.
6761     * When the focus change event is caused by directional navigation, direction
6762     * and previouslyFocusedRect provide insight into where the focus is coming from.
6763     * When overriding, be sure to call up through to the super class so that
6764     * the standard focus handling will occur.
6765     *
6766     * @param gainFocus True if the View has focus; false otherwise.
6767     * @param direction The direction focus has moved when requestFocus()
6768     *                  is called to give this view focus. Values are
6769     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6770     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6771     *                  It may not always apply, in which case use the default.
6772     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6773     *        system, of the previously focused view.  If applicable, this will be
6774     *        passed in as finer grained information about where the focus is coming
6775     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6776     */
6777    @CallSuper
6778    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6779            @Nullable Rect previouslyFocusedRect) {
6780        if (gainFocus) {
6781            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6782        } else {
6783            notifyViewAccessibilityStateChangedIfNeeded(
6784                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6785        }
6786
6787        // Here we check whether we still need the default focus highlight, and switch it on/off.
6788        switchDefaultFocusHighlight();
6789
6790        InputMethodManager imm = InputMethodManager.peekInstance();
6791        if (!gainFocus) {
6792            if (isPressed()) {
6793                setPressed(false);
6794            }
6795            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6796                imm.focusOut(this);
6797            }
6798            onFocusLost();
6799        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6800            imm.focusIn(this);
6801        }
6802
6803        invalidate(true);
6804        ListenerInfo li = mListenerInfo;
6805        if (li != null && li.mOnFocusChangeListener != null) {
6806            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6807        }
6808
6809        if (mAttachInfo != null) {
6810            mAttachInfo.mKeyDispatchState.reset(this);
6811        }
6812
6813        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6814    }
6815
6816    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6817        if (isAutofillable() && isAttachedToWindow()) {
6818            AutofillManager afm = getAutofillManager();
6819            if (afm != null) {
6820                if (enter && hasWindowFocus() && isFocused()) {
6821                    afm.notifyViewEntered(this);
6822                } else if (!hasWindowFocus() || !isFocused()) {
6823                    afm.notifyViewExited(this);
6824                }
6825            }
6826        }
6827    }
6828
6829    /**
6830     * Sends an accessibility event of the given type. If accessibility is
6831     * not enabled this method has no effect. The default implementation calls
6832     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6833     * to populate information about the event source (this View), then calls
6834     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6835     * populate the text content of the event source including its descendants,
6836     * and last calls
6837     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6838     * on its parent to request sending of the event to interested parties.
6839     * <p>
6840     * If an {@link AccessibilityDelegate} has been specified via calling
6841     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6842     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6843     * responsible for handling this call.
6844     * </p>
6845     *
6846     * @param eventType The type of the event to send, as defined by several types from
6847     * {@link android.view.accessibility.AccessibilityEvent}, such as
6848     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6849     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6850     *
6851     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6852     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6853     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6854     * @see AccessibilityDelegate
6855     */
6856    public void sendAccessibilityEvent(int eventType) {
6857        if (mAccessibilityDelegate != null) {
6858            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6859        } else {
6860            sendAccessibilityEventInternal(eventType);
6861        }
6862    }
6863
6864    /**
6865     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6866     * {@link AccessibilityEvent} to make an announcement which is related to some
6867     * sort of a context change for which none of the events representing UI transitions
6868     * is a good fit. For example, announcing a new page in a book. If accessibility
6869     * is not enabled this method does nothing.
6870     *
6871     * @param text The announcement text.
6872     */
6873    public void announceForAccessibility(CharSequence text) {
6874        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6875            AccessibilityEvent event = AccessibilityEvent.obtain(
6876                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6877            onInitializeAccessibilityEvent(event);
6878            event.getText().add(text);
6879            event.setContentDescription(null);
6880            mParent.requestSendAccessibilityEvent(this, event);
6881        }
6882    }
6883
6884    /**
6885     * @see #sendAccessibilityEvent(int)
6886     *
6887     * Note: Called from the default {@link AccessibilityDelegate}.
6888     *
6889     * @hide
6890     */
6891    public void sendAccessibilityEventInternal(int eventType) {
6892        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6893            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6894        }
6895    }
6896
6897    /**
6898     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6899     * takes as an argument an empty {@link AccessibilityEvent} and does not
6900     * perform a check whether accessibility is enabled.
6901     * <p>
6902     * If an {@link AccessibilityDelegate} has been specified via calling
6903     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6904     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6905     * is responsible for handling this call.
6906     * </p>
6907     *
6908     * @param event The event to send.
6909     *
6910     * @see #sendAccessibilityEvent(int)
6911     */
6912    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6913        if (mAccessibilityDelegate != null) {
6914            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6915        } else {
6916            sendAccessibilityEventUncheckedInternal(event);
6917        }
6918    }
6919
6920    /**
6921     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6922     *
6923     * Note: Called from the default {@link AccessibilityDelegate}.
6924     *
6925     * @hide
6926     */
6927    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6928        if (!isShown()) {
6929            return;
6930        }
6931        onInitializeAccessibilityEvent(event);
6932        // Only a subset of accessibility events populates text content.
6933        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6934            dispatchPopulateAccessibilityEvent(event);
6935        }
6936        // In the beginning we called #isShown(), so we know that getParent() is not null.
6937        ViewParent parent = getParent();
6938        if (parent != null) {
6939            getParent().requestSendAccessibilityEvent(this, event);
6940        }
6941    }
6942
6943    /**
6944     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6945     * to its children for adding their text content to the event. Note that the
6946     * event text is populated in a separate dispatch path since we add to the
6947     * event not only the text of the source but also the text of all its descendants.
6948     * A typical implementation will call
6949     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6950     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6951     * on each child. Override this method if custom population of the event text
6952     * content is required.
6953     * <p>
6954     * If an {@link AccessibilityDelegate} has been specified via calling
6955     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6956     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6957     * is responsible for handling this call.
6958     * </p>
6959     * <p>
6960     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6961     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6962     * </p>
6963     *
6964     * @param event The event.
6965     *
6966     * @return True if the event population was completed.
6967     */
6968    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6969        if (mAccessibilityDelegate != null) {
6970            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6971        } else {
6972            return dispatchPopulateAccessibilityEventInternal(event);
6973        }
6974    }
6975
6976    /**
6977     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6978     *
6979     * Note: Called from the default {@link AccessibilityDelegate}.
6980     *
6981     * @hide
6982     */
6983    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6984        onPopulateAccessibilityEvent(event);
6985        return false;
6986    }
6987
6988    /**
6989     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6990     * giving a chance to this View to populate the accessibility event with its
6991     * text content. While this method is free to modify event
6992     * attributes other than text content, doing so should normally be performed in
6993     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6994     * <p>
6995     * Example: Adding formatted date string to an accessibility event in addition
6996     *          to the text added by the super implementation:
6997     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6998     *     super.onPopulateAccessibilityEvent(event);
6999     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7000     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7001     *         mCurrentDate.getTimeInMillis(), flags);
7002     *     event.getText().add(selectedDateUtterance);
7003     * }</pre>
7004     * <p>
7005     * If an {@link AccessibilityDelegate} has been specified via calling
7006     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7007     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7008     * is responsible for handling this call.
7009     * </p>
7010     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7011     * information to the event, in case the default implementation has basic information to add.
7012     * </p>
7013     *
7014     * @param event The accessibility event which to populate.
7015     *
7016     * @see #sendAccessibilityEvent(int)
7017     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7018     */
7019    @CallSuper
7020    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7021        if (mAccessibilityDelegate != null) {
7022            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7023        } else {
7024            onPopulateAccessibilityEventInternal(event);
7025        }
7026    }
7027
7028    /**
7029     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7030     *
7031     * Note: Called from the default {@link AccessibilityDelegate}.
7032     *
7033     * @hide
7034     */
7035    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7036    }
7037
7038    /**
7039     * Initializes an {@link AccessibilityEvent} with information about
7040     * this View which is the event source. In other words, the source of
7041     * an accessibility event is the view whose state change triggered firing
7042     * the event.
7043     * <p>
7044     * Example: Setting the password property of an event in addition
7045     *          to properties set by the super implementation:
7046     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7047     *     super.onInitializeAccessibilityEvent(event);
7048     *     event.setPassword(true);
7049     * }</pre>
7050     * <p>
7051     * If an {@link AccessibilityDelegate} has been specified via calling
7052     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7053     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7054     * is responsible for handling this call.
7055     * </p>
7056     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7057     * information to the event, in case the default implementation has basic information to add.
7058     * </p>
7059     * @param event The event to initialize.
7060     *
7061     * @see #sendAccessibilityEvent(int)
7062     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7063     */
7064    @CallSuper
7065    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7066        if (mAccessibilityDelegate != null) {
7067            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7068        } else {
7069            onInitializeAccessibilityEventInternal(event);
7070        }
7071    }
7072
7073    /**
7074     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7075     *
7076     * Note: Called from the default {@link AccessibilityDelegate}.
7077     *
7078     * @hide
7079     */
7080    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7081        event.setSource(this);
7082        event.setClassName(getAccessibilityClassName());
7083        event.setPackageName(getContext().getPackageName());
7084        event.setEnabled(isEnabled());
7085        event.setContentDescription(mContentDescription);
7086
7087        switch (event.getEventType()) {
7088            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7089                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7090                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7091                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7092                event.setItemCount(focusablesTempList.size());
7093                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7094                if (mAttachInfo != null) {
7095                    focusablesTempList.clear();
7096                }
7097            } break;
7098            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7099                CharSequence text = getIterableTextForAccessibility();
7100                if (text != null && text.length() > 0) {
7101                    event.setFromIndex(getAccessibilitySelectionStart());
7102                    event.setToIndex(getAccessibilitySelectionEnd());
7103                    event.setItemCount(text.length());
7104                }
7105            } break;
7106        }
7107    }
7108
7109    /**
7110     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7111     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7112     * This method is responsible for obtaining an accessibility node info from a
7113     * pool of reusable instances and calling
7114     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7115     * initialize the former.
7116     * <p>
7117     * Note: The client is responsible for recycling the obtained instance by calling
7118     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7119     * </p>
7120     *
7121     * @return A populated {@link AccessibilityNodeInfo}.
7122     *
7123     * @see AccessibilityNodeInfo
7124     */
7125    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7126        if (mAccessibilityDelegate != null) {
7127            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7128        } else {
7129            return createAccessibilityNodeInfoInternal();
7130        }
7131    }
7132
7133    /**
7134     * @see #createAccessibilityNodeInfo()
7135     *
7136     * @hide
7137     */
7138    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7139        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7140        if (provider != null) {
7141            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7142        } else {
7143            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7144            onInitializeAccessibilityNodeInfo(info);
7145            return info;
7146        }
7147    }
7148
7149    /**
7150     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7151     * The base implementation sets:
7152     * <ul>
7153     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7154     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7155     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7156     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7157     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7158     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7159     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7160     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7161     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7162     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7163     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7164     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7165     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7166     * </ul>
7167     * <p>
7168     * Subclasses should override this method, call the super implementation,
7169     * and set additional attributes.
7170     * </p>
7171     * <p>
7172     * If an {@link AccessibilityDelegate} has been specified via calling
7173     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7174     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7175     * is responsible for handling this call.
7176     * </p>
7177     *
7178     * @param info The instance to initialize.
7179     */
7180    @CallSuper
7181    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7182        if (mAccessibilityDelegate != null) {
7183            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7184        } else {
7185            onInitializeAccessibilityNodeInfoInternal(info);
7186        }
7187    }
7188
7189    /**
7190     * Gets the location of this view in screen coordinates.
7191     *
7192     * @param outRect The output location
7193     * @hide
7194     */
7195    public void getBoundsOnScreen(Rect outRect) {
7196        getBoundsOnScreen(outRect, false);
7197    }
7198
7199    /**
7200     * Gets the location of this view in screen coordinates.
7201     *
7202     * @param outRect The output location
7203     * @param clipToParent Whether to clip child bounds to the parent ones.
7204     * @hide
7205     */
7206    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7207        if (mAttachInfo == null) {
7208            return;
7209        }
7210
7211        RectF position = mAttachInfo.mTmpTransformRect;
7212        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7213
7214        if (!hasIdentityMatrix()) {
7215            getMatrix().mapRect(position);
7216        }
7217
7218        position.offset(mLeft, mTop);
7219
7220        ViewParent parent = mParent;
7221        while (parent instanceof View) {
7222            View parentView = (View) parent;
7223
7224            position.offset(-parentView.mScrollX, -parentView.mScrollY);
7225
7226            if (clipToParent) {
7227                position.left = Math.max(position.left, 0);
7228                position.top = Math.max(position.top, 0);
7229                position.right = Math.min(position.right, parentView.getWidth());
7230                position.bottom = Math.min(position.bottom, parentView.getHeight());
7231            }
7232
7233            if (!parentView.hasIdentityMatrix()) {
7234                parentView.getMatrix().mapRect(position);
7235            }
7236
7237            position.offset(parentView.mLeft, parentView.mTop);
7238
7239            parent = parentView.mParent;
7240        }
7241
7242        if (parent instanceof ViewRootImpl) {
7243            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7244            position.offset(0, -viewRootImpl.mCurScrollY);
7245        }
7246
7247        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7248
7249        outRect.set(Math.round(position.left), Math.round(position.top),
7250                Math.round(position.right), Math.round(position.bottom));
7251    }
7252
7253    /**
7254     * Return the class name of this object to be used for accessibility purposes.
7255     * Subclasses should only override this if they are implementing something that
7256     * should be seen as a completely new class of view when used by accessibility,
7257     * unrelated to the class it is deriving from.  This is used to fill in
7258     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7259     */
7260    public CharSequence getAccessibilityClassName() {
7261        return View.class.getName();
7262    }
7263
7264    /**
7265     * Called when assist structure is being retrieved from a view as part of
7266     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7267     * @param structure Fill in with structured view data.  The default implementation
7268     * fills in all data that can be inferred from the view itself.
7269     */
7270    public void onProvideStructure(ViewStructure structure) {
7271        onProvideStructureForAssistOrAutofill(structure, false);
7272    }
7273
7274    /**
7275     * Called when assist structure is being retrieved from a view as part of an autofill request.
7276     *
7277     * <p>This method already provides most of what's needed for autofill, but should be overridden
7278     * when:
7279     * <ol>
7280     * <li>The view contents does not include PII (Personally Identifiable Information), so it
7281     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7282     * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7283     * {@link ViewStructure#setAutofillOptions(CharSequence[])},
7284     * or {@link ViewStructure#setUrl(String)}.
7285     * </ol>
7286     *
7287     * @param structure Fill in with structured view data. The default implementation
7288     * fills in all data that can be inferred from the view itself.
7289     * @param flags optional flags (currently {@code 0}).
7290     */
7291    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
7292        onProvideStructureForAssistOrAutofill(structure, true);
7293    }
7294
7295    private void setAutofillId(ViewStructure structure) {
7296        // The autofill id needs to be unique, but its value doesn't matter,
7297        // so it's better to reuse the accessibility id to save space.
7298        structure.setAutofillId(getAccessibilityViewId());
7299    }
7300
7301    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7302            boolean forAutofill) {
7303        final int id = mID;
7304        if (id != NO_ID && !isViewIdGenerated(id)) {
7305            String pkg, type, entry;
7306            try {
7307                final Resources res = getResources();
7308                entry = res.getResourceEntryName(id);
7309                type = res.getResourceTypeName(id);
7310                pkg = res.getResourcePackageName(id);
7311            } catch (Resources.NotFoundException e) {
7312                entry = type = pkg = null;
7313            }
7314            structure.setId(id, pkg, type, entry);
7315        } else {
7316            structure.setId(id, null, null, null);
7317        }
7318
7319        if (forAutofill) {
7320            setAutofillId(structure);
7321            final @AutofillType int autofillType = getAutofillType();
7322            // Don't need to fill autofill info if view does not support it.
7323            // For example, only TextViews that are editable support autofill
7324            if (autofillType != AUTOFILL_TYPE_NONE) {
7325                structure.setAutofillType(autofillType);
7326                structure.setAutofillHints(getAutofillHints());
7327                structure.setAutofillValue(getAutofillValue());
7328            }
7329        }
7330
7331        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
7332        if (!hasIdentityMatrix()) {
7333            structure.setTransformation(getMatrix());
7334        }
7335        structure.setElevation(getZ());
7336        structure.setVisibility(getVisibility());
7337        structure.setEnabled(isEnabled());
7338        if (isClickable()) {
7339            structure.setClickable(true);
7340        }
7341        if (isFocusable()) {
7342            structure.setFocusable(true);
7343        }
7344        if (isFocused()) {
7345            structure.setFocused(true);
7346        }
7347        if (isAccessibilityFocused()) {
7348            structure.setAccessibilityFocused(true);
7349        }
7350        if (isSelected()) {
7351            structure.setSelected(true);
7352        }
7353        if (isActivated()) {
7354            structure.setActivated(true);
7355        }
7356        if (isLongClickable()) {
7357            structure.setLongClickable(true);
7358        }
7359        if (this instanceof Checkable) {
7360            structure.setCheckable(true);
7361            if (((Checkable)this).isChecked()) {
7362                structure.setChecked(true);
7363            }
7364        }
7365        if (isOpaque()) {
7366            structure.setOpaque(true);
7367        }
7368        if (isContextClickable()) {
7369            structure.setContextClickable(true);
7370        }
7371        structure.setClassName(getAccessibilityClassName().toString());
7372        structure.setContentDescription(getContentDescription());
7373    }
7374
7375    /**
7376     * Called when assist structure is being retrieved from a view as part of
7377     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7378     * generate additional virtual structure under this view.  The defaullt implementation
7379     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7380     * view's virtual accessibility nodes, if any.  You can override this for a more
7381     * optimal implementation providing this data.
7382     */
7383    public void onProvideVirtualStructure(ViewStructure structure) {
7384        onProvideVirtualStructureForAssistOrAutofill(structure, false);
7385    }
7386
7387    /**
7388     * Called when assist structure is being retrieved from a view as part of an autofill request
7389     * to generate additional virtual structure under this view.
7390     *
7391     * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
7392     * generate this from the view's virtual accessibility nodes, if any. You can override this
7393     * for a more optimal implementation providing this data.
7394     *
7395     * <p>When implementing this method, subclasses must follow the rules below:
7396     *
7397     * <ol>
7398     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7399     * children.
7400     * <li>Call
7401     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7402     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7403     * when the focus inside the view changed.
7404     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7405     * AutofillValue)} when the value of a child changed.
7406     * <li>Call {@link AutofillManager#commit()} when the autofill context
7407     * of the view structure changed and you want the current autofill interaction if such
7408     * to be commited.
7409     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7410     * of the view structure changed and you want the current autofill interaction if such
7411     * to be cancelled.
7412     * </ol>
7413     *
7414     * @param structure Fill in with structured view data.
7415     * @param flags optional flags (currently {@code 0}).
7416     */
7417    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7418        onProvideVirtualStructureForAssistOrAutofill(structure, true);
7419    }
7420
7421    private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure,
7422            boolean forAutofill) {
7423        if (forAutofill) {
7424            setAutofillId(structure);
7425        }
7426        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7427        // this method should take a boolean with the type of request.
7428        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7429        if (provider != null) {
7430            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7431            structure.setChildCount(1);
7432            ViewStructure root = structure.newChild(0);
7433            if (forAutofill) {
7434                setAutofillId(root);
7435            }
7436            populateVirtualStructure(root, provider, info, forAutofill);
7437            info.recycle();
7438        }
7439    }
7440
7441    /**
7442     * Automatically fills the content of this view with the {@code value}.
7443     *
7444     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7445     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7446     * to support the Autofill Framework.
7447     *
7448     * <p>Typically, it is implemented by:
7449     *
7450     * <ol>
7451     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7452     * <li>Passing the actual value to the equivalent setter in the view.
7453     * </ol>
7454     *
7455     * <p>For example, a text-field view would call:
7456     * <pre class="prettyprint">
7457     * CharSequence text = value.getTextValue();
7458     * if (text != null) {
7459     *     setText(text);
7460     * }
7461     * </pre>
7462     *
7463     * <p>If the value is updated asyncronously the next call to
7464     * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
7465     * changed to the autofilled value. If not, the view will not be considered autofilled.
7466     *
7467     * @param value value to be autofilled.
7468     */
7469    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7470    }
7471
7472    /**
7473     * Automatically fills the content of a virtual views.
7474     *
7475     * <p>See {@link #autofill(AutofillValue)} and
7476     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7477     * <p>To indicate that a virtual view was autofilled
7478     * <code>@android:drawable/autofilled_highlight</code> should be drawn over it until the data
7479     * changes.
7480     *
7481     * @param values map of values to be autofilled, keyed by virtual child id.
7482     */
7483    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7484    }
7485
7486    /**
7487     * Describes the autofill type that should be used on calls to
7488     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7489     *
7490     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7491     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7492     */
7493    public @AutofillType int getAutofillType() {
7494        return AUTOFILL_TYPE_NONE;
7495    }
7496
7497    /**
7498     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7499     *
7500     * @return The hints set via the attribute or {@code null} if no hint it set.
7501     *
7502     * @attr ref android.R.styleable#View_autofillHints
7503     */
7504    @ViewDebug.ExportedProperty()
7505    @Nullable public String[] getAutofillHints() {
7506        return mAutofillHints;
7507    }
7508
7509    /**
7510     * @hide
7511     */
7512    public boolean isAutofilled() {
7513        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7514    }
7515
7516    /**
7517     * Gets the {@link View}'s current autofill value.
7518     *
7519     * <p>By default returns {@code null}, but views should override it (and
7520     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7521     * Framework.
7522     */
7523    @Nullable
7524    public AutofillValue getAutofillValue() {
7525        return null;
7526    }
7527
7528    /**
7529     * Gets the mode for determining whether this View is important for autofill.
7530     *
7531     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7532     *
7533     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7534     * {@link #setImportantForAutofill(int)}.
7535     *
7536     * @attr ref android.R.styleable#View_importantForAutofill
7537     */
7538    @ViewDebug.ExportedProperty(mapping = {
7539            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7540            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7541            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
7542    public @AutofillImportance int getImportantForAutofill() {
7543        return (mPrivateFlags3
7544                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7545    }
7546
7547    /**
7548     * Sets the mode for determining whether this View is important for autofill.
7549     *
7550     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7551     *
7552     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7553     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7554     *
7555     * @attr ref android.R.styleable#View_importantForAutofill
7556     */
7557    public void setImportantForAutofill(@AutofillImportance int mode) {
7558        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7559        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7560                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7561    }
7562
7563    /**
7564     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7565     * associated with this View should be included in a {@link ViewStructure} used for
7566     * autofill purposes.
7567     *
7568     * <p>Generally speaking, a view is important for autofill if:
7569     * <ol>
7570     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7571     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7572     * autofill other views.
7573     * <ol>
7574     *
7575     * <p>For example, view containers should typically return {@code false} for performance reasons
7576     * (since the important info is provided by their children), but if the container is actually
7577     * whose children are part of a compound view, it should return {@code true} (and then override
7578     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7579     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7580     * the structure). On the other hand, views representing labels or editable fields should
7581     * typically return {@code true}, but in some cases they could return {@code false} (for
7582     * example, if they're part of a "Captcha" mechanism).
7583     *
7584     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7585     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7586     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7587     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7588     * should use {@link #setImportantForAutofill(int)} instead.
7589     *
7590     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7591     * excluded from the structure; for example, if the user explicitly requested autofill, the
7592     * View might be always included.
7593     *
7594     * <p>This decision applies just for the view, not its children - if the view children are not
7595     * important for autofill, the view should override
7596     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7597     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7598     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7599     *
7600     * @return whether the view is considered important for autofill.
7601     *
7602     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7603     * @see #IMPORTANT_FOR_AUTOFILL_YES
7604     * @see #IMPORTANT_FOR_AUTOFILL_NO
7605     */
7606    public final boolean isImportantForAutofill() {
7607        final int flag = getImportantForAutofill();
7608
7609        // First, check if view explicity set it to YES or NO
7610        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
7611            return true;
7612        }
7613        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
7614            return false;
7615        }
7616
7617        // Then use some heuristics to handle AUTO.
7618
7619        // Always include views that have a explicity resource id.
7620        final int id = mID;
7621        if (id != NO_ID && !isViewIdGenerated(id)) {
7622            final Resources res = getResources();
7623            String entry = null;
7624            String pkg = null;
7625            try {
7626                entry = res.getResourceEntryName(id);
7627                pkg = res.getResourcePackageName(id);
7628            } catch (Resources.NotFoundException e) {
7629                // ignore
7630            }
7631            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7632                return true;
7633            }
7634        }
7635
7636        // Otherwise, assume it's not important...
7637        return false;
7638    }
7639
7640    @Nullable
7641    private AutofillManager getAutofillManager() {
7642        return mContext.getSystemService(AutofillManager.class);
7643    }
7644
7645    private boolean isAutofillable() {
7646        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
7647    }
7648
7649    private void populateVirtualStructure(ViewStructure structure,
7650            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) {
7651        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7652                null, null, null);
7653        Rect rect = structure.getTempRect();
7654        info.getBoundsInParent(rect);
7655        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7656        structure.setVisibility(VISIBLE);
7657        structure.setEnabled(info.isEnabled());
7658        if (info.isClickable()) {
7659            structure.setClickable(true);
7660        }
7661        if (info.isFocusable()) {
7662            structure.setFocusable(true);
7663        }
7664        if (info.isFocused()) {
7665            structure.setFocused(true);
7666        }
7667        if (info.isAccessibilityFocused()) {
7668            structure.setAccessibilityFocused(true);
7669        }
7670        if (info.isSelected()) {
7671            structure.setSelected(true);
7672        }
7673        if (info.isLongClickable()) {
7674            structure.setLongClickable(true);
7675        }
7676        if (info.isCheckable()) {
7677            structure.setCheckable(true);
7678            if (info.isChecked()) {
7679                structure.setChecked(true);
7680            }
7681        }
7682        if (info.isContextClickable()) {
7683            structure.setContextClickable(true);
7684        }
7685        CharSequence cname = info.getClassName();
7686        structure.setClassName(cname != null ? cname.toString() : null);
7687        structure.setContentDescription(info.getContentDescription());
7688        if (!forAutofill && (info.getText() != null || info.getError() != null)) {
7689            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7690            // just set sanitized values (like text coming from resource files), rather than not
7691            // setting it at all.
7692            structure.setText(info.getText(), info.getTextSelectionStart(),
7693                    info.getTextSelectionEnd());
7694        }
7695        final int NCHILDREN = info.getChildCount();
7696        if (NCHILDREN > 0) {
7697            structure.setChildCount(NCHILDREN);
7698            for (int i=0; i<NCHILDREN; i++) {
7699                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7700                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7701                ViewStructure child = structure.newChild(i);
7702                if (forAutofill) {
7703                    // TODO(b/33197203): add CTS test to autofill virtual children based on
7704                    // Accessibility API.
7705                    child.setAutofillId(structure, i);
7706                }
7707                populateVirtualStructure(child, provider, cinfo, forAutofill);
7708                cinfo.recycle();
7709            }
7710        }
7711    }
7712
7713    /**
7714     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7715     * implementation calls {@link #onProvideStructure} and
7716     * {@link #onProvideVirtualStructure}.
7717     */
7718    public void dispatchProvideStructure(ViewStructure structure) {
7719        dispatchProvideStructureForAssistOrAutofill(structure, false);
7720    }
7721
7722    /**
7723     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7724     *
7725     * <p>The structure must be filled according to the request type, which is set in the
7726     * {@code flags} parameter - see the documentation on each flag for more details.
7727     *
7728     * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
7729     * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7730     *
7731     * @param structure Fill in with structured view data.
7732     * @param flags optional flags (currently {@code 0}).
7733     */
7734    public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
7735        dispatchProvideStructureForAssistOrAutofill(structure, true);
7736    }
7737
7738    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7739            boolean forAutofill) {
7740        boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
7741        if (!blocked) {
7742            if (forAutofill) {
7743                setAutofillId(structure);
7744                // NOTE: flags are not currently supported, hence 0
7745                onProvideAutofillStructure(structure, 0);
7746                onProvideAutofillVirtualStructure(structure, 0);
7747            } else {
7748                onProvideStructure(structure);
7749                onProvideVirtualStructure(structure);
7750            }
7751        } else {
7752            structure.setClassName(getAccessibilityClassName().toString());
7753            structure.setAssistBlocked(true);
7754        }
7755    }
7756
7757    /**
7758     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7759     *
7760     * Note: Called from the default {@link AccessibilityDelegate}.
7761     *
7762     * @hide
7763     */
7764    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7765        if (mAttachInfo == null) {
7766            return;
7767        }
7768
7769        Rect bounds = mAttachInfo.mTmpInvalRect;
7770
7771        getDrawingRect(bounds);
7772        info.setBoundsInParent(bounds);
7773
7774        getBoundsOnScreen(bounds, true);
7775        info.setBoundsInScreen(bounds);
7776
7777        ViewParent parent = getParentForAccessibility();
7778        if (parent instanceof View) {
7779            info.setParent((View) parent);
7780        }
7781
7782        if (mID != View.NO_ID) {
7783            View rootView = getRootView();
7784            if (rootView == null) {
7785                rootView = this;
7786            }
7787
7788            View label = rootView.findLabelForView(this, mID);
7789            if (label != null) {
7790                info.setLabeledBy(label);
7791            }
7792
7793            if ((mAttachInfo.mAccessibilityFetchFlags
7794                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7795                    && Resources.resourceHasPackage(mID)) {
7796                try {
7797                    String viewId = getResources().getResourceName(mID);
7798                    info.setViewIdResourceName(viewId);
7799                } catch (Resources.NotFoundException nfe) {
7800                    /* ignore */
7801                }
7802            }
7803        }
7804
7805        if (mLabelForId != View.NO_ID) {
7806            View rootView = getRootView();
7807            if (rootView == null) {
7808                rootView = this;
7809            }
7810            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7811            if (labeled != null) {
7812                info.setLabelFor(labeled);
7813            }
7814        }
7815
7816        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7817            View rootView = getRootView();
7818            if (rootView == null) {
7819                rootView = this;
7820            }
7821            View next = rootView.findViewInsideOutShouldExist(this,
7822                    mAccessibilityTraversalBeforeId);
7823            if (next != null && next.includeForAccessibility()) {
7824                info.setTraversalBefore(next);
7825            }
7826        }
7827
7828        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7829            View rootView = getRootView();
7830            if (rootView == null) {
7831                rootView = this;
7832            }
7833            View next = rootView.findViewInsideOutShouldExist(this,
7834                    mAccessibilityTraversalAfterId);
7835            if (next != null && next.includeForAccessibility()) {
7836                info.setTraversalAfter(next);
7837            }
7838        }
7839
7840        info.setVisibleToUser(isVisibleToUser());
7841
7842        info.setImportantForAccessibility(isImportantForAccessibility());
7843        info.setPackageName(mContext.getPackageName());
7844        info.setClassName(getAccessibilityClassName());
7845        info.setContentDescription(getContentDescription());
7846
7847        info.setEnabled(isEnabled());
7848        info.setClickable(isClickable());
7849        info.setFocusable(isFocusable());
7850        info.setFocused(isFocused());
7851        info.setAccessibilityFocused(isAccessibilityFocused());
7852        info.setSelected(isSelected());
7853        info.setLongClickable(isLongClickable());
7854        info.setContextClickable(isContextClickable());
7855        info.setLiveRegion(getAccessibilityLiveRegion());
7856
7857        // TODO: These make sense only if we are in an AdapterView but all
7858        // views can be selected. Maybe from accessibility perspective
7859        // we should report as selectable view in an AdapterView.
7860        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7861        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7862
7863        if (isFocusable()) {
7864            if (isFocused()) {
7865                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7866            } else {
7867                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7868            }
7869        }
7870
7871        if (!isAccessibilityFocused()) {
7872            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7873        } else {
7874            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7875        }
7876
7877        if (isClickable() && isEnabled()) {
7878            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7879        }
7880
7881        if (isLongClickable() && isEnabled()) {
7882            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7883        }
7884
7885        if (isContextClickable() && isEnabled()) {
7886            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7887        }
7888
7889        CharSequence text = getIterableTextForAccessibility();
7890        if (text != null && text.length() > 0) {
7891            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7892
7893            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7894            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7895            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7896            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7897                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7898                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7899        }
7900
7901        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7902        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7903    }
7904
7905    /**
7906     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7907     * additional data.
7908     * <p>
7909     * This method only needs overloading if the node is marked as having extra data available.
7910     * </p>
7911     *
7912     * @param info The info to which to add the extra data. Never {@code null}.
7913     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7914     *                     extra data should be added to the {@link Bundle} returned by
7915     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7916     *                     {@code null}.
7917     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7918     *                  {@code null} if the service provided no arguments.
7919     *
7920     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
7921     */
7922    public void addExtraDataToAccessibilityNodeInfo(
7923            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7924            @Nullable Bundle arguments) {
7925    }
7926
7927    /**
7928     * Determine the order in which this view will be drawn relative to its siblings for a11y
7929     *
7930     * @param info The info whose drawing order should be populated
7931     */
7932    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7933        /*
7934         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7935         * drawing order may not be well-defined, and some Views with custom drawing order may
7936         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7937         */
7938        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7939            info.setDrawingOrder(0);
7940            return;
7941        }
7942        int drawingOrderInParent = 1;
7943        // Iterate up the hierarchy if parents are not important for a11y
7944        View viewAtDrawingLevel = this;
7945        final ViewParent parent = getParentForAccessibility();
7946        while (viewAtDrawingLevel != parent) {
7947            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7948            if (!(currentParent instanceof ViewGroup)) {
7949                // Should only happen for the Decor
7950                drawingOrderInParent = 0;
7951                break;
7952            } else {
7953                final ViewGroup parentGroup = (ViewGroup) currentParent;
7954                final int childCount = parentGroup.getChildCount();
7955                if (childCount > 1) {
7956                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7957                    if (preorderedList != null) {
7958                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7959                        for (int i = 0; i < childDrawIndex; i++) {
7960                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7961                        }
7962                    } else {
7963                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7964                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7965                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7966                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7967                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7968                        if (childDrawIndex != 0) {
7969                            for (int i = 0; i < numChildrenToIterate; i++) {
7970                                final int otherDrawIndex = (customOrder ?
7971                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7972                                if (otherDrawIndex < childDrawIndex) {
7973                                    drawingOrderInParent +=
7974                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7975                                }
7976                            }
7977                        }
7978                    }
7979                }
7980            }
7981            viewAtDrawingLevel = (View) currentParent;
7982        }
7983        info.setDrawingOrder(drawingOrderInParent);
7984    }
7985
7986    private static int numViewsForAccessibility(View view) {
7987        if (view != null) {
7988            if (view.includeForAccessibility()) {
7989                return 1;
7990            } else if (view instanceof ViewGroup) {
7991                return ((ViewGroup) view).getNumChildrenForAccessibility();
7992            }
7993        }
7994        return 0;
7995    }
7996
7997    private View findLabelForView(View view, int labeledId) {
7998        if (mMatchLabelForPredicate == null) {
7999            mMatchLabelForPredicate = new MatchLabelForPredicate();
8000        }
8001        mMatchLabelForPredicate.mLabeledId = labeledId;
8002        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8003    }
8004
8005    /**
8006     * Computes whether this view is visible to the user. Such a view is
8007     * attached, visible, all its predecessors are visible, it is not clipped
8008     * entirely by its predecessors, and has an alpha greater than zero.
8009     *
8010     * @return Whether the view is visible on the screen.
8011     *
8012     * @hide
8013     */
8014    protected boolean isVisibleToUser() {
8015        return isVisibleToUser(null);
8016    }
8017
8018    /**
8019     * Computes whether the given portion of this view is visible to the user.
8020     * Such a view is attached, visible, all its predecessors are visible,
8021     * has an alpha greater than zero, and the specified portion is not
8022     * clipped entirely by its predecessors.
8023     *
8024     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8025     *                    <code>null</code>, and the entire view will be tested in this case.
8026     *                    When <code>true</code> is returned by the function, the actual visible
8027     *                    region will be stored in this parameter; that is, if boundInView is fully
8028     *                    contained within the view, no modification will be made, otherwise regions
8029     *                    outside of the visible area of the view will be clipped.
8030     *
8031     * @return Whether the specified portion of the view is visible on the screen.
8032     *
8033     * @hide
8034     */
8035    protected boolean isVisibleToUser(Rect boundInView) {
8036        if (mAttachInfo != null) {
8037            // Attached to invisible window means this view is not visible.
8038            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8039                return false;
8040            }
8041            // An invisible predecessor or one with alpha zero means
8042            // that this view is not visible to the user.
8043            Object current = this;
8044            while (current instanceof View) {
8045                View view = (View) current;
8046                // We have attach info so this view is attached and there is no
8047                // need to check whether we reach to ViewRootImpl on the way up.
8048                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8049                        view.getVisibility() != VISIBLE) {
8050                    return false;
8051                }
8052                current = view.mParent;
8053            }
8054            // Check if the view is entirely covered by its predecessors.
8055            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8056            Point offset = mAttachInfo.mPoint;
8057            if (!getGlobalVisibleRect(visibleRect, offset)) {
8058                return false;
8059            }
8060            // Check if the visible portion intersects the rectangle of interest.
8061            if (boundInView != null) {
8062                visibleRect.offset(-offset.x, -offset.y);
8063                return boundInView.intersect(visibleRect);
8064            }
8065            return true;
8066        }
8067        return false;
8068    }
8069
8070    /**
8071     * Returns the delegate for implementing accessibility support via
8072     * composition. For more details see {@link AccessibilityDelegate}.
8073     *
8074     * @return The delegate, or null if none set.
8075     *
8076     * @hide
8077     */
8078    public AccessibilityDelegate getAccessibilityDelegate() {
8079        return mAccessibilityDelegate;
8080    }
8081
8082    /**
8083     * Sets a delegate for implementing accessibility support via composition
8084     * (as opposed to inheritance). For more details, see
8085     * {@link AccessibilityDelegate}.
8086     * <p>
8087     * <strong>Note:</strong> On platform versions prior to
8088     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8089     * views in the {@code android.widget.*} package are called <i>before</i>
8090     * host methods. This prevents certain properties such as class name from
8091     * being modified by overriding
8092     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8093     * as any changes will be overwritten by the host class.
8094     * <p>
8095     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8096     * methods are called <i>after</i> host methods, which all properties to be
8097     * modified without being overwritten by the host class.
8098     *
8099     * @param delegate the object to which accessibility method calls should be
8100     *                 delegated
8101     * @see AccessibilityDelegate
8102     */
8103    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8104        mAccessibilityDelegate = delegate;
8105    }
8106
8107    /**
8108     * Gets the provider for managing a virtual view hierarchy rooted at this View
8109     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8110     * that explore the window content.
8111     * <p>
8112     * If this method returns an instance, this instance is responsible for managing
8113     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8114     * View including the one representing the View itself. Similarly the returned
8115     * instance is responsible for performing accessibility actions on any virtual
8116     * view or the root view itself.
8117     * </p>
8118     * <p>
8119     * If an {@link AccessibilityDelegate} has been specified via calling
8120     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8121     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8122     * is responsible for handling this call.
8123     * </p>
8124     *
8125     * @return The provider.
8126     *
8127     * @see AccessibilityNodeProvider
8128     */
8129    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8130        if (mAccessibilityDelegate != null) {
8131            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8132        } else {
8133            return null;
8134        }
8135    }
8136
8137    /**
8138     * Gets the unique identifier of this view on the screen for accessibility purposes.
8139     *
8140     * @return The view accessibility id.
8141     *
8142     * @hide
8143     */
8144    public int getAccessibilityViewId() {
8145        if (mAccessibilityViewId == NO_ID) {
8146            mAccessibilityViewId = mContext.getNextAccessibilityId();
8147        }
8148        return mAccessibilityViewId;
8149    }
8150
8151    /**
8152     * Gets the unique identifier of the window in which this View reseides.
8153     *
8154     * @return The window accessibility id.
8155     *
8156     * @hide
8157     */
8158    public int getAccessibilityWindowId() {
8159        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8160                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8161    }
8162
8163    /**
8164     * Returns the {@link View}'s content description.
8165     * <p>
8166     * <strong>Note:</strong> Do not override this method, as it will have no
8167     * effect on the content description presented to accessibility services.
8168     * You must call {@link #setContentDescription(CharSequence)} to modify the
8169     * content description.
8170     *
8171     * @return the content description
8172     * @see #setContentDescription(CharSequence)
8173     * @attr ref android.R.styleable#View_contentDescription
8174     */
8175    @ViewDebug.ExportedProperty(category = "accessibility")
8176    public CharSequence getContentDescription() {
8177        return mContentDescription;
8178    }
8179
8180    /**
8181     * Sets the {@link View}'s content description.
8182     * <p>
8183     * A content description briefly describes the view and is primarily used
8184     * for accessibility support to determine how a view should be presented to
8185     * the user. In the case of a view with no textual representation, such as
8186     * {@link android.widget.ImageButton}, a useful content description
8187     * explains what the view does. For example, an image button with a phone
8188     * icon that is used to place a call may use "Call" as its content
8189     * description. An image of a floppy disk that is used to save a file may
8190     * use "Save".
8191     *
8192     * @param contentDescription The content description.
8193     * @see #getContentDescription()
8194     * @attr ref android.R.styleable#View_contentDescription
8195     */
8196    @RemotableViewMethod
8197    public void setContentDescription(CharSequence contentDescription) {
8198        if (mContentDescription == null) {
8199            if (contentDescription == null) {
8200                return;
8201            }
8202        } else if (mContentDescription.equals(contentDescription)) {
8203            return;
8204        }
8205        mContentDescription = contentDescription;
8206        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8207        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8208            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8209            notifySubtreeAccessibilityStateChangedIfNeeded();
8210        } else {
8211            notifyViewAccessibilityStateChangedIfNeeded(
8212                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8213        }
8214    }
8215
8216    /**
8217     * Sets the id of a view before which this one is visited in accessibility traversal.
8218     * A screen-reader must visit the content of this view before the content of the one
8219     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8220     * will traverse the entire content of B before traversing the entire content of A,
8221     * regardles of what traversal strategy it is using.
8222     * <p>
8223     * Views that do not have specified before/after relationships are traversed in order
8224     * determined by the screen-reader.
8225     * </p>
8226     * <p>
8227     * Setting that this view is before a view that is not important for accessibility
8228     * or if this view is not important for accessibility will have no effect as the
8229     * screen-reader is not aware of unimportant views.
8230     * </p>
8231     *
8232     * @param beforeId The id of a view this one precedes in accessibility traversal.
8233     *
8234     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8235     *
8236     * @see #setImportantForAccessibility(int)
8237     */
8238    @RemotableViewMethod
8239    public void setAccessibilityTraversalBefore(int beforeId) {
8240        if (mAccessibilityTraversalBeforeId == beforeId) {
8241            return;
8242        }
8243        mAccessibilityTraversalBeforeId = beforeId;
8244        notifyViewAccessibilityStateChangedIfNeeded(
8245                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8246    }
8247
8248    /**
8249     * Gets the id of a view before which this one is visited in accessibility traversal.
8250     *
8251     * @return The id of a view this one precedes in accessibility traversal if
8252     *         specified, otherwise {@link #NO_ID}.
8253     *
8254     * @see #setAccessibilityTraversalBefore(int)
8255     */
8256    public int getAccessibilityTraversalBefore() {
8257        return mAccessibilityTraversalBeforeId;
8258    }
8259
8260    /**
8261     * Sets the id of a view after which this one is visited in accessibility traversal.
8262     * A screen-reader must visit the content of the other view before the content of this
8263     * one. For example, if view B is set to be after view A, then a screen-reader
8264     * will traverse the entire content of A before traversing the entire content of B,
8265     * regardles of what traversal strategy it is using.
8266     * <p>
8267     * Views that do not have specified before/after relationships are traversed in order
8268     * determined by the screen-reader.
8269     * </p>
8270     * <p>
8271     * Setting that this view is after a view that is not important for accessibility
8272     * or if this view is not important for accessibility will have no effect as the
8273     * screen-reader is not aware of unimportant views.
8274     * </p>
8275     *
8276     * @param afterId The id of a view this one succedees in accessibility traversal.
8277     *
8278     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8279     *
8280     * @see #setImportantForAccessibility(int)
8281     */
8282    @RemotableViewMethod
8283    public void setAccessibilityTraversalAfter(int afterId) {
8284        if (mAccessibilityTraversalAfterId == afterId) {
8285            return;
8286        }
8287        mAccessibilityTraversalAfterId = afterId;
8288        notifyViewAccessibilityStateChangedIfNeeded(
8289                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8290    }
8291
8292    /**
8293     * Gets the id of a view after which this one is visited in accessibility traversal.
8294     *
8295     * @return The id of a view this one succeedes in accessibility traversal if
8296     *         specified, otherwise {@link #NO_ID}.
8297     *
8298     * @see #setAccessibilityTraversalAfter(int)
8299     */
8300    public int getAccessibilityTraversalAfter() {
8301        return mAccessibilityTraversalAfterId;
8302    }
8303
8304    /**
8305     * Gets the id of a view for which this view serves as a label for
8306     * accessibility purposes.
8307     *
8308     * @return The labeled view id.
8309     */
8310    @ViewDebug.ExportedProperty(category = "accessibility")
8311    public int getLabelFor() {
8312        return mLabelForId;
8313    }
8314
8315    /**
8316     * Sets the id of a view for which this view serves as a label for
8317     * accessibility purposes.
8318     *
8319     * @param id The labeled view id.
8320     */
8321    @RemotableViewMethod
8322    public void setLabelFor(@IdRes int id) {
8323        if (mLabelForId == id) {
8324            return;
8325        }
8326        mLabelForId = id;
8327        if (mLabelForId != View.NO_ID
8328                && mID == View.NO_ID) {
8329            mID = generateViewId();
8330        }
8331        notifyViewAccessibilityStateChangedIfNeeded(
8332                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8333    }
8334
8335    /**
8336     * Invoked whenever this view loses focus, either by losing window focus or by losing
8337     * focus within its window. This method can be used to clear any state tied to the
8338     * focus. For instance, if a button is held pressed with the trackball and the window
8339     * loses focus, this method can be used to cancel the press.
8340     *
8341     * Subclasses of View overriding this method should always call super.onFocusLost().
8342     *
8343     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8344     * @see #onWindowFocusChanged(boolean)
8345     *
8346     * @hide pending API council approval
8347     */
8348    @CallSuper
8349    protected void onFocusLost() {
8350        resetPressedState();
8351    }
8352
8353    private void resetPressedState() {
8354        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8355            return;
8356        }
8357
8358        if (isPressed()) {
8359            setPressed(false);
8360
8361            if (!mHasPerformedLongPress) {
8362                removeLongPressCallback();
8363            }
8364        }
8365    }
8366
8367    /**
8368     * Returns true if this view has focus
8369     *
8370     * @return True if this view has focus, false otherwise.
8371     */
8372    @ViewDebug.ExportedProperty(category = "focus")
8373    public boolean isFocused() {
8374        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8375    }
8376
8377    /**
8378     * Find the view in the hierarchy rooted at this view that currently has
8379     * focus.
8380     *
8381     * @return The view that currently has focus, or null if no focused view can
8382     *         be found.
8383     */
8384    public View findFocus() {
8385        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8386    }
8387
8388    /**
8389     * Indicates whether this view is one of the set of scrollable containers in
8390     * its window.
8391     *
8392     * @return whether this view is one of the set of scrollable containers in
8393     * its window
8394     *
8395     * @attr ref android.R.styleable#View_isScrollContainer
8396     */
8397    public boolean isScrollContainer() {
8398        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8399    }
8400
8401    /**
8402     * Change whether this view is one of the set of scrollable containers in
8403     * its window.  This will be used to determine whether the window can
8404     * resize or must pan when a soft input area is open -- scrollable
8405     * containers allow the window to use resize mode since the container
8406     * will appropriately shrink.
8407     *
8408     * @attr ref android.R.styleable#View_isScrollContainer
8409     */
8410    public void setScrollContainer(boolean isScrollContainer) {
8411        if (isScrollContainer) {
8412            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8413                mAttachInfo.mScrollContainers.add(this);
8414                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8415            }
8416            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8417        } else {
8418            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8419                mAttachInfo.mScrollContainers.remove(this);
8420            }
8421            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8422        }
8423    }
8424
8425    /**
8426     * Returns the quality of the drawing cache.
8427     *
8428     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8429     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8430     *
8431     * @see #setDrawingCacheQuality(int)
8432     * @see #setDrawingCacheEnabled(boolean)
8433     * @see #isDrawingCacheEnabled()
8434     *
8435     * @attr ref android.R.styleable#View_drawingCacheQuality
8436     */
8437    @DrawingCacheQuality
8438    public int getDrawingCacheQuality() {
8439        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8440    }
8441
8442    /**
8443     * Set the drawing cache quality of this view. This value is used only when the
8444     * drawing cache is enabled
8445     *
8446     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8447     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8448     *
8449     * @see #getDrawingCacheQuality()
8450     * @see #setDrawingCacheEnabled(boolean)
8451     * @see #isDrawingCacheEnabled()
8452     *
8453     * @attr ref android.R.styleable#View_drawingCacheQuality
8454     */
8455    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8456        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8457    }
8458
8459    /**
8460     * Returns whether the screen should remain on, corresponding to the current
8461     * value of {@link #KEEP_SCREEN_ON}.
8462     *
8463     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8464     *
8465     * @see #setKeepScreenOn(boolean)
8466     *
8467     * @attr ref android.R.styleable#View_keepScreenOn
8468     */
8469    public boolean getKeepScreenOn() {
8470        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8471    }
8472
8473    /**
8474     * Controls whether the screen should remain on, modifying the
8475     * value of {@link #KEEP_SCREEN_ON}.
8476     *
8477     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8478     *
8479     * @see #getKeepScreenOn()
8480     *
8481     * @attr ref android.R.styleable#View_keepScreenOn
8482     */
8483    public void setKeepScreenOn(boolean keepScreenOn) {
8484        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8485    }
8486
8487    /**
8488     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8489     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8490     *
8491     * @attr ref android.R.styleable#View_nextFocusLeft
8492     */
8493    public int getNextFocusLeftId() {
8494        return mNextFocusLeftId;
8495    }
8496
8497    /**
8498     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8499     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8500     * decide automatically.
8501     *
8502     * @attr ref android.R.styleable#View_nextFocusLeft
8503     */
8504    public void setNextFocusLeftId(int nextFocusLeftId) {
8505        mNextFocusLeftId = nextFocusLeftId;
8506    }
8507
8508    /**
8509     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8510     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8511     *
8512     * @attr ref android.R.styleable#View_nextFocusRight
8513     */
8514    public int getNextFocusRightId() {
8515        return mNextFocusRightId;
8516    }
8517
8518    /**
8519     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8520     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8521     * decide automatically.
8522     *
8523     * @attr ref android.R.styleable#View_nextFocusRight
8524     */
8525    public void setNextFocusRightId(int nextFocusRightId) {
8526        mNextFocusRightId = nextFocusRightId;
8527    }
8528
8529    /**
8530     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8531     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8532     *
8533     * @attr ref android.R.styleable#View_nextFocusUp
8534     */
8535    public int getNextFocusUpId() {
8536        return mNextFocusUpId;
8537    }
8538
8539    /**
8540     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8541     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8542     * decide automatically.
8543     *
8544     * @attr ref android.R.styleable#View_nextFocusUp
8545     */
8546    public void setNextFocusUpId(int nextFocusUpId) {
8547        mNextFocusUpId = nextFocusUpId;
8548    }
8549
8550    /**
8551     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8552     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8553     *
8554     * @attr ref android.R.styleable#View_nextFocusDown
8555     */
8556    public int getNextFocusDownId() {
8557        return mNextFocusDownId;
8558    }
8559
8560    /**
8561     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8562     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8563     * decide automatically.
8564     *
8565     * @attr ref android.R.styleable#View_nextFocusDown
8566     */
8567    public void setNextFocusDownId(int nextFocusDownId) {
8568        mNextFocusDownId = nextFocusDownId;
8569    }
8570
8571    /**
8572     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8573     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8574     *
8575     * @attr ref android.R.styleable#View_nextFocusForward
8576     */
8577    public int getNextFocusForwardId() {
8578        return mNextFocusForwardId;
8579    }
8580
8581    /**
8582     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8583     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8584     * decide automatically.
8585     *
8586     * @attr ref android.R.styleable#View_nextFocusForward
8587     */
8588    public void setNextFocusForwardId(int nextFocusForwardId) {
8589        mNextFocusForwardId = nextFocusForwardId;
8590    }
8591
8592    /**
8593     * Gets the id of the root of the next keyboard navigation cluster.
8594     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8595     * decide automatically.
8596     *
8597     * @attr ref android.R.styleable#View_nextClusterForward
8598     */
8599    public int getNextClusterForwardId() {
8600        return mNextClusterForwardId;
8601    }
8602
8603    /**
8604     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8605     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8606     * decide automatically.
8607     *
8608     * @attr ref android.R.styleable#View_nextClusterForward
8609     */
8610    public void setNextClusterForwardId(int nextClusterForwardId) {
8611        mNextClusterForwardId = nextClusterForwardId;
8612    }
8613
8614    /**
8615     * Returns the visibility of this view and all of its ancestors
8616     *
8617     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8618     */
8619    public boolean isShown() {
8620        View current = this;
8621        //noinspection ConstantConditions
8622        do {
8623            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8624                return false;
8625            }
8626            ViewParent parent = current.mParent;
8627            if (parent == null) {
8628                return false; // We are not attached to the view root
8629            }
8630            if (!(parent instanceof View)) {
8631                return true;
8632            }
8633            current = (View) parent;
8634        } while (current != null);
8635
8636        return false;
8637    }
8638
8639    /**
8640     * Called by the view hierarchy when the content insets for a window have
8641     * changed, to allow it to adjust its content to fit within those windows.
8642     * The content insets tell you the space that the status bar, input method,
8643     * and other system windows infringe on the application's window.
8644     *
8645     * <p>You do not normally need to deal with this function, since the default
8646     * window decoration given to applications takes care of applying it to the
8647     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8648     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8649     * and your content can be placed under those system elements.  You can then
8650     * use this method within your view hierarchy if you have parts of your UI
8651     * which you would like to ensure are not being covered.
8652     *
8653     * <p>The default implementation of this method simply applies the content
8654     * insets to the view's padding, consuming that content (modifying the
8655     * insets to be 0), and returning true.  This behavior is off by default, but can
8656     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8657     *
8658     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8659     * insets object is propagated down the hierarchy, so any changes made to it will
8660     * be seen by all following views (including potentially ones above in
8661     * the hierarchy since this is a depth-first traversal).  The first view
8662     * that returns true will abort the entire traversal.
8663     *
8664     * <p>The default implementation works well for a situation where it is
8665     * used with a container that covers the entire window, allowing it to
8666     * apply the appropriate insets to its content on all edges.  If you need
8667     * a more complicated layout (such as two different views fitting system
8668     * windows, one on the top of the window, and one on the bottom),
8669     * you can override the method and handle the insets however you would like.
8670     * Note that the insets provided by the framework are always relative to the
8671     * far edges of the window, not accounting for the location of the called view
8672     * within that window.  (In fact when this method is called you do not yet know
8673     * where the layout will place the view, as it is done before layout happens.)
8674     *
8675     * <p>Note: unlike many View methods, there is no dispatch phase to this
8676     * call.  If you are overriding it in a ViewGroup and want to allow the
8677     * call to continue to your children, you must be sure to call the super
8678     * implementation.
8679     *
8680     * <p>Here is a sample layout that makes use of fitting system windows
8681     * to have controls for a video view placed inside of the window decorations
8682     * that it hides and shows.  This can be used with code like the second
8683     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8684     *
8685     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8686     *
8687     * @param insets Current content insets of the window.  Prior to
8688     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8689     * the insets or else you and Android will be unhappy.
8690     *
8691     * @return {@code true} if this view applied the insets and it should not
8692     * continue propagating further down the hierarchy, {@code false} otherwise.
8693     * @see #getFitsSystemWindows()
8694     * @see #setFitsSystemWindows(boolean)
8695     * @see #setSystemUiVisibility(int)
8696     *
8697     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8698     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8699     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8700     * to implement handling their own insets.
8701     */
8702    @Deprecated
8703    protected boolean fitSystemWindows(Rect insets) {
8704        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8705            if (insets == null) {
8706                // Null insets by definition have already been consumed.
8707                // This call cannot apply insets since there are none to apply,
8708                // so return false.
8709                return false;
8710            }
8711            // If we're not in the process of dispatching the newer apply insets call,
8712            // that means we're not in the compatibility path. Dispatch into the newer
8713            // apply insets path and take things from there.
8714            try {
8715                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8716                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8717            } finally {
8718                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8719            }
8720        } else {
8721            // We're being called from the newer apply insets path.
8722            // Perform the standard fallback behavior.
8723            return fitSystemWindowsInt(insets);
8724        }
8725    }
8726
8727    private boolean fitSystemWindowsInt(Rect insets) {
8728        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8729            mUserPaddingStart = UNDEFINED_PADDING;
8730            mUserPaddingEnd = UNDEFINED_PADDING;
8731            Rect localInsets = sThreadLocal.get();
8732            if (localInsets == null) {
8733                localInsets = new Rect();
8734                sThreadLocal.set(localInsets);
8735            }
8736            boolean res = computeFitSystemWindows(insets, localInsets);
8737            mUserPaddingLeftInitial = localInsets.left;
8738            mUserPaddingRightInitial = localInsets.right;
8739            internalSetPadding(localInsets.left, localInsets.top,
8740                    localInsets.right, localInsets.bottom);
8741            return res;
8742        }
8743        return false;
8744    }
8745
8746    /**
8747     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8748     *
8749     * <p>This method should be overridden by views that wish to apply a policy different from or
8750     * in addition to the default behavior. Clients that wish to force a view subtree
8751     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8752     *
8753     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8754     * it will be called during dispatch instead of this method. The listener may optionally
8755     * call this method from its own implementation if it wishes to apply the view's default
8756     * insets policy in addition to its own.</p>
8757     *
8758     * <p>Implementations of this method should either return the insets parameter unchanged
8759     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8760     * that this view applied itself. This allows new inset types added in future platform
8761     * versions to pass through existing implementations unchanged without being erroneously
8762     * consumed.</p>
8763     *
8764     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8765     * property is set then the view will consume the system window insets and apply them
8766     * as padding for the view.</p>
8767     *
8768     * @param insets Insets to apply
8769     * @return The supplied insets with any applied insets consumed
8770     */
8771    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8772        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8773            // We weren't called from within a direct call to fitSystemWindows,
8774            // call into it as a fallback in case we're in a class that overrides it
8775            // and has logic to perform.
8776            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8777                return insets.consumeSystemWindowInsets();
8778            }
8779        } else {
8780            // We were called from within a direct call to fitSystemWindows.
8781            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8782                return insets.consumeSystemWindowInsets();
8783            }
8784        }
8785        return insets;
8786    }
8787
8788    /**
8789     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8790     * window insets to this view. The listener's
8791     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8792     * method will be called instead of the view's
8793     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8794     *
8795     * @param listener Listener to set
8796     *
8797     * @see #onApplyWindowInsets(WindowInsets)
8798     */
8799    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8800        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8801    }
8802
8803    /**
8804     * Request to apply the given window insets to this view or another view in its subtree.
8805     *
8806     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8807     * obscured by window decorations or overlays. This can include the status and navigation bars,
8808     * action bars, input methods and more. New inset categories may be added in the future.
8809     * The method returns the insets provided minus any that were applied by this view or its
8810     * children.</p>
8811     *
8812     * <p>Clients wishing to provide custom behavior should override the
8813     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8814     * {@link OnApplyWindowInsetsListener} via the
8815     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8816     * method.</p>
8817     *
8818     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8819     * </p>
8820     *
8821     * @param insets Insets to apply
8822     * @return The provided insets minus the insets that were consumed
8823     */
8824    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8825        try {
8826            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8827            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8828                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8829            } else {
8830                return onApplyWindowInsets(insets);
8831            }
8832        } finally {
8833            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8834        }
8835    }
8836
8837    /**
8838     * Compute the view's coordinate within the surface.
8839     *
8840     * <p>Computes the coordinates of this view in its surface. The argument
8841     * must be an array of two integers. After the method returns, the array
8842     * contains the x and y location in that order.</p>
8843     * @hide
8844     * @param location an array of two integers in which to hold the coordinates
8845     */
8846    public void getLocationInSurface(@Size(2) int[] location) {
8847        getLocationInWindow(location);
8848        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8849            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8850            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8851        }
8852    }
8853
8854    /**
8855     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8856     * only available if the view is attached.
8857     *
8858     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8859     */
8860    public WindowInsets getRootWindowInsets() {
8861        if (mAttachInfo != null) {
8862            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8863        }
8864        return null;
8865    }
8866
8867    /**
8868     * @hide Compute the insets that should be consumed by this view and the ones
8869     * that should propagate to those under it.
8870     */
8871    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8872        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8873                || mAttachInfo == null
8874                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8875                        && !mAttachInfo.mOverscanRequested)) {
8876            outLocalInsets.set(inoutInsets);
8877            inoutInsets.set(0, 0, 0, 0);
8878            return true;
8879        } else {
8880            // The application wants to take care of fitting system window for
8881            // the content...  however we still need to take care of any overscan here.
8882            final Rect overscan = mAttachInfo.mOverscanInsets;
8883            outLocalInsets.set(overscan);
8884            inoutInsets.left -= overscan.left;
8885            inoutInsets.top -= overscan.top;
8886            inoutInsets.right -= overscan.right;
8887            inoutInsets.bottom -= overscan.bottom;
8888            return false;
8889        }
8890    }
8891
8892    /**
8893     * Compute insets that should be consumed by this view and the ones that should propagate
8894     * to those under it.
8895     *
8896     * @param in Insets currently being processed by this View, likely received as a parameter
8897     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8898     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8899     *                       by this view
8900     * @return Insets that should be passed along to views under this one
8901     */
8902    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8903        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8904                || mAttachInfo == null
8905                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8906            outLocalInsets.set(in.getSystemWindowInsets());
8907            return in.consumeSystemWindowInsets();
8908        } else {
8909            outLocalInsets.set(0, 0, 0, 0);
8910            return in;
8911        }
8912    }
8913
8914    /**
8915     * Sets whether or not this view should account for system screen decorations
8916     * such as the status bar and inset its content; that is, controlling whether
8917     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8918     * executed.  See that method for more details.
8919     *
8920     * <p>Note that if you are providing your own implementation of
8921     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8922     * flag to true -- your implementation will be overriding the default
8923     * implementation that checks this flag.
8924     *
8925     * @param fitSystemWindows If true, then the default implementation of
8926     * {@link #fitSystemWindows(Rect)} will be executed.
8927     *
8928     * @attr ref android.R.styleable#View_fitsSystemWindows
8929     * @see #getFitsSystemWindows()
8930     * @see #fitSystemWindows(Rect)
8931     * @see #setSystemUiVisibility(int)
8932     */
8933    public void setFitsSystemWindows(boolean fitSystemWindows) {
8934        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8935    }
8936
8937    /**
8938     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8939     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8940     * will be executed.
8941     *
8942     * @return {@code true} if the default implementation of
8943     * {@link #fitSystemWindows(Rect)} will be executed.
8944     *
8945     * @attr ref android.R.styleable#View_fitsSystemWindows
8946     * @see #setFitsSystemWindows(boolean)
8947     * @see #fitSystemWindows(Rect)
8948     * @see #setSystemUiVisibility(int)
8949     */
8950    @ViewDebug.ExportedProperty
8951    public boolean getFitsSystemWindows() {
8952        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8953    }
8954
8955    /** @hide */
8956    public boolean fitsSystemWindows() {
8957        return getFitsSystemWindows();
8958    }
8959
8960    /**
8961     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8962     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8963     */
8964    @Deprecated
8965    public void requestFitSystemWindows() {
8966        if (mParent != null) {
8967            mParent.requestFitSystemWindows();
8968        }
8969    }
8970
8971    /**
8972     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8973     */
8974    public void requestApplyInsets() {
8975        requestFitSystemWindows();
8976    }
8977
8978    /**
8979     * For use by PhoneWindow to make its own system window fitting optional.
8980     * @hide
8981     */
8982    public void makeOptionalFitsSystemWindows() {
8983        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8984    }
8985
8986    /**
8987     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8988     * treat them as such.
8989     * @hide
8990     */
8991    public void getOutsets(Rect outOutsetRect) {
8992        if (mAttachInfo != null) {
8993            outOutsetRect.set(mAttachInfo.mOutsets);
8994        } else {
8995            outOutsetRect.setEmpty();
8996        }
8997    }
8998
8999    /**
9000     * Returns the visibility status for this view.
9001     *
9002     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9003     * @attr ref android.R.styleable#View_visibility
9004     */
9005    @ViewDebug.ExportedProperty(mapping = {
9006        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9007        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9008        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9009    })
9010    @Visibility
9011    public int getVisibility() {
9012        return mViewFlags & VISIBILITY_MASK;
9013    }
9014
9015    /**
9016     * Set the visibility state of this view.
9017     *
9018     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9019     * @attr ref android.R.styleable#View_visibility
9020     */
9021    @RemotableViewMethod
9022    public void setVisibility(@Visibility int visibility) {
9023        setFlags(visibility, VISIBILITY_MASK);
9024    }
9025
9026    /**
9027     * Returns the enabled status for this view. The interpretation of the
9028     * enabled state varies by subclass.
9029     *
9030     * @return True if this view is enabled, false otherwise.
9031     */
9032    @ViewDebug.ExportedProperty
9033    public boolean isEnabled() {
9034        return (mViewFlags & ENABLED_MASK) == ENABLED;
9035    }
9036
9037    /**
9038     * Set the enabled state of this view. The interpretation of the enabled
9039     * state varies by subclass.
9040     *
9041     * @param enabled True if this view is enabled, false otherwise.
9042     */
9043    @RemotableViewMethod
9044    public void setEnabled(boolean enabled) {
9045        if (enabled == isEnabled()) return;
9046
9047        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9048
9049        /*
9050         * The View most likely has to change its appearance, so refresh
9051         * the drawable state.
9052         */
9053        refreshDrawableState();
9054
9055        // Invalidate too, since the default behavior for views is to be
9056        // be drawn at 50% alpha rather than to change the drawable.
9057        invalidate(true);
9058
9059        if (!enabled) {
9060            cancelPendingInputEvents();
9061        }
9062    }
9063
9064    /**
9065     * Set whether this view can receive the focus.
9066     * <p>
9067     * Setting this to false will also ensure that this view is not focusable
9068     * in touch mode.
9069     *
9070     * @param focusable If true, this view can receive the focus.
9071     *
9072     * @see #setFocusableInTouchMode(boolean)
9073     * @see #setFocusable(int)
9074     * @attr ref android.R.styleable#View_focusable
9075     */
9076    public void setFocusable(boolean focusable) {
9077        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9078    }
9079
9080    /**
9081     * Sets whether this view can receive focus.
9082     * <p>
9083     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9084     * automatically based on the view's interactivity. This is the default.
9085     * <p>
9086     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9087     * in touch mode.
9088     *
9089     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9090     *                  or {@link #FOCUSABLE_AUTO}.
9091     * @see #setFocusableInTouchMode(boolean)
9092     * @attr ref android.R.styleable#View_focusable
9093     */
9094    public void setFocusable(@Focusable int focusable) {
9095        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9096            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9097        }
9098        setFlags(focusable, FOCUSABLE_MASK);
9099    }
9100
9101    /**
9102     * Set whether this view can receive focus while in touch mode.
9103     *
9104     * Setting this to true will also ensure that this view is focusable.
9105     *
9106     * @param focusableInTouchMode If true, this view can receive the focus while
9107     *   in touch mode.
9108     *
9109     * @see #setFocusable(boolean)
9110     * @attr ref android.R.styleable#View_focusableInTouchMode
9111     */
9112    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9113        // Focusable in touch mode should always be set before the focusable flag
9114        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9115        // which, in touch mode, will not successfully request focus on this view
9116        // because the focusable in touch mode flag is not set
9117        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9118
9119        // Clear FOCUSABLE_AUTO if set.
9120        if (focusableInTouchMode) {
9121            // Clears FOCUSABLE_AUTO if set.
9122            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9123        }
9124    }
9125
9126    /**
9127     * Sets the hints that helps the autofill service to select the appropriate data to fill the
9128     * view.
9129     *
9130     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9131     * @attr ref android.R.styleable#View_autofillHints
9132     */
9133    public void setAutofillHints(@Nullable String... autofillHints) {
9134        if (autofillHints == null || autofillHints.length == 0) {
9135            mAutofillHints = null;
9136        } else {
9137            mAutofillHints = autofillHints;
9138        }
9139    }
9140
9141    /**
9142     * @hide
9143     */
9144    @TestApi
9145    public void setAutofilled(boolean isAutofilled) {
9146        boolean wasChanged = isAutofilled != isAutofilled();
9147
9148        if (wasChanged) {
9149            if (isAutofilled) {
9150                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9151            } else {
9152                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9153            }
9154
9155            invalidate();
9156        }
9157    }
9158
9159    /**
9160     * Set whether this view should have sound effects enabled for events such as
9161     * clicking and touching.
9162     *
9163     * <p>You may wish to disable sound effects for a view if you already play sounds,
9164     * for instance, a dial key that plays dtmf tones.
9165     *
9166     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9167     * @see #isSoundEffectsEnabled()
9168     * @see #playSoundEffect(int)
9169     * @attr ref android.R.styleable#View_soundEffectsEnabled
9170     */
9171    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9172        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9173    }
9174
9175    /**
9176     * @return whether this view should have sound effects enabled for events such as
9177     *     clicking and touching.
9178     *
9179     * @see #setSoundEffectsEnabled(boolean)
9180     * @see #playSoundEffect(int)
9181     * @attr ref android.R.styleable#View_soundEffectsEnabled
9182     */
9183    @ViewDebug.ExportedProperty
9184    public boolean isSoundEffectsEnabled() {
9185        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9186    }
9187
9188    /**
9189     * Set whether this view should have haptic feedback for events such as
9190     * long presses.
9191     *
9192     * <p>You may wish to disable haptic feedback if your view already controls
9193     * its own haptic feedback.
9194     *
9195     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9196     * @see #isHapticFeedbackEnabled()
9197     * @see #performHapticFeedback(int)
9198     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9199     */
9200    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9201        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9202    }
9203
9204    /**
9205     * @return whether this view should have haptic feedback enabled for events
9206     * long presses.
9207     *
9208     * @see #setHapticFeedbackEnabled(boolean)
9209     * @see #performHapticFeedback(int)
9210     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9211     */
9212    @ViewDebug.ExportedProperty
9213    public boolean isHapticFeedbackEnabled() {
9214        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9215    }
9216
9217    /**
9218     * Returns the layout direction for this view.
9219     *
9220     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9221     *   {@link #LAYOUT_DIRECTION_RTL},
9222     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9223     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9224     *
9225     * @attr ref android.R.styleable#View_layoutDirection
9226     *
9227     * @hide
9228     */
9229    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9230        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9231        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9232        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9233        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9234    })
9235    @LayoutDir
9236    public int getRawLayoutDirection() {
9237        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9238    }
9239
9240    /**
9241     * Set the layout direction for this view. This will propagate a reset of layout direction
9242     * resolution to the view's children and resolve layout direction for this view.
9243     *
9244     * @param layoutDirection the layout direction to set. Should be one of:
9245     *
9246     * {@link #LAYOUT_DIRECTION_LTR},
9247     * {@link #LAYOUT_DIRECTION_RTL},
9248     * {@link #LAYOUT_DIRECTION_INHERIT},
9249     * {@link #LAYOUT_DIRECTION_LOCALE}.
9250     *
9251     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9252     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9253     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9254     *
9255     * @attr ref android.R.styleable#View_layoutDirection
9256     */
9257    @RemotableViewMethod
9258    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9259        if (getRawLayoutDirection() != layoutDirection) {
9260            // Reset the current layout direction and the resolved one
9261            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9262            resetRtlProperties();
9263            // Set the new layout direction (filtered)
9264            mPrivateFlags2 |=
9265                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9266            // We need to resolve all RTL properties as they all depend on layout direction
9267            resolveRtlPropertiesIfNeeded();
9268            requestLayout();
9269            invalidate(true);
9270        }
9271    }
9272
9273    /**
9274     * Returns the resolved layout direction for this view.
9275     *
9276     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9277     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9278     *
9279     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9280     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9281     *
9282     * @attr ref android.R.styleable#View_layoutDirection
9283     */
9284    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9285        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9286        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9287    })
9288    @ResolvedLayoutDir
9289    public int getLayoutDirection() {
9290        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9291        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9292            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9293            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9294        }
9295        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9296                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9297    }
9298
9299    /**
9300     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9301     * layout attribute and/or the inherited value from the parent
9302     *
9303     * @return true if the layout is right-to-left.
9304     *
9305     * @hide
9306     */
9307    @ViewDebug.ExportedProperty(category = "layout")
9308    public boolean isLayoutRtl() {
9309        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9310    }
9311
9312    /**
9313     * Indicates whether the view is currently tracking transient state that the
9314     * app should not need to concern itself with saving and restoring, but that
9315     * the framework should take special note to preserve when possible.
9316     *
9317     * <p>A view with transient state cannot be trivially rebound from an external
9318     * data source, such as an adapter binding item views in a list. This may be
9319     * because the view is performing an animation, tracking user selection
9320     * of content, or similar.</p>
9321     *
9322     * @return true if the view has transient state
9323     */
9324    @ViewDebug.ExportedProperty(category = "layout")
9325    public boolean hasTransientState() {
9326        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9327    }
9328
9329    /**
9330     * Set whether this view is currently tracking transient state that the
9331     * framework should attempt to preserve when possible. This flag is reference counted,
9332     * so every call to setHasTransientState(true) should be paired with a later call
9333     * to setHasTransientState(false).
9334     *
9335     * <p>A view with transient state cannot be trivially rebound from an external
9336     * data source, such as an adapter binding item views in a list. This may be
9337     * because the view is performing an animation, tracking user selection
9338     * of content, or similar.</p>
9339     *
9340     * @param hasTransientState true if this view has transient state
9341     */
9342    public void setHasTransientState(boolean hasTransientState) {
9343        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9344                mTransientStateCount - 1;
9345        if (mTransientStateCount < 0) {
9346            mTransientStateCount = 0;
9347            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9348                    "unmatched pair of setHasTransientState calls");
9349        } else if ((hasTransientState && mTransientStateCount == 1) ||
9350                (!hasTransientState && mTransientStateCount == 0)) {
9351            // update flag if we've just incremented up from 0 or decremented down to 0
9352            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9353                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9354            if (mParent != null) {
9355                try {
9356                    mParent.childHasTransientStateChanged(this, hasTransientState);
9357                } catch (AbstractMethodError e) {
9358                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9359                            " does not fully implement ViewParent", e);
9360                }
9361            }
9362        }
9363    }
9364
9365    /**
9366     * Returns true if this view is currently attached to a window.
9367     */
9368    public boolean isAttachedToWindow() {
9369        return mAttachInfo != null;
9370    }
9371
9372    /**
9373     * Returns true if this view has been through at least one layout since it
9374     * was last attached to or detached from a window.
9375     */
9376    public boolean isLaidOut() {
9377        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9378    }
9379
9380    /**
9381     * If this view doesn't do any drawing on its own, set this flag to
9382     * allow further optimizations. By default, this flag is not set on
9383     * View, but could be set on some View subclasses such as ViewGroup.
9384     *
9385     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9386     * you should clear this flag.
9387     *
9388     * @param willNotDraw whether or not this View draw on its own
9389     */
9390    public void setWillNotDraw(boolean willNotDraw) {
9391        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9392    }
9393
9394    /**
9395     * Returns whether or not this View draws on its own.
9396     *
9397     * @return true if this view has nothing to draw, false otherwise
9398     */
9399    @ViewDebug.ExportedProperty(category = "drawing")
9400    public boolean willNotDraw() {
9401        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9402    }
9403
9404    /**
9405     * When a View's drawing cache is enabled, drawing is redirected to an
9406     * offscreen bitmap. Some views, like an ImageView, must be able to
9407     * bypass this mechanism if they already draw a single bitmap, to avoid
9408     * unnecessary usage of the memory.
9409     *
9410     * @param willNotCacheDrawing true if this view does not cache its
9411     *        drawing, false otherwise
9412     */
9413    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9414        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9415    }
9416
9417    /**
9418     * Returns whether or not this View can cache its drawing or not.
9419     *
9420     * @return true if this view does not cache its drawing, false otherwise
9421     */
9422    @ViewDebug.ExportedProperty(category = "drawing")
9423    public boolean willNotCacheDrawing() {
9424        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9425    }
9426
9427    /**
9428     * Indicates whether this view reacts to click events or not.
9429     *
9430     * @return true if the view is clickable, false otherwise
9431     *
9432     * @see #setClickable(boolean)
9433     * @attr ref android.R.styleable#View_clickable
9434     */
9435    @ViewDebug.ExportedProperty
9436    public boolean isClickable() {
9437        return (mViewFlags & CLICKABLE) == CLICKABLE;
9438    }
9439
9440    /**
9441     * Enables or disables click events for this view. When a view
9442     * is clickable it will change its state to "pressed" on every click.
9443     * Subclasses should set the view clickable to visually react to
9444     * user's clicks.
9445     *
9446     * @param clickable true to make the view clickable, false otherwise
9447     *
9448     * @see #isClickable()
9449     * @attr ref android.R.styleable#View_clickable
9450     */
9451    public void setClickable(boolean clickable) {
9452        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9453    }
9454
9455    /**
9456     * Indicates whether this view reacts to long click events or not.
9457     *
9458     * @return true if the view is long clickable, false otherwise
9459     *
9460     * @see #setLongClickable(boolean)
9461     * @attr ref android.R.styleable#View_longClickable
9462     */
9463    public boolean isLongClickable() {
9464        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9465    }
9466
9467    /**
9468     * Enables or disables long click events for this view. When a view is long
9469     * clickable it reacts to the user holding down the button for a longer
9470     * duration than a tap. This event can either launch the listener or a
9471     * context menu.
9472     *
9473     * @param longClickable true to make the view long clickable, false otherwise
9474     * @see #isLongClickable()
9475     * @attr ref android.R.styleable#View_longClickable
9476     */
9477    public void setLongClickable(boolean longClickable) {
9478        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9479    }
9480
9481    /**
9482     * Indicates whether this view reacts to context clicks or not.
9483     *
9484     * @return true if the view is context clickable, false otherwise
9485     * @see #setContextClickable(boolean)
9486     * @attr ref android.R.styleable#View_contextClickable
9487     */
9488    public boolean isContextClickable() {
9489        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9490    }
9491
9492    /**
9493     * Enables or disables context clicking for this view. This event can launch the listener.
9494     *
9495     * @param contextClickable true to make the view react to a context click, false otherwise
9496     * @see #isContextClickable()
9497     * @attr ref android.R.styleable#View_contextClickable
9498     */
9499    public void setContextClickable(boolean contextClickable) {
9500        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9501    }
9502
9503    /**
9504     * Sets the pressed state for this view and provides a touch coordinate for
9505     * animation hinting.
9506     *
9507     * @param pressed Pass true to set the View's internal state to "pressed",
9508     *            or false to reverts the View's internal state from a
9509     *            previously set "pressed" state.
9510     * @param x The x coordinate of the touch that caused the press
9511     * @param y The y coordinate of the touch that caused the press
9512     */
9513    private void setPressed(boolean pressed, float x, float y) {
9514        if (pressed) {
9515            drawableHotspotChanged(x, y);
9516        }
9517
9518        setPressed(pressed);
9519    }
9520
9521    /**
9522     * Sets the pressed state for this view.
9523     *
9524     * @see #isClickable()
9525     * @see #setClickable(boolean)
9526     *
9527     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9528     *        the View's internal state from a previously set "pressed" state.
9529     */
9530    public void setPressed(boolean pressed) {
9531        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9532
9533        if (pressed) {
9534            mPrivateFlags |= PFLAG_PRESSED;
9535        } else {
9536            mPrivateFlags &= ~PFLAG_PRESSED;
9537        }
9538
9539        if (needsRefresh) {
9540            refreshDrawableState();
9541        }
9542        dispatchSetPressed(pressed);
9543    }
9544
9545    /**
9546     * Dispatch setPressed to all of this View's children.
9547     *
9548     * @see #setPressed(boolean)
9549     *
9550     * @param pressed The new pressed state
9551     */
9552    protected void dispatchSetPressed(boolean pressed) {
9553    }
9554
9555    /**
9556     * Indicates whether the view is currently in pressed state. Unless
9557     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9558     * the pressed state.
9559     *
9560     * @see #setPressed(boolean)
9561     * @see #isClickable()
9562     * @see #setClickable(boolean)
9563     *
9564     * @return true if the view is currently pressed, false otherwise
9565     */
9566    @ViewDebug.ExportedProperty
9567    public boolean isPressed() {
9568        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9569    }
9570
9571    /**
9572     * @hide
9573     * Indicates whether this view will participate in data collection through
9574     * {@link ViewStructure}.  If true, it will not provide any data
9575     * for itself or its children.  If false, the normal data collection will be allowed.
9576     *
9577     * @return Returns false if assist data collection is not blocked, else true.
9578     *
9579     * @see #setAssistBlocked(boolean)
9580     * @attr ref android.R.styleable#View_assistBlocked
9581     */
9582    public boolean isAssistBlocked() {
9583        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9584    }
9585
9586    /**
9587     * @hide
9588     * Indicates whether this view will participate in data collection through
9589     * {@link ViewStructure} for autofill purposes.
9590     *
9591     * <p>If {@code true}, it will not provide any data for itself or its children.
9592     * <p>If {@code false}, the normal data collection will be allowed.
9593     *
9594     * @return Returns {@code false} if assist data collection for autofill is not blocked,
9595     * else {@code true}.
9596     *
9597     * TODO(b/33197203): update / remove javadoc tags below
9598     * @see #setAssistBlocked(boolean)
9599     * @attr ref android.R.styleable#View_assistBlocked
9600     */
9601    public boolean isAutofillBlocked() {
9602        return false; // TODO(b/33197203): properly implement it
9603    }
9604
9605    /**
9606     * @hide
9607     * Controls whether assist data collection from this view and its children is enabled
9608     * (that is, whether {@link #onProvideStructure} and
9609     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9610     * allowing normal assist collection.  Setting this to false will disable assist collection.
9611     *
9612     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9613     * (the default) to allow it.
9614     *
9615     * @see #isAssistBlocked()
9616     * @see #onProvideStructure
9617     * @see #onProvideVirtualStructure
9618     * @attr ref android.R.styleable#View_assistBlocked
9619     */
9620    public void setAssistBlocked(boolean enabled) {
9621        if (enabled) {
9622            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9623        } else {
9624            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9625        }
9626    }
9627
9628    /**
9629     * Indicates whether this view will save its state (that is,
9630     * whether its {@link #onSaveInstanceState} method will be called).
9631     *
9632     * @return Returns true if the view state saving is enabled, else false.
9633     *
9634     * @see #setSaveEnabled(boolean)
9635     * @attr ref android.R.styleable#View_saveEnabled
9636     */
9637    public boolean isSaveEnabled() {
9638        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9639    }
9640
9641    /**
9642     * Controls whether the saving of this view's state is
9643     * enabled (that is, whether its {@link #onSaveInstanceState} method
9644     * will be called).  Note that even if freezing is enabled, the
9645     * view still must have an id assigned to it (via {@link #setId(int)})
9646     * for its state to be saved.  This flag can only disable the
9647     * saving of this view; any child views may still have their state saved.
9648     *
9649     * @param enabled Set to false to <em>disable</em> state saving, or true
9650     * (the default) to allow it.
9651     *
9652     * @see #isSaveEnabled()
9653     * @see #setId(int)
9654     * @see #onSaveInstanceState()
9655     * @attr ref android.R.styleable#View_saveEnabled
9656     */
9657    public void setSaveEnabled(boolean enabled) {
9658        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9659    }
9660
9661    /**
9662     * Gets whether the framework should discard touches when the view's
9663     * window is obscured by another visible window.
9664     * Refer to the {@link View} security documentation for more details.
9665     *
9666     * @return True if touch filtering is enabled.
9667     *
9668     * @see #setFilterTouchesWhenObscured(boolean)
9669     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9670     */
9671    @ViewDebug.ExportedProperty
9672    public boolean getFilterTouchesWhenObscured() {
9673        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9674    }
9675
9676    /**
9677     * Sets whether the framework should discard touches when the view's
9678     * window is obscured by another visible window.
9679     * Refer to the {@link View} security documentation for more details.
9680     *
9681     * @param enabled True if touch filtering should be enabled.
9682     *
9683     * @see #getFilterTouchesWhenObscured
9684     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9685     */
9686    public void setFilterTouchesWhenObscured(boolean enabled) {
9687        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9688                FILTER_TOUCHES_WHEN_OBSCURED);
9689    }
9690
9691    /**
9692     * Indicates whether the entire hierarchy under this view will save its
9693     * state when a state saving traversal occurs from its parent.  The default
9694     * is true; if false, these views will not be saved unless
9695     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9696     *
9697     * @return Returns true if the view state saving from parent is enabled, else false.
9698     *
9699     * @see #setSaveFromParentEnabled(boolean)
9700     */
9701    public boolean isSaveFromParentEnabled() {
9702        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9703    }
9704
9705    /**
9706     * Controls whether the entire hierarchy under this view will save its
9707     * state when a state saving traversal occurs from its parent.  The default
9708     * is true; if false, these views will not be saved unless
9709     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9710     *
9711     * @param enabled Set to false to <em>disable</em> state saving, or true
9712     * (the default) to allow it.
9713     *
9714     * @see #isSaveFromParentEnabled()
9715     * @see #setId(int)
9716     * @see #onSaveInstanceState()
9717     */
9718    public void setSaveFromParentEnabled(boolean enabled) {
9719        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9720    }
9721
9722
9723    /**
9724     * Returns whether this View is currently able to take focus.
9725     *
9726     * @return True if this view can take focus, or false otherwise.
9727     */
9728    @ViewDebug.ExportedProperty(category = "focus")
9729    public final boolean isFocusable() {
9730        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9731    }
9732
9733    /**
9734     * Returns the focusable setting for this view.
9735     *
9736     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9737     * @attr ref android.R.styleable#View_focusable
9738     */
9739    @ViewDebug.ExportedProperty(mapping = {
9740            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9741            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9742            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9743            }, category = "focus")
9744    @Focusable
9745    public int getFocusable() {
9746        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9747    }
9748
9749    /**
9750     * When a view is focusable, it may not want to take focus when in touch mode.
9751     * For example, a button would like focus when the user is navigating via a D-pad
9752     * so that the user can click on it, but once the user starts touching the screen,
9753     * the button shouldn't take focus
9754     * @return Whether the view is focusable in touch mode.
9755     * @attr ref android.R.styleable#View_focusableInTouchMode
9756     */
9757    @ViewDebug.ExportedProperty(category = "focus")
9758    public final boolean isFocusableInTouchMode() {
9759        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9760    }
9761
9762    /**
9763     * Find the nearest view in the specified direction that can take focus.
9764     * This does not actually give focus to that view.
9765     *
9766     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9767     *
9768     * @return The nearest focusable in the specified direction, or null if none
9769     *         can be found.
9770     */
9771    public View focusSearch(@FocusRealDirection int direction) {
9772        if (mParent != null) {
9773            return mParent.focusSearch(this, direction);
9774        } else {
9775            return null;
9776        }
9777    }
9778
9779    /**
9780     * Returns whether this View is a root of a keyboard navigation cluster.
9781     *
9782     * @return True if this view is a root of a cluster, or false otherwise.
9783     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9784     */
9785    @ViewDebug.ExportedProperty(category = "focus")
9786    public final boolean isKeyboardNavigationCluster() {
9787        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9788    }
9789
9790    /**
9791     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
9792     * will be ignored.
9793     *
9794     * @return the keyboard navigation cluster that this view is in (can be this view)
9795     *         or {@code null} if not in one
9796     */
9797    View findKeyboardNavigationCluster() {
9798        if (mParent instanceof View) {
9799            View cluster = ((View) mParent).findKeyboardNavigationCluster();
9800            if (cluster != null) {
9801                return cluster;
9802            } else if (isKeyboardNavigationCluster()) {
9803                return this;
9804            }
9805        }
9806        return null;
9807    }
9808
9809    /**
9810     * Set whether this view is a root of a keyboard navigation cluster.
9811     *
9812     * @param isCluster If true, this view is a root of a cluster.
9813     *
9814     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9815     */
9816    public void setKeyboardNavigationCluster(boolean isCluster) {
9817        if (isCluster) {
9818            mPrivateFlags3 |= PFLAG3_CLUSTER;
9819        } else {
9820            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9821        }
9822    }
9823
9824    /**
9825     * Sets this View as the one which receives focus the next time cluster navigation jumps
9826     * to the cluster containing this View. This does NOT change focus even if the cluster
9827     * containing this view is current.
9828     *
9829     * @hide
9830     */
9831    public final void setFocusedInCluster() {
9832        View top = findKeyboardNavigationCluster();
9833        if (top == this) {
9834            return;
9835        }
9836        ViewParent parent = mParent;
9837        View child = this;
9838        while (parent instanceof ViewGroup) {
9839            ((ViewGroup) parent).setFocusedInCluster(child);
9840            if (parent == top) {
9841                return;
9842            }
9843            child = (View) parent;
9844            parent = parent.getParent();
9845        }
9846    }
9847
9848    /**
9849     * Returns whether this View should receive focus when the focus is restored for the view
9850     * hierarchy containing this view.
9851     * <p>
9852     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9853     * window or serves as a target of cluster navigation.
9854     *
9855     * @see #restoreDefaultFocus()
9856     *
9857     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9858     * @attr ref android.R.styleable#View_focusedByDefault
9859     */
9860    @ViewDebug.ExportedProperty(category = "focus")
9861    public final boolean isFocusedByDefault() {
9862        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9863    }
9864
9865    /**
9866     * Sets whether this View should receive focus when the focus is restored for the view
9867     * hierarchy containing this view.
9868     * <p>
9869     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9870     * window or serves as a target of cluster navigation.
9871     *
9872     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9873     *                           {@code false} otherwise.
9874     *
9875     * @see #restoreDefaultFocus()
9876     *
9877     * @attr ref android.R.styleable#View_focusedByDefault
9878     */
9879    public void setFocusedByDefault(boolean isFocusedByDefault) {
9880        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9881            return;
9882        }
9883
9884        if (isFocusedByDefault) {
9885            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9886        } else {
9887            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9888        }
9889
9890        if (mParent instanceof ViewGroup) {
9891            if (isFocusedByDefault) {
9892                ((ViewGroup) mParent).setDefaultFocus(this);
9893            } else {
9894                ((ViewGroup) mParent).clearDefaultFocus(this);
9895            }
9896        }
9897    }
9898
9899    /**
9900     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9901     *
9902     * @return {@code true} if this view has default focus, {@code false} otherwise
9903     */
9904    boolean hasDefaultFocus() {
9905        return isFocusedByDefault();
9906    }
9907
9908    /**
9909     * Find the nearest keyboard navigation cluster in the specified direction.
9910     * This does not actually give focus to that cluster.
9911     *
9912     * @param currentCluster The starting point of the search. Null means the current cluster is not
9913     *                       found yet
9914     * @param direction Direction to look
9915     *
9916     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9917     *         can be found
9918     */
9919    public View keyboardNavigationClusterSearch(View currentCluster,
9920            @FocusDirection int direction) {
9921        if (isKeyboardNavigationCluster()) {
9922            currentCluster = this;
9923        }
9924        if (isRootNamespace()) {
9925            // Root namespace means we should consider ourselves the top of the
9926            // tree for group searching; otherwise we could be group searching
9927            // into other tabs.  see LocalActivityManager and TabHost for more info.
9928            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9929                    this, currentCluster, direction);
9930        } else if (mParent != null) {
9931            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9932        }
9933        return null;
9934    }
9935
9936    /**
9937     * This method is the last chance for the focused view and its ancestors to
9938     * respond to an arrow key. This is called when the focused view did not
9939     * consume the key internally, nor could the view system find a new view in
9940     * the requested direction to give focus to.
9941     *
9942     * @param focused The currently focused view.
9943     * @param direction The direction focus wants to move. One of FOCUS_UP,
9944     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9945     * @return True if the this view consumed this unhandled move.
9946     */
9947    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9948        return false;
9949    }
9950
9951    /**
9952     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
9953     * have {@link android.R.attr#state_focused} defined in its background.
9954     *
9955     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
9956     *                                      highlight, {@code false} otherwise.
9957     *
9958     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
9959     */
9960    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
9961        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
9962    }
9963
9964    /**
9965
9966    /**
9967     * Returns whether this View should use a default focus highlight when it gets focused but
9968     * doesn't have {@link android.R.attr#state_focused} defined in its background.
9969     *
9970     * @return True if this View should use a default focus highlight.
9971     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
9972     */
9973    @ViewDebug.ExportedProperty(category = "focus")
9974    public final boolean getDefaultFocusHighlightEnabled() {
9975        return mDefaultFocusHighlightEnabled;
9976    }
9977
9978    /**
9979     * If a user manually specified the next view id for a particular direction,
9980     * use the root to look up the view.
9981     * @param root The root view of the hierarchy containing this view.
9982     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9983     * or FOCUS_BACKWARD.
9984     * @return The user specified next view, or null if there is none.
9985     */
9986    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9987        switch (direction) {
9988            case FOCUS_LEFT:
9989                if (mNextFocusLeftId == View.NO_ID) return null;
9990                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9991            case FOCUS_RIGHT:
9992                if (mNextFocusRightId == View.NO_ID) return null;
9993                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9994            case FOCUS_UP:
9995                if (mNextFocusUpId == View.NO_ID) return null;
9996                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9997            case FOCUS_DOWN:
9998                if (mNextFocusDownId == View.NO_ID) return null;
9999                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10000            case FOCUS_FORWARD:
10001                if (mNextFocusForwardId == View.NO_ID) return null;
10002                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10003            case FOCUS_BACKWARD: {
10004                if (mID == View.NO_ID) return null;
10005                final int id = mID;
10006                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10007                    @Override
10008                    public boolean test(View t) {
10009                        return t.mNextFocusForwardId == id;
10010                    }
10011                });
10012            }
10013        }
10014        return null;
10015    }
10016
10017    /**
10018     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10019     * use the root to look up the view.
10020     *
10021     * @param root the root view of the hierarchy containing this view
10022     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10023     * @return the user-specified next cluster, or {@code null} if there is none
10024     */
10025    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10026        switch (direction) {
10027            case FOCUS_FORWARD:
10028                if (mNextClusterForwardId == View.NO_ID) return null;
10029                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10030            case FOCUS_BACKWARD: {
10031                if (mID == View.NO_ID) return null;
10032                final int id = mID;
10033                return root.findViewByPredicateInsideOut(this,
10034                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10035            }
10036        }
10037        return null;
10038    }
10039
10040    private View findViewInsideOutShouldExist(View root, int id) {
10041        if (mMatchIdPredicate == null) {
10042            mMatchIdPredicate = new MatchIdPredicate();
10043        }
10044        mMatchIdPredicate.mId = id;
10045        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10046        if (result == null) {
10047            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10048        }
10049        return result;
10050    }
10051
10052    /**
10053     * Find and return all focusable views that are descendants of this view,
10054     * possibly including this view if it is focusable itself.
10055     *
10056     * @param direction The direction of the focus
10057     * @return A list of focusable views
10058     */
10059    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10060        ArrayList<View> result = new ArrayList<View>(24);
10061        addFocusables(result, direction);
10062        return result;
10063    }
10064
10065    /**
10066     * Add any focusable views that are descendants of this view (possibly
10067     * including this view if it is focusable itself) to views.  If we are in touch mode,
10068     * only add views that are also focusable in touch mode.
10069     *
10070     * @param views Focusable views found so far
10071     * @param direction The direction of the focus
10072     */
10073    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10074        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10075    }
10076
10077    /**
10078     * Adds any focusable views that are descendants of this view (possibly
10079     * including this view if it is focusable itself) to views. This method
10080     * adds all focusable views regardless if we are in touch mode or
10081     * only views focusable in touch mode if we are in touch mode or
10082     * only views that can take accessibility focus if accessibility is enabled
10083     * depending on the focusable mode parameter.
10084     *
10085     * @param views Focusable views found so far or null if all we are interested is
10086     *        the number of focusables.
10087     * @param direction The direction of the focus.
10088     * @param focusableMode The type of focusables to be added.
10089     *
10090     * @see #FOCUSABLES_ALL
10091     * @see #FOCUSABLES_TOUCH_MODE
10092     */
10093    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10094            @FocusableMode int focusableMode) {
10095        if (views == null) {
10096            return;
10097        }
10098        if (!isFocusable()) {
10099            return;
10100        }
10101        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10102                && !isFocusableInTouchMode()) {
10103            return;
10104        }
10105        views.add(this);
10106    }
10107
10108    /**
10109     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10110     * including this view if it is a cluster root itself) to views.
10111     *
10112     * @param views Keyboard navigation cluster roots found so far
10113     * @param direction Direction to look
10114     */
10115    public void addKeyboardNavigationClusters(
10116            @NonNull Collection<View> views,
10117            int direction) {
10118        if (!isKeyboardNavigationCluster()) {
10119            return;
10120        }
10121        if (!hasFocusable()) {
10122            return;
10123        }
10124        views.add(this);
10125    }
10126
10127    /**
10128     * Finds the Views that contain given text. The containment is case insensitive.
10129     * The search is performed by either the text that the View renders or the content
10130     * description that describes the view for accessibility purposes and the view does
10131     * not render or both. Clients can specify how the search is to be performed via
10132     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10133     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10134     *
10135     * @param outViews The output list of matching Views.
10136     * @param searched The text to match against.
10137     *
10138     * @see #FIND_VIEWS_WITH_TEXT
10139     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10140     * @see #setContentDescription(CharSequence)
10141     */
10142    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10143            @FindViewFlags int flags) {
10144        if (getAccessibilityNodeProvider() != null) {
10145            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10146                outViews.add(this);
10147            }
10148        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10149                && (searched != null && searched.length() > 0)
10150                && (mContentDescription != null && mContentDescription.length() > 0)) {
10151            String searchedLowerCase = searched.toString().toLowerCase();
10152            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10153            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10154                outViews.add(this);
10155            }
10156        }
10157    }
10158
10159    /**
10160     * Find and return all touchable views that are descendants of this view,
10161     * possibly including this view if it is touchable itself.
10162     *
10163     * @return A list of touchable views
10164     */
10165    public ArrayList<View> getTouchables() {
10166        ArrayList<View> result = new ArrayList<View>();
10167        addTouchables(result);
10168        return result;
10169    }
10170
10171    /**
10172     * Add any touchable views that are descendants of this view (possibly
10173     * including this view if it is touchable itself) to views.
10174     *
10175     * @param views Touchable views found so far
10176     */
10177    public void addTouchables(ArrayList<View> views) {
10178        final int viewFlags = mViewFlags;
10179
10180        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10181                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10182                && (viewFlags & ENABLED_MASK) == ENABLED) {
10183            views.add(this);
10184        }
10185    }
10186
10187    /**
10188     * Returns whether this View is accessibility focused.
10189     *
10190     * @return True if this View is accessibility focused.
10191     */
10192    public boolean isAccessibilityFocused() {
10193        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10194    }
10195
10196    /**
10197     * Call this to try to give accessibility focus to this view.
10198     *
10199     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10200     * returns false or the view is no visible or the view already has accessibility
10201     * focus.
10202     *
10203     * See also {@link #focusSearch(int)}, which is what you call to say that you
10204     * have focus, and you want your parent to look for the next one.
10205     *
10206     * @return Whether this view actually took accessibility focus.
10207     *
10208     * @hide
10209     */
10210    public boolean requestAccessibilityFocus() {
10211        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10212        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10213            return false;
10214        }
10215        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10216            return false;
10217        }
10218        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10219            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10220            ViewRootImpl viewRootImpl = getViewRootImpl();
10221            if (viewRootImpl != null) {
10222                viewRootImpl.setAccessibilityFocus(this, null);
10223            }
10224            invalidate();
10225            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10226            return true;
10227        }
10228        return false;
10229    }
10230
10231    /**
10232     * Call this to try to clear accessibility focus of this view.
10233     *
10234     * See also {@link #focusSearch(int)}, which is what you call to say that you
10235     * have focus, and you want your parent to look for the next one.
10236     *
10237     * @hide
10238     */
10239    public void clearAccessibilityFocus() {
10240        clearAccessibilityFocusNoCallbacks(0);
10241
10242        // Clear the global reference of accessibility focus if this view or
10243        // any of its descendants had accessibility focus. This will NOT send
10244        // an event or update internal state if focus is cleared from a
10245        // descendant view, which may leave views in inconsistent states.
10246        final ViewRootImpl viewRootImpl = getViewRootImpl();
10247        if (viewRootImpl != null) {
10248            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10249            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10250                viewRootImpl.setAccessibilityFocus(null, null);
10251            }
10252        }
10253    }
10254
10255    private void sendAccessibilityHoverEvent(int eventType) {
10256        // Since we are not delivering to a client accessibility events from not
10257        // important views (unless the clinet request that) we need to fire the
10258        // event from the deepest view exposed to the client. As a consequence if
10259        // the user crosses a not exposed view the client will see enter and exit
10260        // of the exposed predecessor followed by and enter and exit of that same
10261        // predecessor when entering and exiting the not exposed descendant. This
10262        // is fine since the client has a clear idea which view is hovered at the
10263        // price of a couple more events being sent. This is a simple and
10264        // working solution.
10265        View source = this;
10266        while (true) {
10267            if (source.includeForAccessibility()) {
10268                source.sendAccessibilityEvent(eventType);
10269                return;
10270            }
10271            ViewParent parent = source.getParent();
10272            if (parent instanceof View) {
10273                source = (View) parent;
10274            } else {
10275                return;
10276            }
10277        }
10278    }
10279
10280    /**
10281     * Clears accessibility focus without calling any callback methods
10282     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10283     * is used separately from that one for clearing accessibility focus when
10284     * giving this focus to another view.
10285     *
10286     * @param action The action, if any, that led to focus being cleared. Set to
10287     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10288     * the window.
10289     */
10290    void clearAccessibilityFocusNoCallbacks(int action) {
10291        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10292            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10293            invalidate();
10294            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10295                AccessibilityEvent event = AccessibilityEvent.obtain(
10296                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10297                event.setAction(action);
10298                if (mAccessibilityDelegate != null) {
10299                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10300                } else {
10301                    sendAccessibilityEventUnchecked(event);
10302                }
10303            }
10304        }
10305    }
10306
10307    /**
10308     * Call this to try to give focus to a specific view or to one of its
10309     * descendants.
10310     *
10311     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10312     * false), or if it is focusable and it is not focusable in touch mode
10313     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10314     *
10315     * See also {@link #focusSearch(int)}, which is what you call to say that you
10316     * have focus, and you want your parent to look for the next one.
10317     *
10318     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10319     * {@link #FOCUS_DOWN} and <code>null</code>.
10320     *
10321     * @return Whether this view or one of its descendants actually took focus.
10322     */
10323    public final boolean requestFocus() {
10324        return requestFocus(View.FOCUS_DOWN);
10325    }
10326
10327    /**
10328     * This will request focus for whichever View was last focused within this
10329     * cluster before a focus-jump out of it.
10330     *
10331     * @hide
10332     */
10333    @TestApi
10334    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10335        // Prioritize focusableByDefault over algorithmic focus selection.
10336        if (restoreDefaultFocus()) {
10337            return true;
10338        }
10339        return requestFocus(direction);
10340    }
10341
10342    /**
10343     * This will request focus for whichever View not in a cluster was last focused before a
10344     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10345     * the "first" focusable view it finds.
10346     *
10347     * @hide
10348     */
10349    @TestApi
10350    public boolean restoreFocusNotInCluster() {
10351        return requestFocus(View.FOCUS_DOWN);
10352    }
10353
10354    /**
10355     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10356     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10357     *
10358     * @return Whether this view or one of its descendants actually took focus
10359     */
10360    public boolean restoreDefaultFocus() {
10361        return requestFocus(View.FOCUS_DOWN);
10362    }
10363
10364    /**
10365     * Call this to try to give focus to a specific view or to one of its
10366     * descendants and give it a hint about what direction focus is heading.
10367     *
10368     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10369     * false), or if it is focusable and it is not focusable in touch mode
10370     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10371     *
10372     * See also {@link #focusSearch(int)}, which is what you call to say that you
10373     * have focus, and you want your parent to look for the next one.
10374     *
10375     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10376     * <code>null</code> set for the previously focused rectangle.
10377     *
10378     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10379     * @return Whether this view or one of its descendants actually took focus.
10380     */
10381    public final boolean requestFocus(int direction) {
10382        return requestFocus(direction, null);
10383    }
10384
10385    /**
10386     * Call this to try to give focus to a specific view or to one of its descendants
10387     * and give it hints about the direction and a specific rectangle that the focus
10388     * is coming from.  The rectangle can help give larger views a finer grained hint
10389     * about where focus is coming from, and therefore, where to show selection, or
10390     * forward focus change internally.
10391     *
10392     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10393     * false), or if it is focusable and it is not focusable in touch mode
10394     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10395     *
10396     * A View will not take focus if it is not visible.
10397     *
10398     * A View will not take focus if one of its parents has
10399     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10400     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10401     *
10402     * See also {@link #focusSearch(int)}, which is what you call to say that you
10403     * have focus, and you want your parent to look for the next one.
10404     *
10405     * You may wish to override this method if your custom {@link View} has an internal
10406     * {@link View} that it wishes to forward the request to.
10407     *
10408     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10409     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10410     *        to give a finer grained hint about where focus is coming from.  May be null
10411     *        if there is no hint.
10412     * @return Whether this view or one of its descendants actually took focus.
10413     */
10414    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10415        return requestFocusNoSearch(direction, previouslyFocusedRect);
10416    }
10417
10418    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10419        // need to be focusable
10420        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10421                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10422            return false;
10423        }
10424
10425        // need to be focusable in touch mode if in touch mode
10426        if (isInTouchMode() &&
10427            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10428               return false;
10429        }
10430
10431        // need to not have any parents blocking us
10432        if (hasAncestorThatBlocksDescendantFocus()) {
10433            return false;
10434        }
10435
10436        handleFocusGainInternal(direction, previouslyFocusedRect);
10437        return true;
10438    }
10439
10440    /**
10441     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10442     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10443     * touch mode to request focus when they are touched.
10444     *
10445     * @return Whether this view or one of its descendants actually took focus.
10446     *
10447     * @see #isInTouchMode()
10448     *
10449     */
10450    public final boolean requestFocusFromTouch() {
10451        // Leave touch mode if we need to
10452        if (isInTouchMode()) {
10453            ViewRootImpl viewRoot = getViewRootImpl();
10454            if (viewRoot != null) {
10455                viewRoot.ensureTouchMode(false);
10456            }
10457        }
10458        return requestFocus(View.FOCUS_DOWN);
10459    }
10460
10461    /**
10462     * @return Whether any ancestor of this view blocks descendant focus.
10463     */
10464    private boolean hasAncestorThatBlocksDescendantFocus() {
10465        final boolean focusableInTouchMode = isFocusableInTouchMode();
10466        ViewParent ancestor = mParent;
10467        while (ancestor instanceof ViewGroup) {
10468            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10469            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10470                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10471                return true;
10472            } else {
10473                ancestor = vgAncestor.getParent();
10474            }
10475        }
10476        return false;
10477    }
10478
10479    /**
10480     * Gets the mode for determining whether this View is important for accessibility.
10481     * A view is important for accessibility if it fires accessibility events and if it
10482     * is reported to accessibility services that query the screen.
10483     *
10484     * @return The mode for determining whether a view is important for accessibility, one
10485     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10486     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10487     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10488     *
10489     * @attr ref android.R.styleable#View_importantForAccessibility
10490     *
10491     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10492     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10493     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10494     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10495     */
10496    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10497            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10498            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10499            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10500            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10501                    to = "noHideDescendants")
10502        })
10503    public int getImportantForAccessibility() {
10504        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10505                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10506    }
10507
10508    /**
10509     * Sets the live region mode for this view. This indicates to accessibility
10510     * services whether they should automatically notify the user about changes
10511     * to the view's content description or text, or to the content descriptions
10512     * or text of the view's children (where applicable).
10513     * <p>
10514     * For example, in a login screen with a TextView that displays an "incorrect
10515     * password" notification, that view should be marked as a live region with
10516     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10517     * <p>
10518     * To disable change notifications for this view, use
10519     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10520     * mode for most views.
10521     * <p>
10522     * To indicate that the user should be notified of changes, use
10523     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10524     * <p>
10525     * If the view's changes should interrupt ongoing speech and notify the user
10526     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10527     *
10528     * @param mode The live region mode for this view, one of:
10529     *        <ul>
10530     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10531     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10532     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10533     *        </ul>
10534     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10535     */
10536    public void setAccessibilityLiveRegion(int mode) {
10537        if (mode != getAccessibilityLiveRegion()) {
10538            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10539            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10540                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10541            notifyViewAccessibilityStateChangedIfNeeded(
10542                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10543        }
10544    }
10545
10546    /**
10547     * Gets the live region mode for this View.
10548     *
10549     * @return The live region mode for the view.
10550     *
10551     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10552     *
10553     * @see #setAccessibilityLiveRegion(int)
10554     */
10555    public int getAccessibilityLiveRegion() {
10556        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10557                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10558    }
10559
10560    /**
10561     * Sets how to determine whether this view is important for accessibility
10562     * which is if it fires accessibility events and if it is reported to
10563     * accessibility services that query the screen.
10564     *
10565     * @param mode How to determine whether this view is important for accessibility.
10566     *
10567     * @attr ref android.R.styleable#View_importantForAccessibility
10568     *
10569     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10570     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10571     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10572     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10573     */
10574    public void setImportantForAccessibility(int mode) {
10575        final int oldMode = getImportantForAccessibility();
10576        if (mode != oldMode) {
10577            final boolean hideDescendants =
10578                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10579
10580            // If this node or its descendants are no longer important, try to
10581            // clear accessibility focus.
10582            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10583                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10584                if (focusHost != null) {
10585                    focusHost.clearAccessibilityFocus();
10586                }
10587            }
10588
10589            // If we're moving between AUTO and another state, we might not need
10590            // to send a subtree changed notification. We'll store the computed
10591            // importance, since we'll need to check it later to make sure.
10592            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10593                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10594            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10595            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10596            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10597                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10598            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10599                notifySubtreeAccessibilityStateChangedIfNeeded();
10600            } else {
10601                notifyViewAccessibilityStateChangedIfNeeded(
10602                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10603            }
10604        }
10605    }
10606
10607    /**
10608     * Returns the view within this view's hierarchy that is hosting
10609     * accessibility focus.
10610     *
10611     * @param searchDescendants whether to search for focus in descendant views
10612     * @return the view hosting accessibility focus, or {@code null}
10613     */
10614    private View findAccessibilityFocusHost(boolean searchDescendants) {
10615        if (isAccessibilityFocusedViewOrHost()) {
10616            return this;
10617        }
10618
10619        if (searchDescendants) {
10620            final ViewRootImpl viewRoot = getViewRootImpl();
10621            if (viewRoot != null) {
10622                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10623                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10624                    return focusHost;
10625                }
10626            }
10627        }
10628
10629        return null;
10630    }
10631
10632    /**
10633     * Computes whether this view should be exposed for accessibility. In
10634     * general, views that are interactive or provide information are exposed
10635     * while views that serve only as containers are hidden.
10636     * <p>
10637     * If an ancestor of this view has importance
10638     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10639     * returns <code>false</code>.
10640     * <p>
10641     * Otherwise, the value is computed according to the view's
10642     * {@link #getImportantForAccessibility()} value:
10643     * <ol>
10644     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10645     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10646     * </code>
10647     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10648     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10649     * view satisfies any of the following:
10650     * <ul>
10651     * <li>Is actionable, e.g. {@link #isClickable()},
10652     * {@link #isLongClickable()}, or {@link #isFocusable()}
10653     * <li>Has an {@link AccessibilityDelegate}
10654     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10655     * {@link OnKeyListener}, etc.
10656     * <li>Is an accessibility live region, e.g.
10657     * {@link #getAccessibilityLiveRegion()} is not
10658     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10659     * </ul>
10660     * </ol>
10661     *
10662     * @return Whether the view is exposed for accessibility.
10663     * @see #setImportantForAccessibility(int)
10664     * @see #getImportantForAccessibility()
10665     */
10666    public boolean isImportantForAccessibility() {
10667        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10668                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10669        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10670                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10671            return false;
10672        }
10673
10674        // Check parent mode to ensure we're not hidden.
10675        ViewParent parent = mParent;
10676        while (parent instanceof View) {
10677            if (((View) parent).getImportantForAccessibility()
10678                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10679                return false;
10680            }
10681            parent = parent.getParent();
10682        }
10683
10684        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10685                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10686                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10687    }
10688
10689    /**
10690     * Gets the parent for accessibility purposes. Note that the parent for
10691     * accessibility is not necessary the immediate parent. It is the first
10692     * predecessor that is important for accessibility.
10693     *
10694     * @return The parent for accessibility purposes.
10695     */
10696    public ViewParent getParentForAccessibility() {
10697        if (mParent instanceof View) {
10698            View parentView = (View) mParent;
10699            if (parentView.includeForAccessibility()) {
10700                return mParent;
10701            } else {
10702                return mParent.getParentForAccessibility();
10703            }
10704        }
10705        return null;
10706    }
10707
10708    /**
10709     * Adds the children of this View relevant for accessibility to the given list
10710     * as output. Since some Views are not important for accessibility the added
10711     * child views are not necessarily direct children of this view, rather they are
10712     * the first level of descendants important for accessibility.
10713     *
10714     * @param outChildren The output list that will receive children for accessibility.
10715     */
10716    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10717
10718    }
10719
10720    /**
10721     * Whether to regard this view for accessibility. A view is regarded for
10722     * accessibility if it is important for accessibility or the querying
10723     * accessibility service has explicitly requested that view not
10724     * important for accessibility are regarded.
10725     *
10726     * @return Whether to regard the view for accessibility.
10727     *
10728     * @hide
10729     */
10730    public boolean includeForAccessibility() {
10731        if (mAttachInfo != null) {
10732            return (mAttachInfo.mAccessibilityFetchFlags
10733                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10734                    || isImportantForAccessibility();
10735        }
10736        return false;
10737    }
10738
10739    /**
10740     * Returns whether the View is considered actionable from
10741     * accessibility perspective. Such view are important for
10742     * accessibility.
10743     *
10744     * @return True if the view is actionable for accessibility.
10745     *
10746     * @hide
10747     */
10748    public boolean isActionableForAccessibility() {
10749        return (isClickable() || isLongClickable() || isFocusable());
10750    }
10751
10752    /**
10753     * Returns whether the View has registered callbacks which makes it
10754     * important for accessibility.
10755     *
10756     * @return True if the view is actionable for accessibility.
10757     */
10758    private boolean hasListenersForAccessibility() {
10759        ListenerInfo info = getListenerInfo();
10760        return mTouchDelegate != null || info.mOnKeyListener != null
10761                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10762                || info.mOnHoverListener != null || info.mOnDragListener != null;
10763    }
10764
10765    /**
10766     * Notifies that the accessibility state of this view changed. The change
10767     * is local to this view and does not represent structural changes such
10768     * as children and parent. For example, the view became focusable. The
10769     * notification is at at most once every
10770     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10771     * to avoid unnecessary load to the system. Also once a view has a pending
10772     * notification this method is a NOP until the notification has been sent.
10773     *
10774     * @hide
10775     */
10776    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10777        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10778            return;
10779        }
10780        if (mSendViewStateChangedAccessibilityEvent == null) {
10781            mSendViewStateChangedAccessibilityEvent =
10782                    new SendViewStateChangedAccessibilityEvent();
10783        }
10784        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10785    }
10786
10787    /**
10788     * Notifies that the accessibility state of this view changed. The change
10789     * is *not* local to this view and does represent structural changes such
10790     * as children and parent. For example, the view size changed. The
10791     * notification is at at most once every
10792     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10793     * to avoid unnecessary load to the system. Also once a view has a pending
10794     * notification this method is a NOP until the notification has been sent.
10795     *
10796     * @hide
10797     */
10798    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10799        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10800            return;
10801        }
10802        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10803            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10804            if (mParent != null) {
10805                try {
10806                    mParent.notifySubtreeAccessibilityStateChanged(
10807                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10808                } catch (AbstractMethodError e) {
10809                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10810                            " does not fully implement ViewParent", e);
10811                }
10812            }
10813        }
10814    }
10815
10816    /**
10817     * Change the visibility of the View without triggering any other changes. This is
10818     * important for transitions, where visibility changes should not adjust focus or
10819     * trigger a new layout. This is only used when the visibility has already been changed
10820     * and we need a transient value during an animation. When the animation completes,
10821     * the original visibility value is always restored.
10822     *
10823     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10824     * @hide
10825     */
10826    public void setTransitionVisibility(@Visibility int visibility) {
10827        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10828    }
10829
10830    /**
10831     * Reset the flag indicating the accessibility state of the subtree rooted
10832     * at this view changed.
10833     */
10834    void resetSubtreeAccessibilityStateChanged() {
10835        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10836    }
10837
10838    /**
10839     * Report an accessibility action to this view's parents for delegated processing.
10840     *
10841     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10842     * call this method to delegate an accessibility action to a supporting parent. If the parent
10843     * returns true from its
10844     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10845     * method this method will return true to signify that the action was consumed.</p>
10846     *
10847     * <p>This method is useful for implementing nested scrolling child views. If
10848     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10849     * a custom view implementation may invoke this method to allow a parent to consume the
10850     * scroll first. If this method returns true the custom view should skip its own scrolling
10851     * behavior.</p>
10852     *
10853     * @param action Accessibility action to delegate
10854     * @param arguments Optional action arguments
10855     * @return true if the action was consumed by a parent
10856     */
10857    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10858        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10859            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10860                return true;
10861            }
10862        }
10863        return false;
10864    }
10865
10866    /**
10867     * Performs the specified accessibility action on the view. For
10868     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10869     * <p>
10870     * If an {@link AccessibilityDelegate} has been specified via calling
10871     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10872     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10873     * is responsible for handling this call.
10874     * </p>
10875     *
10876     * <p>The default implementation will delegate
10877     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10878     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10879     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10880     *
10881     * @param action The action to perform.
10882     * @param arguments Optional action arguments.
10883     * @return Whether the action was performed.
10884     */
10885    public boolean performAccessibilityAction(int action, Bundle arguments) {
10886      if (mAccessibilityDelegate != null) {
10887          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10888      } else {
10889          return performAccessibilityActionInternal(action, arguments);
10890      }
10891    }
10892
10893   /**
10894    * @see #performAccessibilityAction(int, Bundle)
10895    *
10896    * Note: Called from the default {@link AccessibilityDelegate}.
10897    *
10898    * @hide
10899    */
10900    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10901        if (isNestedScrollingEnabled()
10902                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10903                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10904                || action == R.id.accessibilityActionScrollUp
10905                || action == R.id.accessibilityActionScrollLeft
10906                || action == R.id.accessibilityActionScrollDown
10907                || action == R.id.accessibilityActionScrollRight)) {
10908            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10909                return true;
10910            }
10911        }
10912
10913        switch (action) {
10914            case AccessibilityNodeInfo.ACTION_CLICK: {
10915                if (isClickable()) {
10916                    performClick();
10917                    return true;
10918                }
10919            } break;
10920            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10921                if (isLongClickable()) {
10922                    performLongClick();
10923                    return true;
10924                }
10925            } break;
10926            case AccessibilityNodeInfo.ACTION_FOCUS: {
10927                if (!hasFocus()) {
10928                    // Get out of touch mode since accessibility
10929                    // wants to move focus around.
10930                    getViewRootImpl().ensureTouchMode(false);
10931                    return requestFocus();
10932                }
10933            } break;
10934            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10935                if (hasFocus()) {
10936                    clearFocus();
10937                    return !isFocused();
10938                }
10939            } break;
10940            case AccessibilityNodeInfo.ACTION_SELECT: {
10941                if (!isSelected()) {
10942                    setSelected(true);
10943                    return isSelected();
10944                }
10945            } break;
10946            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10947                if (isSelected()) {
10948                    setSelected(false);
10949                    return !isSelected();
10950                }
10951            } break;
10952            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10953                if (!isAccessibilityFocused()) {
10954                    return requestAccessibilityFocus();
10955                }
10956            } break;
10957            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10958                if (isAccessibilityFocused()) {
10959                    clearAccessibilityFocus();
10960                    return true;
10961                }
10962            } break;
10963            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10964                if (arguments != null) {
10965                    final int granularity = arguments.getInt(
10966                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10967                    final boolean extendSelection = arguments.getBoolean(
10968                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10969                    return traverseAtGranularity(granularity, true, extendSelection);
10970                }
10971            } break;
10972            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10973                if (arguments != null) {
10974                    final int granularity = arguments.getInt(
10975                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10976                    final boolean extendSelection = arguments.getBoolean(
10977                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10978                    return traverseAtGranularity(granularity, false, extendSelection);
10979                }
10980            } break;
10981            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10982                CharSequence text = getIterableTextForAccessibility();
10983                if (text == null) {
10984                    return false;
10985                }
10986                final int start = (arguments != null) ? arguments.getInt(
10987                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10988                final int end = (arguments != null) ? arguments.getInt(
10989                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10990                // Only cursor position can be specified (selection length == 0)
10991                if ((getAccessibilitySelectionStart() != start
10992                        || getAccessibilitySelectionEnd() != end)
10993                        && (start == end)) {
10994                    setAccessibilitySelection(start, end);
10995                    notifyViewAccessibilityStateChangedIfNeeded(
10996                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10997                    return true;
10998                }
10999            } break;
11000            case R.id.accessibilityActionShowOnScreen: {
11001                if (mAttachInfo != null) {
11002                    final Rect r = mAttachInfo.mTmpInvalRect;
11003                    getDrawingRect(r);
11004                    return requestRectangleOnScreen(r, true);
11005                }
11006            } break;
11007            case R.id.accessibilityActionContextClick: {
11008                if (isContextClickable()) {
11009                    performContextClick();
11010                    return true;
11011                }
11012            } break;
11013        }
11014        return false;
11015    }
11016
11017    private boolean traverseAtGranularity(int granularity, boolean forward,
11018            boolean extendSelection) {
11019        CharSequence text = getIterableTextForAccessibility();
11020        if (text == null || text.length() == 0) {
11021            return false;
11022        }
11023        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11024        if (iterator == null) {
11025            return false;
11026        }
11027        int current = getAccessibilitySelectionEnd();
11028        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11029            current = forward ? 0 : text.length();
11030        }
11031        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11032        if (range == null) {
11033            return false;
11034        }
11035        final int segmentStart = range[0];
11036        final int segmentEnd = range[1];
11037        int selectionStart;
11038        int selectionEnd;
11039        if (extendSelection && isAccessibilitySelectionExtendable()) {
11040            selectionStart = getAccessibilitySelectionStart();
11041            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11042                selectionStart = forward ? segmentStart : segmentEnd;
11043            }
11044            selectionEnd = forward ? segmentEnd : segmentStart;
11045        } else {
11046            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11047        }
11048        setAccessibilitySelection(selectionStart, selectionEnd);
11049        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11050                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11051        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11052        return true;
11053    }
11054
11055    /**
11056     * Gets the text reported for accessibility purposes.
11057     *
11058     * @return The accessibility text.
11059     *
11060     * @hide
11061     */
11062    public CharSequence getIterableTextForAccessibility() {
11063        return getContentDescription();
11064    }
11065
11066    /**
11067     * Gets whether accessibility selection can be extended.
11068     *
11069     * @return If selection is extensible.
11070     *
11071     * @hide
11072     */
11073    public boolean isAccessibilitySelectionExtendable() {
11074        return false;
11075    }
11076
11077    /**
11078     * @hide
11079     */
11080    public int getAccessibilitySelectionStart() {
11081        return mAccessibilityCursorPosition;
11082    }
11083
11084    /**
11085     * @hide
11086     */
11087    public int getAccessibilitySelectionEnd() {
11088        return getAccessibilitySelectionStart();
11089    }
11090
11091    /**
11092     * @hide
11093     */
11094    public void setAccessibilitySelection(int start, int end) {
11095        if (start ==  end && end == mAccessibilityCursorPosition) {
11096            return;
11097        }
11098        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11099            mAccessibilityCursorPosition = start;
11100        } else {
11101            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11102        }
11103        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11104    }
11105
11106    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11107            int fromIndex, int toIndex) {
11108        if (mParent == null) {
11109            return;
11110        }
11111        AccessibilityEvent event = AccessibilityEvent.obtain(
11112                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11113        onInitializeAccessibilityEvent(event);
11114        onPopulateAccessibilityEvent(event);
11115        event.setFromIndex(fromIndex);
11116        event.setToIndex(toIndex);
11117        event.setAction(action);
11118        event.setMovementGranularity(granularity);
11119        mParent.requestSendAccessibilityEvent(this, event);
11120    }
11121
11122    /**
11123     * @hide
11124     */
11125    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11126        switch (granularity) {
11127            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11128                CharSequence text = getIterableTextForAccessibility();
11129                if (text != null && text.length() > 0) {
11130                    CharacterTextSegmentIterator iterator =
11131                        CharacterTextSegmentIterator.getInstance(
11132                                mContext.getResources().getConfiguration().locale);
11133                    iterator.initialize(text.toString());
11134                    return iterator;
11135                }
11136            } break;
11137            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11138                CharSequence text = getIterableTextForAccessibility();
11139                if (text != null && text.length() > 0) {
11140                    WordTextSegmentIterator iterator =
11141                        WordTextSegmentIterator.getInstance(
11142                                mContext.getResources().getConfiguration().locale);
11143                    iterator.initialize(text.toString());
11144                    return iterator;
11145                }
11146            } break;
11147            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11148                CharSequence text = getIterableTextForAccessibility();
11149                if (text != null && text.length() > 0) {
11150                    ParagraphTextSegmentIterator iterator =
11151                        ParagraphTextSegmentIterator.getInstance();
11152                    iterator.initialize(text.toString());
11153                    return iterator;
11154                }
11155            } break;
11156        }
11157        return null;
11158    }
11159
11160    /**
11161     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11162     * and {@link #onFinishTemporaryDetach()}.
11163     *
11164     * <p>This method always returns {@code true} when called directly or indirectly from
11165     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11166     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11167     * <ul>
11168     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11169     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11170     * </ul>
11171     * </p>
11172     *
11173     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11174     * and {@link #onFinishTemporaryDetach()}.
11175     */
11176    public final boolean isTemporarilyDetached() {
11177        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11178    }
11179
11180    /**
11181     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11182     * a container View.
11183     */
11184    @CallSuper
11185    public void dispatchStartTemporaryDetach() {
11186        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11187        notifyEnterOrExitForAutoFillIfNeeded(false);
11188        onStartTemporaryDetach();
11189    }
11190
11191    /**
11192     * This is called when a container is going to temporarily detach a child, with
11193     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11194     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11195     * {@link #onDetachedFromWindow()} when the container is done.
11196     */
11197    public void onStartTemporaryDetach() {
11198        removeUnsetPressCallback();
11199        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11200    }
11201
11202    /**
11203     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11204     * a container View.
11205     */
11206    @CallSuper
11207    public void dispatchFinishTemporaryDetach() {
11208        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11209        onFinishTemporaryDetach();
11210        if (hasWindowFocus() && hasFocus()) {
11211            InputMethodManager.getInstance().focusIn(this);
11212        }
11213        notifyEnterOrExitForAutoFillIfNeeded(true);
11214    }
11215
11216    /**
11217     * Called after {@link #onStartTemporaryDetach} when the container is done
11218     * changing the view.
11219     */
11220    public void onFinishTemporaryDetach() {
11221    }
11222
11223    /**
11224     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11225     * for this view's window.  Returns null if the view is not currently attached
11226     * to the window.  Normally you will not need to use this directly, but
11227     * just use the standard high-level event callbacks like
11228     * {@link #onKeyDown(int, KeyEvent)}.
11229     */
11230    public KeyEvent.DispatcherState getKeyDispatcherState() {
11231        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11232    }
11233
11234    /**
11235     * Dispatch a key event before it is processed by any input method
11236     * associated with the view hierarchy.  This can be used to intercept
11237     * key events in special situations before the IME consumes them; a
11238     * typical example would be handling the BACK key to update the application's
11239     * UI instead of allowing the IME to see it and close itself.
11240     *
11241     * @param event The key event to be dispatched.
11242     * @return True if the event was handled, false otherwise.
11243     */
11244    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11245        return onKeyPreIme(event.getKeyCode(), event);
11246    }
11247
11248    /**
11249     * Dispatch a key event to the next view on the focus path. This path runs
11250     * from the top of the view tree down to the currently focused view. If this
11251     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11252     * the next node down the focus path. This method also fires any key
11253     * listeners.
11254     *
11255     * @param event The key event to be dispatched.
11256     * @return True if the event was handled, false otherwise.
11257     */
11258    public boolean dispatchKeyEvent(KeyEvent event) {
11259        if (mInputEventConsistencyVerifier != null) {
11260            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11261        }
11262
11263        // Give any attached key listener a first crack at the event.
11264        //noinspection SimplifiableIfStatement
11265        ListenerInfo li = mListenerInfo;
11266        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11267                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11268            return true;
11269        }
11270
11271        if (event.dispatch(this, mAttachInfo != null
11272                ? mAttachInfo.mKeyDispatchState : null, this)) {
11273            return true;
11274        }
11275
11276        if (mInputEventConsistencyVerifier != null) {
11277            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11278        }
11279        return false;
11280    }
11281
11282    /**
11283     * Dispatches a key shortcut event.
11284     *
11285     * @param event The key event to be dispatched.
11286     * @return True if the event was handled by the view, false otherwise.
11287     */
11288    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11289        return onKeyShortcut(event.getKeyCode(), event);
11290    }
11291
11292    /**
11293     * Pass the touch screen motion event down to the target view, or this
11294     * view if it is the target.
11295     *
11296     * @param event The motion event to be dispatched.
11297     * @return True if the event was handled by the view, false otherwise.
11298     */
11299    public boolean dispatchTouchEvent(MotionEvent event) {
11300        // If the event should be handled by accessibility focus first.
11301        if (event.isTargetAccessibilityFocus()) {
11302            // We don't have focus or no virtual descendant has it, do not handle the event.
11303            if (!isAccessibilityFocusedViewOrHost()) {
11304                return false;
11305            }
11306            // We have focus and got the event, then use normal event dispatch.
11307            event.setTargetAccessibilityFocus(false);
11308        }
11309
11310        boolean result = false;
11311
11312        if (mInputEventConsistencyVerifier != null) {
11313            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11314        }
11315
11316        final int actionMasked = event.getActionMasked();
11317        if (actionMasked == MotionEvent.ACTION_DOWN) {
11318            // Defensive cleanup for new gesture
11319            stopNestedScroll();
11320        }
11321
11322        if (onFilterTouchEventForSecurity(event)) {
11323            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11324                result = true;
11325            }
11326            //noinspection SimplifiableIfStatement
11327            ListenerInfo li = mListenerInfo;
11328            if (li != null && li.mOnTouchListener != null
11329                    && (mViewFlags & ENABLED_MASK) == ENABLED
11330                    && li.mOnTouchListener.onTouch(this, event)) {
11331                result = true;
11332            }
11333
11334            if (!result && onTouchEvent(event)) {
11335                result = true;
11336            }
11337        }
11338
11339        if (!result && mInputEventConsistencyVerifier != null) {
11340            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11341        }
11342
11343        // Clean up after nested scrolls if this is the end of a gesture;
11344        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11345        // of the gesture.
11346        if (actionMasked == MotionEvent.ACTION_UP ||
11347                actionMasked == MotionEvent.ACTION_CANCEL ||
11348                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11349            stopNestedScroll();
11350        }
11351
11352        return result;
11353    }
11354
11355    boolean isAccessibilityFocusedViewOrHost() {
11356        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11357                .getAccessibilityFocusedHost() == this);
11358    }
11359
11360    /**
11361     * Filter the touch event to apply security policies.
11362     *
11363     * @param event The motion event to be filtered.
11364     * @return True if the event should be dispatched, false if the event should be dropped.
11365     *
11366     * @see #getFilterTouchesWhenObscured
11367     */
11368    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11369        //noinspection RedundantIfStatement
11370        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11371                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11372            // Window is obscured, drop this touch.
11373            return false;
11374        }
11375        return true;
11376    }
11377
11378    /**
11379     * Pass a trackball motion event down to the focused view.
11380     *
11381     * @param event The motion event to be dispatched.
11382     * @return True if the event was handled by the view, false otherwise.
11383     */
11384    public boolean dispatchTrackballEvent(MotionEvent event) {
11385        if (mInputEventConsistencyVerifier != null) {
11386            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11387        }
11388
11389        return onTrackballEvent(event);
11390    }
11391
11392    /**
11393     * Pass a captured pointer event down to the focused view.
11394     *
11395     * @param event The motion event to be dispatched.
11396     * @return True if the event was handled by the view, false otherwise.
11397     */
11398    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11399        if (!hasPointerCapture()) {
11400            return false;
11401        }
11402        //noinspection SimplifiableIfStatement
11403        ListenerInfo li = mListenerInfo;
11404        if (li != null && li.mOnCapturedPointerListener != null
11405                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11406            return true;
11407        }
11408        return onCapturedPointerEvent(event);
11409    }
11410
11411    /**
11412     * Dispatch a generic motion event.
11413     * <p>
11414     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11415     * are delivered to the view under the pointer.  All other generic motion events are
11416     * delivered to the focused view.  Hover events are handled specially and are delivered
11417     * to {@link #onHoverEvent(MotionEvent)}.
11418     * </p>
11419     *
11420     * @param event The motion event to be dispatched.
11421     * @return True if the event was handled by the view, false otherwise.
11422     */
11423    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11424        if (mInputEventConsistencyVerifier != null) {
11425            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11426        }
11427
11428        final int source = event.getSource();
11429        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11430            final int action = event.getAction();
11431            if (action == MotionEvent.ACTION_HOVER_ENTER
11432                    || action == MotionEvent.ACTION_HOVER_MOVE
11433                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11434                if (dispatchHoverEvent(event)) {
11435                    return true;
11436                }
11437            } else if (dispatchGenericPointerEvent(event)) {
11438                return true;
11439            }
11440        } else if (dispatchGenericFocusedEvent(event)) {
11441            return true;
11442        }
11443
11444        if (dispatchGenericMotionEventInternal(event)) {
11445            return true;
11446        }
11447
11448        if (mInputEventConsistencyVerifier != null) {
11449            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11450        }
11451        return false;
11452    }
11453
11454    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11455        //noinspection SimplifiableIfStatement
11456        ListenerInfo li = mListenerInfo;
11457        if (li != null && li.mOnGenericMotionListener != null
11458                && (mViewFlags & ENABLED_MASK) == ENABLED
11459                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11460            return true;
11461        }
11462
11463        if (onGenericMotionEvent(event)) {
11464            return true;
11465        }
11466
11467        final int actionButton = event.getActionButton();
11468        switch (event.getActionMasked()) {
11469            case MotionEvent.ACTION_BUTTON_PRESS:
11470                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11471                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11472                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11473                    if (performContextClick(event.getX(), event.getY())) {
11474                        mInContextButtonPress = true;
11475                        setPressed(true, event.getX(), event.getY());
11476                        removeTapCallback();
11477                        removeLongPressCallback();
11478                        return true;
11479                    }
11480                }
11481                break;
11482
11483            case MotionEvent.ACTION_BUTTON_RELEASE:
11484                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11485                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11486                    mInContextButtonPress = false;
11487                    mIgnoreNextUpEvent = true;
11488                }
11489                break;
11490        }
11491
11492        if (mInputEventConsistencyVerifier != null) {
11493            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11494        }
11495        return false;
11496    }
11497
11498    /**
11499     * Dispatch a hover event.
11500     * <p>
11501     * Do not call this method directly.
11502     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11503     * </p>
11504     *
11505     * @param event The motion event to be dispatched.
11506     * @return True if the event was handled by the view, false otherwise.
11507     */
11508    protected boolean dispatchHoverEvent(MotionEvent event) {
11509        ListenerInfo li = mListenerInfo;
11510        //noinspection SimplifiableIfStatement
11511        if (li != null && li.mOnHoverListener != null
11512                && (mViewFlags & ENABLED_MASK) == ENABLED
11513                && li.mOnHoverListener.onHover(this, event)) {
11514            return true;
11515        }
11516
11517        return onHoverEvent(event);
11518    }
11519
11520    /**
11521     * Returns true if the view has a child to which it has recently sent
11522     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11523     * it does not have a hovered child, then it must be the innermost hovered view.
11524     * @hide
11525     */
11526    protected boolean hasHoveredChild() {
11527        return false;
11528    }
11529
11530    /**
11531     * Dispatch a generic motion event to the view under the first pointer.
11532     * <p>
11533     * Do not call this method directly.
11534     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11535     * </p>
11536     *
11537     * @param event The motion event to be dispatched.
11538     * @return True if the event was handled by the view, false otherwise.
11539     */
11540    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11541        return false;
11542    }
11543
11544    /**
11545     * Dispatch a generic motion event to the currently focused view.
11546     * <p>
11547     * Do not call this method directly.
11548     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11549     * </p>
11550     *
11551     * @param event The motion event to be dispatched.
11552     * @return True if the event was handled by the view, false otherwise.
11553     */
11554    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11555        return false;
11556    }
11557
11558    /**
11559     * Dispatch a pointer event.
11560     * <p>
11561     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11562     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11563     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11564     * and should not be expected to handle other pointing device features.
11565     * </p>
11566     *
11567     * @param event The motion event to be dispatched.
11568     * @return True if the event was handled by the view, false otherwise.
11569     * @hide
11570     */
11571    public final boolean dispatchPointerEvent(MotionEvent event) {
11572        if (event.isTouchEvent()) {
11573            return dispatchTouchEvent(event);
11574        } else {
11575            return dispatchGenericMotionEvent(event);
11576        }
11577    }
11578
11579    /**
11580     * Called when the window containing this view gains or loses window focus.
11581     * ViewGroups should override to route to their children.
11582     *
11583     * @param hasFocus True if the window containing this view now has focus,
11584     *        false otherwise.
11585     */
11586    public void dispatchWindowFocusChanged(boolean hasFocus) {
11587        onWindowFocusChanged(hasFocus);
11588    }
11589
11590    /**
11591     * Called when the window containing this view gains or loses focus.  Note
11592     * that this is separate from view focus: to receive key events, both
11593     * your view and its window must have focus.  If a window is displayed
11594     * on top of yours that takes input focus, then your own window will lose
11595     * focus but the view focus will remain unchanged.
11596     *
11597     * @param hasWindowFocus True if the window containing this view now has
11598     *        focus, false otherwise.
11599     */
11600    public void onWindowFocusChanged(boolean hasWindowFocus) {
11601        InputMethodManager imm = InputMethodManager.peekInstance();
11602        if (!hasWindowFocus) {
11603            if (isPressed()) {
11604                setPressed(false);
11605            }
11606            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11607            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11608                imm.focusOut(this);
11609            }
11610            removeLongPressCallback();
11611            removeTapCallback();
11612            onFocusLost();
11613        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11614            imm.focusIn(this);
11615        }
11616
11617        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11618
11619        refreshDrawableState();
11620    }
11621
11622    /**
11623     * Returns true if this view is in a window that currently has window focus.
11624     * Note that this is not the same as the view itself having focus.
11625     *
11626     * @return True if this view is in a window that currently has window focus.
11627     */
11628    public boolean hasWindowFocus() {
11629        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11630    }
11631
11632    /**
11633     * Dispatch a view visibility change down the view hierarchy.
11634     * ViewGroups should override to route to their children.
11635     * @param changedView The view whose visibility changed. Could be 'this' or
11636     * an ancestor view.
11637     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11638     * {@link #INVISIBLE} or {@link #GONE}.
11639     */
11640    protected void dispatchVisibilityChanged(@NonNull View changedView,
11641            @Visibility int visibility) {
11642        onVisibilityChanged(changedView, visibility);
11643    }
11644
11645    /**
11646     * Called when the visibility of the view or an ancestor of the view has
11647     * changed.
11648     *
11649     * @param changedView The view whose visibility changed. May be
11650     *                    {@code this} or an ancestor view.
11651     * @param visibility The new visibility, one of {@link #VISIBLE},
11652     *                   {@link #INVISIBLE} or {@link #GONE}.
11653     */
11654    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11655    }
11656
11657    /**
11658     * Dispatch a hint about whether this view is displayed. For instance, when
11659     * a View moves out of the screen, it might receives a display hint indicating
11660     * the view is not displayed. Applications should not <em>rely</em> on this hint
11661     * as there is no guarantee that they will receive one.
11662     *
11663     * @param hint A hint about whether or not this view is displayed:
11664     * {@link #VISIBLE} or {@link #INVISIBLE}.
11665     */
11666    public void dispatchDisplayHint(@Visibility int hint) {
11667        onDisplayHint(hint);
11668    }
11669
11670    /**
11671     * Gives this view a hint about whether is displayed or not. For instance, when
11672     * a View moves out of the screen, it might receives a display hint indicating
11673     * the view is not displayed. Applications should not <em>rely</em> on this hint
11674     * as there is no guarantee that they will receive one.
11675     *
11676     * @param hint A hint about whether or not this view is displayed:
11677     * {@link #VISIBLE} or {@link #INVISIBLE}.
11678     */
11679    protected void onDisplayHint(@Visibility int hint) {
11680    }
11681
11682    /**
11683     * Dispatch a window visibility change down the view hierarchy.
11684     * ViewGroups should override to route to their children.
11685     *
11686     * @param visibility The new visibility of the window.
11687     *
11688     * @see #onWindowVisibilityChanged(int)
11689     */
11690    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11691        onWindowVisibilityChanged(visibility);
11692    }
11693
11694    /**
11695     * Called when the window containing has change its visibility
11696     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11697     * that this tells you whether or not your window is being made visible
11698     * to the window manager; this does <em>not</em> tell you whether or not
11699     * your window is obscured by other windows on the screen, even if it
11700     * is itself visible.
11701     *
11702     * @param visibility The new visibility of the window.
11703     */
11704    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11705        if (visibility == VISIBLE) {
11706            initialAwakenScrollBars();
11707        }
11708    }
11709
11710    /**
11711     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11712     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11713     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11714     *
11715     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11716     *                  ancestors or by window visibility
11717     * @return true if this view is visible to the user, not counting clipping or overlapping
11718     */
11719    boolean dispatchVisibilityAggregated(boolean isVisible) {
11720        final boolean thisVisible = getVisibility() == VISIBLE;
11721        // If we're not visible but something is telling us we are, ignore it.
11722        if (thisVisible || !isVisible) {
11723            onVisibilityAggregated(isVisible);
11724        }
11725        return thisVisible && isVisible;
11726    }
11727
11728    /**
11729     * Called when the user-visibility of this View is potentially affected by a change
11730     * to this view itself, an ancestor view or the window this view is attached to.
11731     *
11732     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11733     *                  and this view's window is also visible
11734     */
11735    @CallSuper
11736    public void onVisibilityAggregated(boolean isVisible) {
11737        if (isVisible && mAttachInfo != null) {
11738            initialAwakenScrollBars();
11739        }
11740
11741        final Drawable dr = mBackground;
11742        if (dr != null && isVisible != dr.isVisible()) {
11743            dr.setVisible(isVisible, false);
11744        }
11745        final Drawable hl = mDefaultFocusHighlight;
11746        if (hl != null && isVisible != hl.isVisible()) {
11747            hl.setVisible(isVisible, false);
11748        }
11749        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11750        if (fg != null && isVisible != fg.isVisible()) {
11751            fg.setVisible(isVisible, false);
11752        }
11753
11754        if (isAutofillable()) {
11755            AutofillManager afm = getAutofillManager();
11756
11757            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
11758                if (mVisibilityChangeForAutofillHandler != null) {
11759                    mVisibilityChangeForAutofillHandler.removeMessages(0);
11760                }
11761
11762                // If the view is in the background but still part of the hierarchy this is called
11763                // with isVisible=false. Hence visibility==false requires further checks
11764                if (isVisible) {
11765                    afm.notifyViewVisibilityChange(this, true);
11766                } else {
11767                    if (mVisibilityChangeForAutofillHandler == null) {
11768                        mVisibilityChangeForAutofillHandler =
11769                                new VisibilityChangeForAutofillHandler(afm, this);
11770                    }
11771                    // Let current operation (e.g. removal of the view from the hierarchy)
11772                    // finish before checking state
11773                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
11774                }
11775            }
11776        }
11777    }
11778
11779    /**
11780     * Returns the current visibility of the window this view is attached to
11781     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11782     *
11783     * @return Returns the current visibility of the view's window.
11784     */
11785    @Visibility
11786    public int getWindowVisibility() {
11787        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11788    }
11789
11790    /**
11791     * Retrieve the overall visible display size in which the window this view is
11792     * attached to has been positioned in.  This takes into account screen
11793     * decorations above the window, for both cases where the window itself
11794     * is being position inside of them or the window is being placed under
11795     * then and covered insets are used for the window to position its content
11796     * inside.  In effect, this tells you the available area where content can
11797     * be placed and remain visible to users.
11798     *
11799     * <p>This function requires an IPC back to the window manager to retrieve
11800     * the requested information, so should not be used in performance critical
11801     * code like drawing.
11802     *
11803     * @param outRect Filled in with the visible display frame.  If the view
11804     * is not attached to a window, this is simply the raw display size.
11805     */
11806    public void getWindowVisibleDisplayFrame(Rect outRect) {
11807        if (mAttachInfo != null) {
11808            try {
11809                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11810            } catch (RemoteException e) {
11811                return;
11812            }
11813            // XXX This is really broken, and probably all needs to be done
11814            // in the window manager, and we need to know more about whether
11815            // we want the area behind or in front of the IME.
11816            final Rect insets = mAttachInfo.mVisibleInsets;
11817            outRect.left += insets.left;
11818            outRect.top += insets.top;
11819            outRect.right -= insets.right;
11820            outRect.bottom -= insets.bottom;
11821            return;
11822        }
11823        // The view is not attached to a display so we don't have a context.
11824        // Make a best guess about the display size.
11825        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11826        d.getRectSize(outRect);
11827    }
11828
11829    /**
11830     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11831     * is currently in without any insets.
11832     *
11833     * @hide
11834     */
11835    public void getWindowDisplayFrame(Rect outRect) {
11836        if (mAttachInfo != null) {
11837            try {
11838                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11839            } catch (RemoteException e) {
11840                return;
11841            }
11842            return;
11843        }
11844        // The view is not attached to a display so we don't have a context.
11845        // Make a best guess about the display size.
11846        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11847        d.getRectSize(outRect);
11848    }
11849
11850    /**
11851     * Dispatch a notification about a resource configuration change down
11852     * the view hierarchy.
11853     * ViewGroups should override to route to their children.
11854     *
11855     * @param newConfig The new resource configuration.
11856     *
11857     * @see #onConfigurationChanged(android.content.res.Configuration)
11858     */
11859    public void dispatchConfigurationChanged(Configuration newConfig) {
11860        onConfigurationChanged(newConfig);
11861    }
11862
11863    /**
11864     * Called when the current configuration of the resources being used
11865     * by the application have changed.  You can use this to decide when
11866     * to reload resources that can changed based on orientation and other
11867     * configuration characteristics.  You only need to use this if you are
11868     * not relying on the normal {@link android.app.Activity} mechanism of
11869     * recreating the activity instance upon a configuration change.
11870     *
11871     * @param newConfig The new resource configuration.
11872     */
11873    protected void onConfigurationChanged(Configuration newConfig) {
11874    }
11875
11876    /**
11877     * Private function to aggregate all per-view attributes in to the view
11878     * root.
11879     */
11880    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11881        performCollectViewAttributes(attachInfo, visibility);
11882    }
11883
11884    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11885        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11886            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11887                attachInfo.mKeepScreenOn = true;
11888            }
11889            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11890            ListenerInfo li = mListenerInfo;
11891            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11892                attachInfo.mHasSystemUiListeners = true;
11893            }
11894        }
11895    }
11896
11897    void needGlobalAttributesUpdate(boolean force) {
11898        final AttachInfo ai = mAttachInfo;
11899        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11900            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11901                    || ai.mHasSystemUiListeners) {
11902                ai.mRecomputeGlobalAttributes = true;
11903            }
11904        }
11905    }
11906
11907    /**
11908     * Returns whether the device is currently in touch mode.  Touch mode is entered
11909     * once the user begins interacting with the device by touch, and affects various
11910     * things like whether focus is always visible to the user.
11911     *
11912     * @return Whether the device is in touch mode.
11913     */
11914    @ViewDebug.ExportedProperty
11915    public boolean isInTouchMode() {
11916        if (mAttachInfo != null) {
11917            return mAttachInfo.mInTouchMode;
11918        } else {
11919            return ViewRootImpl.isInTouchMode();
11920        }
11921    }
11922
11923    /**
11924     * Returns the context the view is running in, through which it can
11925     * access the current theme, resources, etc.
11926     *
11927     * @return The view's Context.
11928     */
11929    @ViewDebug.CapturedViewProperty
11930    public final Context getContext() {
11931        return mContext;
11932    }
11933
11934    /**
11935     * Handle a key event before it is processed by any input method
11936     * associated with the view hierarchy.  This can be used to intercept
11937     * key events in special situations before the IME consumes them; a
11938     * typical example would be handling the BACK key to update the application's
11939     * UI instead of allowing the IME to see it and close itself.
11940     *
11941     * @param keyCode The value in event.getKeyCode().
11942     * @param event Description of the key event.
11943     * @return If you handled the event, return true. If you want to allow the
11944     *         event to be handled by the next receiver, return false.
11945     */
11946    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11947        return false;
11948    }
11949
11950    /**
11951     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11952     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11953     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11954     * is released, if the view is enabled and clickable.
11955     * <p>
11956     * Key presses in software keyboards will generally NOT trigger this
11957     * listener, although some may elect to do so in some situations. Do not
11958     * rely on this to catch software key presses.
11959     *
11960     * @param keyCode a key code that represents the button pressed, from
11961     *                {@link android.view.KeyEvent}
11962     * @param event the KeyEvent object that defines the button action
11963     */
11964    public boolean onKeyDown(int keyCode, KeyEvent event) {
11965        if (KeyEvent.isConfirmKey(keyCode)) {
11966            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11967                return true;
11968            }
11969
11970            if (event.getRepeatCount() == 0) {
11971                // Long clickable items don't necessarily have to be clickable.
11972                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11973                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11974                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11975                    // For the purposes of menu anchoring and drawable hotspots,
11976                    // key events are considered to be at the center of the view.
11977                    final float x = getWidth() / 2f;
11978                    final float y = getHeight() / 2f;
11979                    if (clickable) {
11980                        setPressed(true, x, y);
11981                    }
11982                    checkForLongClick(0, x, y);
11983                    return true;
11984                }
11985            }
11986        }
11987
11988        return false;
11989    }
11990
11991    /**
11992     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11993     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11994     * the event).
11995     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11996     * although some may elect to do so in some situations. Do not rely on this to
11997     * catch software key presses.
11998     */
11999    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12000        return false;
12001    }
12002
12003    /**
12004     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12005     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12006     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12007     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12008     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12009     * although some may elect to do so in some situations. Do not rely on this to
12010     * catch software key presses.
12011     *
12012     * @param keyCode A key code that represents the button pressed, from
12013     *                {@link android.view.KeyEvent}.
12014     * @param event   The KeyEvent object that defines the button action.
12015     */
12016    public boolean onKeyUp(int keyCode, KeyEvent event) {
12017        if (KeyEvent.isConfirmKey(keyCode)) {
12018            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12019                return true;
12020            }
12021            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12022                setPressed(false);
12023
12024                if (!mHasPerformedLongPress) {
12025                    // This is a tap, so remove the longpress check
12026                    removeLongPressCallback();
12027                    if (!event.isCanceled()) {
12028                        return performClick();
12029                    }
12030                }
12031            }
12032        }
12033        return false;
12034    }
12035
12036    /**
12037     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12038     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12039     * the event).
12040     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12041     * although some may elect to do so in some situations. Do not rely on this to
12042     * catch software key presses.
12043     *
12044     * @param keyCode     A key code that represents the button pressed, from
12045     *                    {@link android.view.KeyEvent}.
12046     * @param repeatCount The number of times the action was made.
12047     * @param event       The KeyEvent object that defines the button action.
12048     */
12049    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12050        return false;
12051    }
12052
12053    /**
12054     * Called on the focused view when a key shortcut event is not handled.
12055     * Override this method to implement local key shortcuts for the View.
12056     * Key shortcuts can also be implemented by setting the
12057     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12058     *
12059     * @param keyCode The value in event.getKeyCode().
12060     * @param event Description of the key event.
12061     * @return If you handled the event, return true. If you want to allow the
12062     *         event to be handled by the next receiver, return false.
12063     */
12064    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12065        return false;
12066    }
12067
12068    /**
12069     * Check whether the called view is a text editor, in which case it
12070     * would make sense to automatically display a soft input window for
12071     * it.  Subclasses should override this if they implement
12072     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12073     * a call on that method would return a non-null InputConnection, and
12074     * they are really a first-class editor that the user would normally
12075     * start typing on when the go into a window containing your view.
12076     *
12077     * <p>The default implementation always returns false.  This does
12078     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12079     * will not be called or the user can not otherwise perform edits on your
12080     * view; it is just a hint to the system that this is not the primary
12081     * purpose of this view.
12082     *
12083     * @return Returns true if this view is a text editor, else false.
12084     */
12085    public boolean onCheckIsTextEditor() {
12086        return false;
12087    }
12088
12089    /**
12090     * Create a new InputConnection for an InputMethod to interact
12091     * with the view.  The default implementation returns null, since it doesn't
12092     * support input methods.  You can override this to implement such support.
12093     * This is only needed for views that take focus and text input.
12094     *
12095     * <p>When implementing this, you probably also want to implement
12096     * {@link #onCheckIsTextEditor()} to indicate you will return a
12097     * non-null InputConnection.</p>
12098     *
12099     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12100     * object correctly and in its entirety, so that the connected IME can rely
12101     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12102     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12103     * must be filled in with the correct cursor position for IMEs to work correctly
12104     * with your application.</p>
12105     *
12106     * @param outAttrs Fill in with attribute information about the connection.
12107     */
12108    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12109        return null;
12110    }
12111
12112    /**
12113     * Called by the {@link android.view.inputmethod.InputMethodManager}
12114     * when a view who is not the current
12115     * input connection target is trying to make a call on the manager.  The
12116     * default implementation returns false; you can override this to return
12117     * true for certain views if you are performing InputConnection proxying
12118     * to them.
12119     * @param view The View that is making the InputMethodManager call.
12120     * @return Return true to allow the call, false to reject.
12121     */
12122    public boolean checkInputConnectionProxy(View view) {
12123        return false;
12124    }
12125
12126    /**
12127     * Show the context menu for this view. It is not safe to hold on to the
12128     * menu after returning from this method.
12129     *
12130     * You should normally not overload this method. Overload
12131     * {@link #onCreateContextMenu(ContextMenu)} or define an
12132     * {@link OnCreateContextMenuListener} to add items to the context menu.
12133     *
12134     * @param menu The context menu to populate
12135     */
12136    public void createContextMenu(ContextMenu menu) {
12137        ContextMenuInfo menuInfo = getContextMenuInfo();
12138
12139        // Sets the current menu info so all items added to menu will have
12140        // my extra info set.
12141        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12142
12143        onCreateContextMenu(menu);
12144        ListenerInfo li = mListenerInfo;
12145        if (li != null && li.mOnCreateContextMenuListener != null) {
12146            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12147        }
12148
12149        // Clear the extra information so subsequent items that aren't mine don't
12150        // have my extra info.
12151        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12152
12153        if (mParent != null) {
12154            mParent.createContextMenu(menu);
12155        }
12156    }
12157
12158    /**
12159     * Views should implement this if they have extra information to associate
12160     * with the context menu. The return result is supplied as a parameter to
12161     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12162     * callback.
12163     *
12164     * @return Extra information about the item for which the context menu
12165     *         should be shown. This information will vary across different
12166     *         subclasses of View.
12167     */
12168    protected ContextMenuInfo getContextMenuInfo() {
12169        return null;
12170    }
12171
12172    /**
12173     * Views should implement this if the view itself is going to add items to
12174     * the context menu.
12175     *
12176     * @param menu the context menu to populate
12177     */
12178    protected void onCreateContextMenu(ContextMenu menu) {
12179    }
12180
12181    /**
12182     * Implement this method to handle trackball motion events.  The
12183     * <em>relative</em> movement of the trackball since the last event
12184     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12185     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12186     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12187     * they will often be fractional values, representing the more fine-grained
12188     * movement information available from a trackball).
12189     *
12190     * @param event The motion event.
12191     * @return True if the event was handled, false otherwise.
12192     */
12193    public boolean onTrackballEvent(MotionEvent event) {
12194        return false;
12195    }
12196
12197    /**
12198     * Implement this method to handle generic motion events.
12199     * <p>
12200     * Generic motion events describe joystick movements, mouse hovers, track pad
12201     * touches, scroll wheel movements and other input events.  The
12202     * {@link MotionEvent#getSource() source} of the motion event specifies
12203     * the class of input that was received.  Implementations of this method
12204     * must examine the bits in the source before processing the event.
12205     * The following code example shows how this is done.
12206     * </p><p>
12207     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12208     * are delivered to the view under the pointer.  All other generic motion events are
12209     * delivered to the focused view.
12210     * </p>
12211     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12212     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12213     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12214     *             // process the joystick movement...
12215     *             return true;
12216     *         }
12217     *     }
12218     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12219     *         switch (event.getAction()) {
12220     *             case MotionEvent.ACTION_HOVER_MOVE:
12221     *                 // process the mouse hover movement...
12222     *                 return true;
12223     *             case MotionEvent.ACTION_SCROLL:
12224     *                 // process the scroll wheel movement...
12225     *                 return true;
12226     *         }
12227     *     }
12228     *     return super.onGenericMotionEvent(event);
12229     * }</pre>
12230     *
12231     * @param event The generic motion event being processed.
12232     * @return True if the event was handled, false otherwise.
12233     */
12234    public boolean onGenericMotionEvent(MotionEvent event) {
12235        return false;
12236    }
12237
12238    /**
12239     * Implement this method to handle hover events.
12240     * <p>
12241     * This method is called whenever a pointer is hovering into, over, or out of the
12242     * bounds of a view and the view is not currently being touched.
12243     * Hover events are represented as pointer events with action
12244     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12245     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12246     * </p>
12247     * <ul>
12248     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12249     * when the pointer enters the bounds of the view.</li>
12250     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12251     * when the pointer has already entered the bounds of the view and has moved.</li>
12252     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12253     * when the pointer has exited the bounds of the view or when the pointer is
12254     * about to go down due to a button click, tap, or similar user action that
12255     * causes the view to be touched.</li>
12256     * </ul>
12257     * <p>
12258     * The view should implement this method to return true to indicate that it is
12259     * handling the hover event, such as by changing its drawable state.
12260     * </p><p>
12261     * The default implementation calls {@link #setHovered} to update the hovered state
12262     * of the view when a hover enter or hover exit event is received, if the view
12263     * is enabled and is clickable.  The default implementation also sends hover
12264     * accessibility events.
12265     * </p>
12266     *
12267     * @param event The motion event that describes the hover.
12268     * @return True if the view handled the hover event.
12269     *
12270     * @see #isHovered
12271     * @see #setHovered
12272     * @see #onHoverChanged
12273     */
12274    public boolean onHoverEvent(MotionEvent event) {
12275        // The root view may receive hover (or touch) events that are outside the bounds of
12276        // the window.  This code ensures that we only send accessibility events for
12277        // hovers that are actually within the bounds of the root view.
12278        final int action = event.getActionMasked();
12279        if (!mSendingHoverAccessibilityEvents) {
12280            if ((action == MotionEvent.ACTION_HOVER_ENTER
12281                    || action == MotionEvent.ACTION_HOVER_MOVE)
12282                    && !hasHoveredChild()
12283                    && pointInView(event.getX(), event.getY())) {
12284                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12285                mSendingHoverAccessibilityEvents = true;
12286            }
12287        } else {
12288            if (action == MotionEvent.ACTION_HOVER_EXIT
12289                    || (action == MotionEvent.ACTION_MOVE
12290                            && !pointInView(event.getX(), event.getY()))) {
12291                mSendingHoverAccessibilityEvents = false;
12292                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12293            }
12294        }
12295
12296        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12297                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12298                && isOnScrollbar(event.getX(), event.getY())) {
12299            awakenScrollBars();
12300        }
12301
12302        // If we consider ourself hoverable, or if we we're already hovered,
12303        // handle changing state in response to ENTER and EXIT events.
12304        if (isHoverable() || isHovered()) {
12305            switch (action) {
12306                case MotionEvent.ACTION_HOVER_ENTER:
12307                    setHovered(true);
12308                    break;
12309                case MotionEvent.ACTION_HOVER_EXIT:
12310                    setHovered(false);
12311                    break;
12312            }
12313
12314            // Dispatch the event to onGenericMotionEvent before returning true.
12315            // This is to provide compatibility with existing applications that
12316            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12317            // break because of the new default handling for hoverable views
12318            // in onHoverEvent.
12319            // Note that onGenericMotionEvent will be called by default when
12320            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12321            dispatchGenericMotionEventInternal(event);
12322            // The event was already handled by calling setHovered(), so always
12323            // return true.
12324            return true;
12325        }
12326
12327        return false;
12328    }
12329
12330    /**
12331     * Returns true if the view should handle {@link #onHoverEvent}
12332     * by calling {@link #setHovered} to change its hovered state.
12333     *
12334     * @return True if the view is hoverable.
12335     */
12336    private boolean isHoverable() {
12337        final int viewFlags = mViewFlags;
12338        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12339            return false;
12340        }
12341
12342        return (viewFlags & CLICKABLE) == CLICKABLE
12343                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12344                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12345    }
12346
12347    /**
12348     * Returns true if the view is currently hovered.
12349     *
12350     * @return True if the view is currently hovered.
12351     *
12352     * @see #setHovered
12353     * @see #onHoverChanged
12354     */
12355    @ViewDebug.ExportedProperty
12356    public boolean isHovered() {
12357        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12358    }
12359
12360    /**
12361     * Sets whether the view is currently hovered.
12362     * <p>
12363     * Calling this method also changes the drawable state of the view.  This
12364     * enables the view to react to hover by using different drawable resources
12365     * to change its appearance.
12366     * </p><p>
12367     * The {@link #onHoverChanged} method is called when the hovered state changes.
12368     * </p>
12369     *
12370     * @param hovered True if the view is hovered.
12371     *
12372     * @see #isHovered
12373     * @see #onHoverChanged
12374     */
12375    public void setHovered(boolean hovered) {
12376        if (hovered) {
12377            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12378                mPrivateFlags |= PFLAG_HOVERED;
12379                refreshDrawableState();
12380                onHoverChanged(true);
12381            }
12382        } else {
12383            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12384                mPrivateFlags &= ~PFLAG_HOVERED;
12385                refreshDrawableState();
12386                onHoverChanged(false);
12387            }
12388        }
12389    }
12390
12391    /**
12392     * Implement this method to handle hover state changes.
12393     * <p>
12394     * This method is called whenever the hover state changes as a result of a
12395     * call to {@link #setHovered}.
12396     * </p>
12397     *
12398     * @param hovered The current hover state, as returned by {@link #isHovered}.
12399     *
12400     * @see #isHovered
12401     * @see #setHovered
12402     */
12403    public void onHoverChanged(boolean hovered) {
12404    }
12405
12406    /**
12407     * Handles scroll bar dragging by mouse input.
12408     *
12409     * @hide
12410     * @param event The motion event.
12411     *
12412     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12413     */
12414    protected boolean handleScrollBarDragging(MotionEvent event) {
12415        if (mScrollCache == null) {
12416            return false;
12417        }
12418        final float x = event.getX();
12419        final float y = event.getY();
12420        final int action = event.getAction();
12421        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12422                && action != MotionEvent.ACTION_DOWN)
12423                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12424                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12425            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12426            return false;
12427        }
12428
12429        switch (action) {
12430            case MotionEvent.ACTION_MOVE:
12431                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12432                    return false;
12433                }
12434                if (mScrollCache.mScrollBarDraggingState
12435                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12436                    final Rect bounds = mScrollCache.mScrollBarBounds;
12437                    getVerticalScrollBarBounds(bounds, null);
12438                    final int range = computeVerticalScrollRange();
12439                    final int offset = computeVerticalScrollOffset();
12440                    final int extent = computeVerticalScrollExtent();
12441
12442                    final int thumbLength = ScrollBarUtils.getThumbLength(
12443                            bounds.height(), bounds.width(), extent, range);
12444                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12445                            bounds.height(), thumbLength, extent, range, offset);
12446
12447                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12448                    final float maxThumbOffset = bounds.height() - thumbLength;
12449                    final float newThumbOffset =
12450                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12451                    final int height = getHeight();
12452                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12453                            && height > 0 && extent > 0) {
12454                        final int newY = Math.round((range - extent)
12455                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12456                        if (newY != getScrollY()) {
12457                            mScrollCache.mScrollBarDraggingPos = y;
12458                            setScrollY(newY);
12459                        }
12460                    }
12461                    return true;
12462                }
12463                if (mScrollCache.mScrollBarDraggingState
12464                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12465                    final Rect bounds = mScrollCache.mScrollBarBounds;
12466                    getHorizontalScrollBarBounds(bounds, null);
12467                    final int range = computeHorizontalScrollRange();
12468                    final int offset = computeHorizontalScrollOffset();
12469                    final int extent = computeHorizontalScrollExtent();
12470
12471                    final int thumbLength = ScrollBarUtils.getThumbLength(
12472                            bounds.width(), bounds.height(), extent, range);
12473                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12474                            bounds.width(), thumbLength, extent, range, offset);
12475
12476                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12477                    final float maxThumbOffset = bounds.width() - thumbLength;
12478                    final float newThumbOffset =
12479                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12480                    final int width = getWidth();
12481                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12482                            && width > 0 && extent > 0) {
12483                        final int newX = Math.round((range - extent)
12484                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12485                        if (newX != getScrollX()) {
12486                            mScrollCache.mScrollBarDraggingPos = x;
12487                            setScrollX(newX);
12488                        }
12489                    }
12490                    return true;
12491                }
12492            case MotionEvent.ACTION_DOWN:
12493                if (mScrollCache.state == ScrollabilityCache.OFF) {
12494                    return false;
12495                }
12496                if (isOnVerticalScrollbarThumb(x, y)) {
12497                    mScrollCache.mScrollBarDraggingState =
12498                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12499                    mScrollCache.mScrollBarDraggingPos = y;
12500                    return true;
12501                }
12502                if (isOnHorizontalScrollbarThumb(x, y)) {
12503                    mScrollCache.mScrollBarDraggingState =
12504                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12505                    mScrollCache.mScrollBarDraggingPos = x;
12506                    return true;
12507                }
12508        }
12509        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12510        return false;
12511    }
12512
12513    /**
12514     * Implement this method to handle touch screen motion events.
12515     * <p>
12516     * If this method is used to detect click actions, it is recommended that
12517     * the actions be performed by implementing and calling
12518     * {@link #performClick()}. This will ensure consistent system behavior,
12519     * including:
12520     * <ul>
12521     * <li>obeying click sound preferences
12522     * <li>dispatching OnClickListener calls
12523     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12524     * accessibility features are enabled
12525     * </ul>
12526     *
12527     * @param event The motion event.
12528     * @return True if the event was handled, false otherwise.
12529     */
12530    public boolean onTouchEvent(MotionEvent event) {
12531        final float x = event.getX();
12532        final float y = event.getY();
12533        final int viewFlags = mViewFlags;
12534        final int action = event.getAction();
12535
12536        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12537                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12538                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12539
12540        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12541            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12542                setPressed(false);
12543            }
12544            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12545            // A disabled view that is clickable still consumes the touch
12546            // events, it just doesn't respond to them.
12547            return clickable;
12548        }
12549        if (mTouchDelegate != null) {
12550            if (mTouchDelegate.onTouchEvent(event)) {
12551                return true;
12552            }
12553        }
12554
12555        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12556            switch (action) {
12557                case MotionEvent.ACTION_UP:
12558                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12559                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12560                        handleTooltipUp();
12561                    }
12562                    if (!clickable) {
12563                        removeTapCallback();
12564                        removeLongPressCallback();
12565                        mInContextButtonPress = false;
12566                        mHasPerformedLongPress = false;
12567                        mIgnoreNextUpEvent = false;
12568                        break;
12569                    }
12570                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12571                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12572                        // take focus if we don't have it already and we should in
12573                        // touch mode.
12574                        boolean focusTaken = false;
12575                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12576                            focusTaken = requestFocus();
12577                        }
12578
12579                        if (prepressed) {
12580                            // The button is being released before we actually
12581                            // showed it as pressed.  Make it show the pressed
12582                            // state now (before scheduling the click) to ensure
12583                            // the user sees it.
12584                            setPressed(true, x, y);
12585                        }
12586
12587                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12588                            // This is a tap, so remove the longpress check
12589                            removeLongPressCallback();
12590
12591                            // Only perform take click actions if we were in the pressed state
12592                            if (!focusTaken) {
12593                                // Use a Runnable and post this rather than calling
12594                                // performClick directly. This lets other visual state
12595                                // of the view update before click actions start.
12596                                if (mPerformClick == null) {
12597                                    mPerformClick = new PerformClick();
12598                                }
12599                                if (!post(mPerformClick)) {
12600                                    performClick();
12601                                }
12602                            }
12603                        }
12604
12605                        if (mUnsetPressedState == null) {
12606                            mUnsetPressedState = new UnsetPressedState();
12607                        }
12608
12609                        if (prepressed) {
12610                            postDelayed(mUnsetPressedState,
12611                                    ViewConfiguration.getPressedStateDuration());
12612                        } else if (!post(mUnsetPressedState)) {
12613                            // If the post failed, unpress right now
12614                            mUnsetPressedState.run();
12615                        }
12616
12617                        removeTapCallback();
12618                    }
12619                    mIgnoreNextUpEvent = false;
12620                    break;
12621
12622                case MotionEvent.ACTION_DOWN:
12623                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12624                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12625                    }
12626                    mHasPerformedLongPress = false;
12627
12628                    if (!clickable) {
12629                        checkForLongClick(0, x, y);
12630                        break;
12631                    }
12632
12633                    if (performButtonActionOnTouchDown(event)) {
12634                        break;
12635                    }
12636
12637                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12638                    boolean isInScrollingContainer = isInScrollingContainer();
12639
12640                    // For views inside a scrolling container, delay the pressed feedback for
12641                    // a short period in case this is a scroll.
12642                    if (isInScrollingContainer) {
12643                        mPrivateFlags |= PFLAG_PREPRESSED;
12644                        if (mPendingCheckForTap == null) {
12645                            mPendingCheckForTap = new CheckForTap();
12646                        }
12647                        mPendingCheckForTap.x = event.getX();
12648                        mPendingCheckForTap.y = event.getY();
12649                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12650                    } else {
12651                        // Not inside a scrolling container, so show the feedback right away
12652                        setPressed(true, x, y);
12653                        checkForLongClick(0, x, y);
12654                    }
12655                    break;
12656
12657                case MotionEvent.ACTION_CANCEL:
12658                    if (clickable) {
12659                        setPressed(false);
12660                    }
12661                    removeTapCallback();
12662                    removeLongPressCallback();
12663                    mInContextButtonPress = false;
12664                    mHasPerformedLongPress = false;
12665                    mIgnoreNextUpEvent = false;
12666                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12667                    break;
12668
12669                case MotionEvent.ACTION_MOVE:
12670                    if (clickable) {
12671                        drawableHotspotChanged(x, y);
12672                    }
12673
12674                    // Be lenient about moving outside of buttons
12675                    if (!pointInView(x, y, mTouchSlop)) {
12676                        // Outside button
12677                        // Remove any future long press/tap checks
12678                        removeTapCallback();
12679                        removeLongPressCallback();
12680                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12681                            setPressed(false);
12682                        }
12683                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12684                    }
12685                    break;
12686            }
12687
12688            return true;
12689        }
12690
12691        return false;
12692    }
12693
12694    /**
12695     * @hide
12696     */
12697    public boolean isInScrollingContainer() {
12698        ViewParent p = getParent();
12699        while (p != null && p instanceof ViewGroup) {
12700            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12701                return true;
12702            }
12703            p = p.getParent();
12704        }
12705        return false;
12706    }
12707
12708    /**
12709     * Remove the longpress detection timer.
12710     */
12711    private void removeLongPressCallback() {
12712        if (mPendingCheckForLongPress != null) {
12713            removeCallbacks(mPendingCheckForLongPress);
12714        }
12715    }
12716
12717    /**
12718     * Remove the pending click action
12719     */
12720    private void removePerformClickCallback() {
12721        if (mPerformClick != null) {
12722            removeCallbacks(mPerformClick);
12723        }
12724    }
12725
12726    /**
12727     * Remove the prepress detection timer.
12728     */
12729    private void removeUnsetPressCallback() {
12730        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12731            setPressed(false);
12732            removeCallbacks(mUnsetPressedState);
12733        }
12734    }
12735
12736    /**
12737     * Remove the tap detection timer.
12738     */
12739    private void removeTapCallback() {
12740        if (mPendingCheckForTap != null) {
12741            mPrivateFlags &= ~PFLAG_PREPRESSED;
12742            removeCallbacks(mPendingCheckForTap);
12743        }
12744    }
12745
12746    /**
12747     * Cancels a pending long press.  Your subclass can use this if you
12748     * want the context menu to come up if the user presses and holds
12749     * at the same place, but you don't want it to come up if they press
12750     * and then move around enough to cause scrolling.
12751     */
12752    public void cancelLongPress() {
12753        removeLongPressCallback();
12754
12755        /*
12756         * The prepressed state handled by the tap callback is a display
12757         * construct, but the tap callback will post a long press callback
12758         * less its own timeout. Remove it here.
12759         */
12760        removeTapCallback();
12761    }
12762
12763    /**
12764     * Remove the pending callback for sending a
12765     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12766     */
12767    private void removeSendViewScrolledAccessibilityEventCallback() {
12768        if (mSendViewScrolledAccessibilityEvent != null) {
12769            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12770            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12771        }
12772    }
12773
12774    /**
12775     * Sets the TouchDelegate for this View.
12776     */
12777    public void setTouchDelegate(TouchDelegate delegate) {
12778        mTouchDelegate = delegate;
12779    }
12780
12781    /**
12782     * Gets the TouchDelegate for this View.
12783     */
12784    public TouchDelegate getTouchDelegate() {
12785        return mTouchDelegate;
12786    }
12787
12788    /**
12789     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12790     *
12791     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12792     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12793     * available. This method should only be called for touch events.
12794     *
12795     * <p class="note">This api is not intended for most applications. Buffered dispatch
12796     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12797     * streams will not improve your input latency. Side effects include: increased latency,
12798     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12799     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12800     * you.</p>
12801     */
12802    public final void requestUnbufferedDispatch(MotionEvent event) {
12803        final int action = event.getAction();
12804        if (mAttachInfo == null
12805                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12806                || !event.isTouchEvent()) {
12807            return;
12808        }
12809        mAttachInfo.mUnbufferedDispatchRequested = true;
12810    }
12811
12812    /**
12813     * Set flags controlling behavior of this view.
12814     *
12815     * @param flags Constant indicating the value which should be set
12816     * @param mask Constant indicating the bit range that should be changed
12817     */
12818    void setFlags(int flags, int mask) {
12819        final boolean accessibilityEnabled =
12820                AccessibilityManager.getInstance(mContext).isEnabled();
12821        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12822
12823        int old = mViewFlags;
12824        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12825
12826        int changed = mViewFlags ^ old;
12827        if (changed == 0) {
12828            return;
12829        }
12830        int privateFlags = mPrivateFlags;
12831
12832        // If focusable is auto, update the FOCUSABLE bit.
12833        int focusableChangedByAuto = 0;
12834        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12835                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12836            // Heuristic only takes into account whether view is clickable.
12837            final int newFocus;
12838            if ((mViewFlags & CLICKABLE) != 0) {
12839                newFocus = FOCUSABLE;
12840            } else {
12841                newFocus = NOT_FOCUSABLE;
12842            }
12843            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12844            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12845            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12846        }
12847
12848        /* Check if the FOCUSABLE bit has changed */
12849        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12850            if (((old & FOCUSABLE) == FOCUSABLE)
12851                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12852                /* Give up focus if we are no longer focusable */
12853                clearFocus();
12854            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12855                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12856                /*
12857                 * Tell the view system that we are now available to take focus
12858                 * if no one else already has it.
12859                 */
12860                if (mParent != null) {
12861                    ViewRootImpl viewRootImpl = getViewRootImpl();
12862                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12863                            || focusableChangedByAuto == 0
12864                            || viewRootImpl == null
12865                            || viewRootImpl.mThread == Thread.currentThread()) {
12866                        mParent.focusableViewAvailable(this);
12867                    }
12868                }
12869            }
12870        }
12871
12872        final int newVisibility = flags & VISIBILITY_MASK;
12873        if (newVisibility == VISIBLE) {
12874            if ((changed & VISIBILITY_MASK) != 0) {
12875                /*
12876                 * If this view is becoming visible, invalidate it in case it changed while
12877                 * it was not visible. Marking it drawn ensures that the invalidation will
12878                 * go through.
12879                 */
12880                mPrivateFlags |= PFLAG_DRAWN;
12881                invalidate(true);
12882
12883                needGlobalAttributesUpdate(true);
12884
12885                // a view becoming visible is worth notifying the parent
12886                // about in case nothing has focus.  even if this specific view
12887                // isn't focusable, it may contain something that is, so let
12888                // the root view try to give this focus if nothing else does.
12889                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12890                    mParent.focusableViewAvailable(this);
12891                }
12892            }
12893        }
12894
12895        /* Check if the GONE bit has changed */
12896        if ((changed & GONE) != 0) {
12897            needGlobalAttributesUpdate(false);
12898            requestLayout();
12899
12900            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12901                if (hasFocus()) clearFocus();
12902                clearAccessibilityFocus();
12903                destroyDrawingCache();
12904                if (mParent instanceof View) {
12905                    // GONE views noop invalidation, so invalidate the parent
12906                    ((View) mParent).invalidate(true);
12907                }
12908                // Mark the view drawn to ensure that it gets invalidated properly the next
12909                // time it is visible and gets invalidated
12910                mPrivateFlags |= PFLAG_DRAWN;
12911            }
12912            if (mAttachInfo != null) {
12913                mAttachInfo.mViewVisibilityChanged = true;
12914            }
12915        }
12916
12917        /* Check if the VISIBLE bit has changed */
12918        if ((changed & INVISIBLE) != 0) {
12919            needGlobalAttributesUpdate(false);
12920            /*
12921             * If this view is becoming invisible, set the DRAWN flag so that
12922             * the next invalidate() will not be skipped.
12923             */
12924            mPrivateFlags |= PFLAG_DRAWN;
12925
12926            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12927                // root view becoming invisible shouldn't clear focus and accessibility focus
12928                if (getRootView() != this) {
12929                    if (hasFocus()) clearFocus();
12930                    clearAccessibilityFocus();
12931                }
12932            }
12933            if (mAttachInfo != null) {
12934                mAttachInfo.mViewVisibilityChanged = true;
12935            }
12936        }
12937
12938        if ((changed & VISIBILITY_MASK) != 0) {
12939            // If the view is invisible, cleanup its display list to free up resources
12940            if (newVisibility != VISIBLE && mAttachInfo != null) {
12941                cleanupDraw();
12942            }
12943
12944            if (mParent instanceof ViewGroup) {
12945                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12946                        (changed & VISIBILITY_MASK), newVisibility);
12947                ((View) mParent).invalidate(true);
12948            } else if (mParent != null) {
12949                mParent.invalidateChild(this, null);
12950            }
12951
12952            if (mAttachInfo != null) {
12953                dispatchVisibilityChanged(this, newVisibility);
12954
12955                // Aggregated visibility changes are dispatched to attached views
12956                // in visible windows where the parent is currently shown/drawn
12957                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12958                // discounting clipping or overlapping. This makes it a good place
12959                // to change animation states.
12960                if (mParent != null && getWindowVisibility() == VISIBLE &&
12961                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12962                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12963                }
12964                notifySubtreeAccessibilityStateChangedIfNeeded();
12965            }
12966        }
12967
12968        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12969            destroyDrawingCache();
12970        }
12971
12972        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12973            destroyDrawingCache();
12974            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12975            invalidateParentCaches();
12976        }
12977
12978        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12979            destroyDrawingCache();
12980            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12981        }
12982
12983        if ((changed & DRAW_MASK) != 0) {
12984            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12985                if (mBackground != null
12986                        || mDefaultFocusHighlight != null
12987                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12988                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12989                } else {
12990                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12991                }
12992            } else {
12993                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12994            }
12995            requestLayout();
12996            invalidate(true);
12997        }
12998
12999        if ((changed & KEEP_SCREEN_ON) != 0) {
13000            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13001                mParent.recomputeViewAttributes(this);
13002            }
13003        }
13004
13005        if (accessibilityEnabled) {
13006            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13007                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13008                    || (changed & CONTEXT_CLICKABLE) != 0) {
13009                if (oldIncludeForAccessibility != includeForAccessibility()) {
13010                    notifySubtreeAccessibilityStateChangedIfNeeded();
13011                } else {
13012                    notifyViewAccessibilityStateChangedIfNeeded(
13013                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13014                }
13015            } else if ((changed & ENABLED_MASK) != 0) {
13016                notifyViewAccessibilityStateChangedIfNeeded(
13017                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13018            }
13019        }
13020    }
13021
13022    /**
13023     * Change the view's z order in the tree, so it's on top of other sibling
13024     * views. This ordering change may affect layout, if the parent container
13025     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13026     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13027     * method should be followed by calls to {@link #requestLayout()} and
13028     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13029     * with the new child ordering.
13030     *
13031     * @see ViewGroup#bringChildToFront(View)
13032     */
13033    public void bringToFront() {
13034        if (mParent != null) {
13035            mParent.bringChildToFront(this);
13036        }
13037    }
13038
13039    /**
13040     * This is called in response to an internal scroll in this view (i.e., the
13041     * view scrolled its own contents). This is typically as a result of
13042     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13043     * called.
13044     *
13045     * @param l Current horizontal scroll origin.
13046     * @param t Current vertical scroll origin.
13047     * @param oldl Previous horizontal scroll origin.
13048     * @param oldt Previous vertical scroll origin.
13049     */
13050    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13051        notifySubtreeAccessibilityStateChangedIfNeeded();
13052
13053        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13054            postSendViewScrolledAccessibilityEventCallback();
13055        }
13056
13057        mBackgroundSizeChanged = true;
13058        mDefaultFocusHighlightSizeChanged = true;
13059        if (mForegroundInfo != null) {
13060            mForegroundInfo.mBoundsChanged = true;
13061        }
13062
13063        final AttachInfo ai = mAttachInfo;
13064        if (ai != null) {
13065            ai.mViewScrollChanged = true;
13066        }
13067
13068        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13069            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13070        }
13071    }
13072
13073    /**
13074     * Interface definition for a callback to be invoked when the scroll
13075     * X or Y positions of a view change.
13076     * <p>
13077     * <b>Note:</b> Some views handle scrolling independently from View and may
13078     * have their own separate listeners for scroll-type events. For example,
13079     * {@link android.widget.ListView ListView} allows clients to register an
13080     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13081     * to listen for changes in list scroll position.
13082     *
13083     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13084     */
13085    public interface OnScrollChangeListener {
13086        /**
13087         * Called when the scroll position of a view changes.
13088         *
13089         * @param v The view whose scroll position has changed.
13090         * @param scrollX Current horizontal scroll origin.
13091         * @param scrollY Current vertical scroll origin.
13092         * @param oldScrollX Previous horizontal scroll origin.
13093         * @param oldScrollY Previous vertical scroll origin.
13094         */
13095        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13096    }
13097
13098    /**
13099     * Interface definition for a callback to be invoked when the layout bounds of a view
13100     * changes due to layout processing.
13101     */
13102    public interface OnLayoutChangeListener {
13103        /**
13104         * Called when the layout bounds of a view changes due to layout processing.
13105         *
13106         * @param v The view whose bounds have changed.
13107         * @param left The new value of the view's left property.
13108         * @param top The new value of the view's top property.
13109         * @param right The new value of the view's right property.
13110         * @param bottom The new value of the view's bottom property.
13111         * @param oldLeft The previous value of the view's left property.
13112         * @param oldTop The previous value of the view's top property.
13113         * @param oldRight The previous value of the view's right property.
13114         * @param oldBottom The previous value of the view's bottom property.
13115         */
13116        void onLayoutChange(View v, int left, int top, int right, int bottom,
13117            int oldLeft, int oldTop, int oldRight, int oldBottom);
13118    }
13119
13120    /**
13121     * This is called during layout when the size of this view has changed. If
13122     * you were just added to the view hierarchy, you're called with the old
13123     * values of 0.
13124     *
13125     * @param w Current width of this view.
13126     * @param h Current height of this view.
13127     * @param oldw Old width of this view.
13128     * @param oldh Old height of this view.
13129     */
13130    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13131    }
13132
13133    /**
13134     * Called by draw to draw the child views. This may be overridden
13135     * by derived classes to gain control just before its children are drawn
13136     * (but after its own view has been drawn).
13137     * @param canvas the canvas on which to draw the view
13138     */
13139    protected void dispatchDraw(Canvas canvas) {
13140
13141    }
13142
13143    /**
13144     * Gets the parent of this view. Note that the parent is a
13145     * ViewParent and not necessarily a View.
13146     *
13147     * @return Parent of this view.
13148     */
13149    public final ViewParent getParent() {
13150        return mParent;
13151    }
13152
13153    /**
13154     * Set the horizontal scrolled position of your view. This will cause a call to
13155     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13156     * invalidated.
13157     * @param value the x position to scroll to
13158     */
13159    public void setScrollX(int value) {
13160        scrollTo(value, mScrollY);
13161    }
13162
13163    /**
13164     * Set the vertical scrolled position of your view. This will cause a call to
13165     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13166     * invalidated.
13167     * @param value the y position to scroll to
13168     */
13169    public void setScrollY(int value) {
13170        scrollTo(mScrollX, value);
13171    }
13172
13173    /**
13174     * Return the scrolled left position of this view. This is the left edge of
13175     * the displayed part of your view. You do not need to draw any pixels
13176     * farther left, since those are outside of the frame of your view on
13177     * screen.
13178     *
13179     * @return The left edge of the displayed part of your view, in pixels.
13180     */
13181    public final int getScrollX() {
13182        return mScrollX;
13183    }
13184
13185    /**
13186     * Return the scrolled top position of this view. This is the top edge of
13187     * the displayed part of your view. You do not need to draw any pixels above
13188     * it, since those are outside of the frame of your view on screen.
13189     *
13190     * @return The top edge of the displayed part of your view, in pixels.
13191     */
13192    public final int getScrollY() {
13193        return mScrollY;
13194    }
13195
13196    /**
13197     * Return the width of the your view.
13198     *
13199     * @return The width of your view, in pixels.
13200     */
13201    @ViewDebug.ExportedProperty(category = "layout")
13202    public final int getWidth() {
13203        return mRight - mLeft;
13204    }
13205
13206    /**
13207     * Return the height of your view.
13208     *
13209     * @return The height of your view, in pixels.
13210     */
13211    @ViewDebug.ExportedProperty(category = "layout")
13212    public final int getHeight() {
13213        return mBottom - mTop;
13214    }
13215
13216    /**
13217     * Return the visible drawing bounds of your view. Fills in the output
13218     * rectangle with the values from getScrollX(), getScrollY(),
13219     * getWidth(), and getHeight(). These bounds do not account for any
13220     * transformation properties currently set on the view, such as
13221     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13222     *
13223     * @param outRect The (scrolled) drawing bounds of the view.
13224     */
13225    public void getDrawingRect(Rect outRect) {
13226        outRect.left = mScrollX;
13227        outRect.top = mScrollY;
13228        outRect.right = mScrollX + (mRight - mLeft);
13229        outRect.bottom = mScrollY + (mBottom - mTop);
13230    }
13231
13232    /**
13233     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13234     * raw width component (that is the result is masked by
13235     * {@link #MEASURED_SIZE_MASK}).
13236     *
13237     * @return The raw measured width of this view.
13238     */
13239    public final int getMeasuredWidth() {
13240        return mMeasuredWidth & MEASURED_SIZE_MASK;
13241    }
13242
13243    /**
13244     * Return the full width measurement information for this view as computed
13245     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13246     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13247     * This should be used during measurement and layout calculations only. Use
13248     * {@link #getWidth()} to see how wide a view is after layout.
13249     *
13250     * @return The measured width of this view as a bit mask.
13251     */
13252    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13253            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13254                    name = "MEASURED_STATE_TOO_SMALL"),
13255    })
13256    public final int getMeasuredWidthAndState() {
13257        return mMeasuredWidth;
13258    }
13259
13260    /**
13261     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13262     * raw height component (that is the result is masked by
13263     * {@link #MEASURED_SIZE_MASK}).
13264     *
13265     * @return The raw measured height of this view.
13266     */
13267    public final int getMeasuredHeight() {
13268        return mMeasuredHeight & MEASURED_SIZE_MASK;
13269    }
13270
13271    /**
13272     * Return the full height measurement information for this view as computed
13273     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13274     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13275     * This should be used during measurement and layout calculations only. Use
13276     * {@link #getHeight()} to see how wide a view is after layout.
13277     *
13278     * @return The measured height of this view as a bit mask.
13279     */
13280    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13281            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13282                    name = "MEASURED_STATE_TOO_SMALL"),
13283    })
13284    public final int getMeasuredHeightAndState() {
13285        return mMeasuredHeight;
13286    }
13287
13288    /**
13289     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13290     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13291     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13292     * and the height component is at the shifted bits
13293     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13294     */
13295    public final int getMeasuredState() {
13296        return (mMeasuredWidth&MEASURED_STATE_MASK)
13297                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13298                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13299    }
13300
13301    /**
13302     * The transform matrix of this view, which is calculated based on the current
13303     * rotation, scale, and pivot properties.
13304     *
13305     * @see #getRotation()
13306     * @see #getScaleX()
13307     * @see #getScaleY()
13308     * @see #getPivotX()
13309     * @see #getPivotY()
13310     * @return The current transform matrix for the view
13311     */
13312    public Matrix getMatrix() {
13313        ensureTransformationInfo();
13314        final Matrix matrix = mTransformationInfo.mMatrix;
13315        mRenderNode.getMatrix(matrix);
13316        return matrix;
13317    }
13318
13319    /**
13320     * Returns true if the transform matrix is the identity matrix.
13321     * Recomputes the matrix if necessary.
13322     *
13323     * @return True if the transform matrix is the identity matrix, false otherwise.
13324     */
13325    final boolean hasIdentityMatrix() {
13326        return mRenderNode.hasIdentityMatrix();
13327    }
13328
13329    void ensureTransformationInfo() {
13330        if (mTransformationInfo == null) {
13331            mTransformationInfo = new TransformationInfo();
13332        }
13333    }
13334
13335    /**
13336     * Utility method to retrieve the inverse of the current mMatrix property.
13337     * We cache the matrix to avoid recalculating it when transform properties
13338     * have not changed.
13339     *
13340     * @return The inverse of the current matrix of this view.
13341     * @hide
13342     */
13343    public final Matrix getInverseMatrix() {
13344        ensureTransformationInfo();
13345        if (mTransformationInfo.mInverseMatrix == null) {
13346            mTransformationInfo.mInverseMatrix = new Matrix();
13347        }
13348        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13349        mRenderNode.getInverseMatrix(matrix);
13350        return matrix;
13351    }
13352
13353    /**
13354     * Gets the distance along the Z axis from the camera to this view.
13355     *
13356     * @see #setCameraDistance(float)
13357     *
13358     * @return The distance along the Z axis.
13359     */
13360    public float getCameraDistance() {
13361        final float dpi = mResources.getDisplayMetrics().densityDpi;
13362        return -(mRenderNode.getCameraDistance() * dpi);
13363    }
13364
13365    /**
13366     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13367     * views are drawn) from the camera to this view. The camera's distance
13368     * affects 3D transformations, for instance rotations around the X and Y
13369     * axis. If the rotationX or rotationY properties are changed and this view is
13370     * large (more than half the size of the screen), it is recommended to always
13371     * use a camera distance that's greater than the height (X axis rotation) or
13372     * the width (Y axis rotation) of this view.</p>
13373     *
13374     * <p>The distance of the camera from the view plane can have an affect on the
13375     * perspective distortion of the view when it is rotated around the x or y axis.
13376     * For example, a large distance will result in a large viewing angle, and there
13377     * will not be much perspective distortion of the view as it rotates. A short
13378     * distance may cause much more perspective distortion upon rotation, and can
13379     * also result in some drawing artifacts if the rotated view ends up partially
13380     * behind the camera (which is why the recommendation is to use a distance at
13381     * least as far as the size of the view, if the view is to be rotated.)</p>
13382     *
13383     * <p>The distance is expressed in "depth pixels." The default distance depends
13384     * on the screen density. For instance, on a medium density display, the
13385     * default distance is 1280. On a high density display, the default distance
13386     * is 1920.</p>
13387     *
13388     * <p>If you want to specify a distance that leads to visually consistent
13389     * results across various densities, use the following formula:</p>
13390     * <pre>
13391     * float scale = context.getResources().getDisplayMetrics().density;
13392     * view.setCameraDistance(distance * scale);
13393     * </pre>
13394     *
13395     * <p>The density scale factor of a high density display is 1.5,
13396     * and 1920 = 1280 * 1.5.</p>
13397     *
13398     * @param distance The distance in "depth pixels", if negative the opposite
13399     *        value is used
13400     *
13401     * @see #setRotationX(float)
13402     * @see #setRotationY(float)
13403     */
13404    public void setCameraDistance(float distance) {
13405        final float dpi = mResources.getDisplayMetrics().densityDpi;
13406
13407        invalidateViewProperty(true, false);
13408        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13409        invalidateViewProperty(false, false);
13410
13411        invalidateParentIfNeededAndWasQuickRejected();
13412    }
13413
13414    /**
13415     * The degrees that the view is rotated around the pivot point.
13416     *
13417     * @see #setRotation(float)
13418     * @see #getPivotX()
13419     * @see #getPivotY()
13420     *
13421     * @return The degrees of rotation.
13422     */
13423    @ViewDebug.ExportedProperty(category = "drawing")
13424    public float getRotation() {
13425        return mRenderNode.getRotation();
13426    }
13427
13428    /**
13429     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13430     * result in clockwise rotation.
13431     *
13432     * @param rotation The degrees of rotation.
13433     *
13434     * @see #getRotation()
13435     * @see #getPivotX()
13436     * @see #getPivotY()
13437     * @see #setRotationX(float)
13438     * @see #setRotationY(float)
13439     *
13440     * @attr ref android.R.styleable#View_rotation
13441     */
13442    public void setRotation(float rotation) {
13443        if (rotation != getRotation()) {
13444            // Double-invalidation is necessary to capture view's old and new areas
13445            invalidateViewProperty(true, false);
13446            mRenderNode.setRotation(rotation);
13447            invalidateViewProperty(false, true);
13448
13449            invalidateParentIfNeededAndWasQuickRejected();
13450            notifySubtreeAccessibilityStateChangedIfNeeded();
13451        }
13452    }
13453
13454    /**
13455     * The degrees that the view is rotated around the vertical axis through the pivot point.
13456     *
13457     * @see #getPivotX()
13458     * @see #getPivotY()
13459     * @see #setRotationY(float)
13460     *
13461     * @return The degrees of Y rotation.
13462     */
13463    @ViewDebug.ExportedProperty(category = "drawing")
13464    public float getRotationY() {
13465        return mRenderNode.getRotationY();
13466    }
13467
13468    /**
13469     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13470     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13471     * down the y axis.
13472     *
13473     * When rotating large views, it is recommended to adjust the camera distance
13474     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13475     *
13476     * @param rotationY The degrees of Y rotation.
13477     *
13478     * @see #getRotationY()
13479     * @see #getPivotX()
13480     * @see #getPivotY()
13481     * @see #setRotation(float)
13482     * @see #setRotationX(float)
13483     * @see #setCameraDistance(float)
13484     *
13485     * @attr ref android.R.styleable#View_rotationY
13486     */
13487    public void setRotationY(float rotationY) {
13488        if (rotationY != getRotationY()) {
13489            invalidateViewProperty(true, false);
13490            mRenderNode.setRotationY(rotationY);
13491            invalidateViewProperty(false, true);
13492
13493            invalidateParentIfNeededAndWasQuickRejected();
13494            notifySubtreeAccessibilityStateChangedIfNeeded();
13495        }
13496    }
13497
13498    /**
13499     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13500     *
13501     * @see #getPivotX()
13502     * @see #getPivotY()
13503     * @see #setRotationX(float)
13504     *
13505     * @return The degrees of X rotation.
13506     */
13507    @ViewDebug.ExportedProperty(category = "drawing")
13508    public float getRotationX() {
13509        return mRenderNode.getRotationX();
13510    }
13511
13512    /**
13513     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13514     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13515     * x axis.
13516     *
13517     * When rotating large views, it is recommended to adjust the camera distance
13518     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13519     *
13520     * @param rotationX The degrees of X rotation.
13521     *
13522     * @see #getRotationX()
13523     * @see #getPivotX()
13524     * @see #getPivotY()
13525     * @see #setRotation(float)
13526     * @see #setRotationY(float)
13527     * @see #setCameraDistance(float)
13528     *
13529     * @attr ref android.R.styleable#View_rotationX
13530     */
13531    public void setRotationX(float rotationX) {
13532        if (rotationX != getRotationX()) {
13533            invalidateViewProperty(true, false);
13534            mRenderNode.setRotationX(rotationX);
13535            invalidateViewProperty(false, true);
13536
13537            invalidateParentIfNeededAndWasQuickRejected();
13538            notifySubtreeAccessibilityStateChangedIfNeeded();
13539        }
13540    }
13541
13542    /**
13543     * The amount that the view is scaled in x around the pivot point, as a proportion of
13544     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13545     *
13546     * <p>By default, this is 1.0f.
13547     *
13548     * @see #getPivotX()
13549     * @see #getPivotY()
13550     * @return The scaling factor.
13551     */
13552    @ViewDebug.ExportedProperty(category = "drawing")
13553    public float getScaleX() {
13554        return mRenderNode.getScaleX();
13555    }
13556
13557    /**
13558     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13559     * the view's unscaled width. A value of 1 means that no scaling is applied.
13560     *
13561     * @param scaleX The scaling factor.
13562     * @see #getPivotX()
13563     * @see #getPivotY()
13564     *
13565     * @attr ref android.R.styleable#View_scaleX
13566     */
13567    public void setScaleX(float scaleX) {
13568        if (scaleX != getScaleX()) {
13569            invalidateViewProperty(true, false);
13570            mRenderNode.setScaleX(scaleX);
13571            invalidateViewProperty(false, true);
13572
13573            invalidateParentIfNeededAndWasQuickRejected();
13574            notifySubtreeAccessibilityStateChangedIfNeeded();
13575        }
13576    }
13577
13578    /**
13579     * The amount that the view is scaled in y around the pivot point, as a proportion of
13580     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13581     *
13582     * <p>By default, this is 1.0f.
13583     *
13584     * @see #getPivotX()
13585     * @see #getPivotY()
13586     * @return The scaling factor.
13587     */
13588    @ViewDebug.ExportedProperty(category = "drawing")
13589    public float getScaleY() {
13590        return mRenderNode.getScaleY();
13591    }
13592
13593    /**
13594     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13595     * the view's unscaled width. A value of 1 means that no scaling is applied.
13596     *
13597     * @param scaleY The scaling factor.
13598     * @see #getPivotX()
13599     * @see #getPivotY()
13600     *
13601     * @attr ref android.R.styleable#View_scaleY
13602     */
13603    public void setScaleY(float scaleY) {
13604        if (scaleY != getScaleY()) {
13605            invalidateViewProperty(true, false);
13606            mRenderNode.setScaleY(scaleY);
13607            invalidateViewProperty(false, true);
13608
13609            invalidateParentIfNeededAndWasQuickRejected();
13610            notifySubtreeAccessibilityStateChangedIfNeeded();
13611        }
13612    }
13613
13614    /**
13615     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13616     * and {@link #setScaleX(float) scaled}.
13617     *
13618     * @see #getRotation()
13619     * @see #getScaleX()
13620     * @see #getScaleY()
13621     * @see #getPivotY()
13622     * @return The x location of the pivot point.
13623     *
13624     * @attr ref android.R.styleable#View_transformPivotX
13625     */
13626    @ViewDebug.ExportedProperty(category = "drawing")
13627    public float getPivotX() {
13628        return mRenderNode.getPivotX();
13629    }
13630
13631    /**
13632     * Sets the x location of the point around which the view is
13633     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13634     * By default, the pivot point is centered on the object.
13635     * Setting this property disables this behavior and causes the view to use only the
13636     * explicitly set pivotX and pivotY values.
13637     *
13638     * @param pivotX The x location of the pivot point.
13639     * @see #getRotation()
13640     * @see #getScaleX()
13641     * @see #getScaleY()
13642     * @see #getPivotY()
13643     *
13644     * @attr ref android.R.styleable#View_transformPivotX
13645     */
13646    public void setPivotX(float pivotX) {
13647        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13648            invalidateViewProperty(true, false);
13649            mRenderNode.setPivotX(pivotX);
13650            invalidateViewProperty(false, true);
13651
13652            invalidateParentIfNeededAndWasQuickRejected();
13653        }
13654    }
13655
13656    /**
13657     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13658     * and {@link #setScaleY(float) scaled}.
13659     *
13660     * @see #getRotation()
13661     * @see #getScaleX()
13662     * @see #getScaleY()
13663     * @see #getPivotY()
13664     * @return The y location of the pivot point.
13665     *
13666     * @attr ref android.R.styleable#View_transformPivotY
13667     */
13668    @ViewDebug.ExportedProperty(category = "drawing")
13669    public float getPivotY() {
13670        return mRenderNode.getPivotY();
13671    }
13672
13673    /**
13674     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13675     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13676     * Setting this property disables this behavior and causes the view to use only the
13677     * explicitly set pivotX and pivotY values.
13678     *
13679     * @param pivotY The y location of the pivot point.
13680     * @see #getRotation()
13681     * @see #getScaleX()
13682     * @see #getScaleY()
13683     * @see #getPivotY()
13684     *
13685     * @attr ref android.R.styleable#View_transformPivotY
13686     */
13687    public void setPivotY(float pivotY) {
13688        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13689            invalidateViewProperty(true, false);
13690            mRenderNode.setPivotY(pivotY);
13691            invalidateViewProperty(false, true);
13692
13693            invalidateParentIfNeededAndWasQuickRejected();
13694        }
13695    }
13696
13697    /**
13698     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13699     * completely transparent and 1 means the view is completely opaque.
13700     *
13701     * <p>By default this is 1.0f.
13702     * @return The opacity of the view.
13703     */
13704    @ViewDebug.ExportedProperty(category = "drawing")
13705    public float getAlpha() {
13706        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13707    }
13708
13709    /**
13710     * Sets the behavior for overlapping rendering for this view (see {@link
13711     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13712     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13713     * providing the value which is then used internally. That is, when {@link
13714     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13715     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13716     * instead.
13717     *
13718     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13719     * instead of that returned by {@link #hasOverlappingRendering()}.
13720     *
13721     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13722     */
13723    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13724        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13725        if (hasOverlappingRendering) {
13726            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13727        } else {
13728            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13729        }
13730    }
13731
13732    /**
13733     * Returns the value for overlapping rendering that is used internally. This is either
13734     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13735     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13736     *
13737     * @return The value for overlapping rendering being used internally.
13738     */
13739    public final boolean getHasOverlappingRendering() {
13740        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13741                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13742                hasOverlappingRendering();
13743    }
13744
13745    /**
13746     * Returns whether this View has content which overlaps.
13747     *
13748     * <p>This function, intended to be overridden by specific View types, is an optimization when
13749     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13750     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13751     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13752     * directly. An example of overlapping rendering is a TextView with a background image, such as
13753     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13754     * ImageView with only the foreground image. The default implementation returns true; subclasses
13755     * should override if they have cases which can be optimized.</p>
13756     *
13757     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13758     * necessitates that a View return true if it uses the methods internally without passing the
13759     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13760     *
13761     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13762     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13763     *
13764     * @return true if the content in this view might overlap, false otherwise.
13765     */
13766    @ViewDebug.ExportedProperty(category = "drawing")
13767    public boolean hasOverlappingRendering() {
13768        return true;
13769    }
13770
13771    /**
13772     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13773     * completely transparent and 1 means the view is completely opaque.
13774     *
13775     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13776     * can have significant performance implications, especially for large views. It is best to use
13777     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13778     *
13779     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13780     * strongly recommended for performance reasons to either override
13781     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13782     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13783     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13784     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13785     * of rendering cost, even for simple or small views. Starting with
13786     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13787     * applied to the view at the rendering level.</p>
13788     *
13789     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13790     * responsible for applying the opacity itself.</p>
13791     *
13792     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13793     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13794     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13795     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13796     *
13797     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13798     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13799     * {@link #hasOverlappingRendering}.</p>
13800     *
13801     * @param alpha The opacity of the view.
13802     *
13803     * @see #hasOverlappingRendering()
13804     * @see #setLayerType(int, android.graphics.Paint)
13805     *
13806     * @attr ref android.R.styleable#View_alpha
13807     */
13808    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13809        ensureTransformationInfo();
13810        if (mTransformationInfo.mAlpha != alpha) {
13811            // Report visibility changes, which can affect children, to accessibility
13812            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13813                notifySubtreeAccessibilityStateChangedIfNeeded();
13814            }
13815            mTransformationInfo.mAlpha = alpha;
13816            if (onSetAlpha((int) (alpha * 255))) {
13817                mPrivateFlags |= PFLAG_ALPHA_SET;
13818                // subclass is handling alpha - don't optimize rendering cache invalidation
13819                invalidateParentCaches();
13820                invalidate(true);
13821            } else {
13822                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13823                invalidateViewProperty(true, false);
13824                mRenderNode.setAlpha(getFinalAlpha());
13825            }
13826        }
13827    }
13828
13829    /**
13830     * Faster version of setAlpha() which performs the same steps except there are
13831     * no calls to invalidate(). The caller of this function should perform proper invalidation
13832     * on the parent and this object. The return value indicates whether the subclass handles
13833     * alpha (the return value for onSetAlpha()).
13834     *
13835     * @param alpha The new value for the alpha property
13836     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13837     *         the new value for the alpha property is different from the old value
13838     */
13839    boolean setAlphaNoInvalidation(float alpha) {
13840        ensureTransformationInfo();
13841        if (mTransformationInfo.mAlpha != alpha) {
13842            mTransformationInfo.mAlpha = alpha;
13843            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13844            if (subclassHandlesAlpha) {
13845                mPrivateFlags |= PFLAG_ALPHA_SET;
13846                return true;
13847            } else {
13848                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13849                mRenderNode.setAlpha(getFinalAlpha());
13850            }
13851        }
13852        return false;
13853    }
13854
13855    /**
13856     * This property is hidden and intended only for use by the Fade transition, which
13857     * animates it to produce a visual translucency that does not side-effect (or get
13858     * affected by) the real alpha property. This value is composited with the other
13859     * alpha value (and the AlphaAnimation value, when that is present) to produce
13860     * a final visual translucency result, which is what is passed into the DisplayList.
13861     *
13862     * @hide
13863     */
13864    public void setTransitionAlpha(float alpha) {
13865        ensureTransformationInfo();
13866        if (mTransformationInfo.mTransitionAlpha != alpha) {
13867            mTransformationInfo.mTransitionAlpha = alpha;
13868            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13869            invalidateViewProperty(true, false);
13870            mRenderNode.setAlpha(getFinalAlpha());
13871        }
13872    }
13873
13874    /**
13875     * Calculates the visual alpha of this view, which is a combination of the actual
13876     * alpha value and the transitionAlpha value (if set).
13877     */
13878    private float getFinalAlpha() {
13879        if (mTransformationInfo != null) {
13880            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13881        }
13882        return 1;
13883    }
13884
13885    /**
13886     * This property is hidden and intended only for use by the Fade transition, which
13887     * animates it to produce a visual translucency that does not side-effect (or get
13888     * affected by) the real alpha property. This value is composited with the other
13889     * alpha value (and the AlphaAnimation value, when that is present) to produce
13890     * a final visual translucency result, which is what is passed into the DisplayList.
13891     *
13892     * @hide
13893     */
13894    @ViewDebug.ExportedProperty(category = "drawing")
13895    public float getTransitionAlpha() {
13896        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13897    }
13898
13899    /**
13900     * Top position of this view relative to its parent.
13901     *
13902     * @return The top of this view, in pixels.
13903     */
13904    @ViewDebug.CapturedViewProperty
13905    public final int getTop() {
13906        return mTop;
13907    }
13908
13909    /**
13910     * Sets the top position of this view relative to its parent. This method is meant to be called
13911     * by the layout system and should not generally be called otherwise, because the property
13912     * may be changed at any time by the layout.
13913     *
13914     * @param top The top of this view, in pixels.
13915     */
13916    public final void setTop(int top) {
13917        if (top != mTop) {
13918            final boolean matrixIsIdentity = hasIdentityMatrix();
13919            if (matrixIsIdentity) {
13920                if (mAttachInfo != null) {
13921                    int minTop;
13922                    int yLoc;
13923                    if (top < mTop) {
13924                        minTop = top;
13925                        yLoc = top - mTop;
13926                    } else {
13927                        minTop = mTop;
13928                        yLoc = 0;
13929                    }
13930                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13931                }
13932            } else {
13933                // Double-invalidation is necessary to capture view's old and new areas
13934                invalidate(true);
13935            }
13936
13937            int width = mRight - mLeft;
13938            int oldHeight = mBottom - mTop;
13939
13940            mTop = top;
13941            mRenderNode.setTop(mTop);
13942
13943            sizeChange(width, mBottom - mTop, width, oldHeight);
13944
13945            if (!matrixIsIdentity) {
13946                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13947                invalidate(true);
13948            }
13949            mBackgroundSizeChanged = true;
13950            mDefaultFocusHighlightSizeChanged = true;
13951            if (mForegroundInfo != null) {
13952                mForegroundInfo.mBoundsChanged = true;
13953            }
13954            invalidateParentIfNeeded();
13955            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13956                // View was rejected last time it was drawn by its parent; this may have changed
13957                invalidateParentIfNeeded();
13958            }
13959        }
13960    }
13961
13962    /**
13963     * Bottom position of this view relative to its parent.
13964     *
13965     * @return The bottom of this view, in pixels.
13966     */
13967    @ViewDebug.CapturedViewProperty
13968    public final int getBottom() {
13969        return mBottom;
13970    }
13971
13972    /**
13973     * True if this view has changed since the last time being drawn.
13974     *
13975     * @return The dirty state of this view.
13976     */
13977    public boolean isDirty() {
13978        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13979    }
13980
13981    /**
13982     * Sets the bottom position of this view relative to its parent. This method is meant to be
13983     * called by the layout system and should not generally be called otherwise, because the
13984     * property may be changed at any time by the layout.
13985     *
13986     * @param bottom The bottom of this view, in pixels.
13987     */
13988    public final void setBottom(int bottom) {
13989        if (bottom != mBottom) {
13990            final boolean matrixIsIdentity = hasIdentityMatrix();
13991            if (matrixIsIdentity) {
13992                if (mAttachInfo != null) {
13993                    int maxBottom;
13994                    if (bottom < mBottom) {
13995                        maxBottom = mBottom;
13996                    } else {
13997                        maxBottom = bottom;
13998                    }
13999                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14000                }
14001            } else {
14002                // Double-invalidation is necessary to capture view's old and new areas
14003                invalidate(true);
14004            }
14005
14006            int width = mRight - mLeft;
14007            int oldHeight = mBottom - mTop;
14008
14009            mBottom = bottom;
14010            mRenderNode.setBottom(mBottom);
14011
14012            sizeChange(width, mBottom - mTop, width, oldHeight);
14013
14014            if (!matrixIsIdentity) {
14015                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14016                invalidate(true);
14017            }
14018            mBackgroundSizeChanged = true;
14019            mDefaultFocusHighlightSizeChanged = true;
14020            if (mForegroundInfo != null) {
14021                mForegroundInfo.mBoundsChanged = true;
14022            }
14023            invalidateParentIfNeeded();
14024            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14025                // View was rejected last time it was drawn by its parent; this may have changed
14026                invalidateParentIfNeeded();
14027            }
14028        }
14029    }
14030
14031    /**
14032     * Left position of this view relative to its parent.
14033     *
14034     * @return The left edge of this view, in pixels.
14035     */
14036    @ViewDebug.CapturedViewProperty
14037    public final int getLeft() {
14038        return mLeft;
14039    }
14040
14041    /**
14042     * Sets the left position of this view relative to its parent. This method is meant to be called
14043     * by the layout system and should not generally be called otherwise, because the property
14044     * may be changed at any time by the layout.
14045     *
14046     * @param left The left of this view, in pixels.
14047     */
14048    public final void setLeft(int left) {
14049        if (left != mLeft) {
14050            final boolean matrixIsIdentity = hasIdentityMatrix();
14051            if (matrixIsIdentity) {
14052                if (mAttachInfo != null) {
14053                    int minLeft;
14054                    int xLoc;
14055                    if (left < mLeft) {
14056                        minLeft = left;
14057                        xLoc = left - mLeft;
14058                    } else {
14059                        minLeft = mLeft;
14060                        xLoc = 0;
14061                    }
14062                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14063                }
14064            } else {
14065                // Double-invalidation is necessary to capture view's old and new areas
14066                invalidate(true);
14067            }
14068
14069            int oldWidth = mRight - mLeft;
14070            int height = mBottom - mTop;
14071
14072            mLeft = left;
14073            mRenderNode.setLeft(left);
14074
14075            sizeChange(mRight - mLeft, height, oldWidth, height);
14076
14077            if (!matrixIsIdentity) {
14078                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14079                invalidate(true);
14080            }
14081            mBackgroundSizeChanged = true;
14082            mDefaultFocusHighlightSizeChanged = true;
14083            if (mForegroundInfo != null) {
14084                mForegroundInfo.mBoundsChanged = true;
14085            }
14086            invalidateParentIfNeeded();
14087            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14088                // View was rejected last time it was drawn by its parent; this may have changed
14089                invalidateParentIfNeeded();
14090            }
14091        }
14092    }
14093
14094    /**
14095     * Right position of this view relative to its parent.
14096     *
14097     * @return The right edge of this view, in pixels.
14098     */
14099    @ViewDebug.CapturedViewProperty
14100    public final int getRight() {
14101        return mRight;
14102    }
14103
14104    /**
14105     * Sets the right position of this view relative to its parent. This method is meant to be called
14106     * by the layout system and should not generally be called otherwise, because the property
14107     * may be changed at any time by the layout.
14108     *
14109     * @param right The right of this view, in pixels.
14110     */
14111    public final void setRight(int right) {
14112        if (right != mRight) {
14113            final boolean matrixIsIdentity = hasIdentityMatrix();
14114            if (matrixIsIdentity) {
14115                if (mAttachInfo != null) {
14116                    int maxRight;
14117                    if (right < mRight) {
14118                        maxRight = mRight;
14119                    } else {
14120                        maxRight = right;
14121                    }
14122                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14123                }
14124            } else {
14125                // Double-invalidation is necessary to capture view's old and new areas
14126                invalidate(true);
14127            }
14128
14129            int oldWidth = mRight - mLeft;
14130            int height = mBottom - mTop;
14131
14132            mRight = right;
14133            mRenderNode.setRight(mRight);
14134
14135            sizeChange(mRight - mLeft, height, oldWidth, height);
14136
14137            if (!matrixIsIdentity) {
14138                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14139                invalidate(true);
14140            }
14141            mBackgroundSizeChanged = true;
14142            mDefaultFocusHighlightSizeChanged = true;
14143            if (mForegroundInfo != null) {
14144                mForegroundInfo.mBoundsChanged = true;
14145            }
14146            invalidateParentIfNeeded();
14147            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14148                // View was rejected last time it was drawn by its parent; this may have changed
14149                invalidateParentIfNeeded();
14150            }
14151        }
14152    }
14153
14154    /**
14155     * The visual x position of this view, in pixels. This is equivalent to the
14156     * {@link #setTranslationX(float) translationX} property plus the current
14157     * {@link #getLeft() left} property.
14158     *
14159     * @return The visual x position of this view, in pixels.
14160     */
14161    @ViewDebug.ExportedProperty(category = "drawing")
14162    public float getX() {
14163        return mLeft + getTranslationX();
14164    }
14165
14166    /**
14167     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14168     * {@link #setTranslationX(float) translationX} property to be the difference between
14169     * the x value passed in and the current {@link #getLeft() left} property.
14170     *
14171     * @param x The visual x position of this view, in pixels.
14172     */
14173    public void setX(float x) {
14174        setTranslationX(x - mLeft);
14175    }
14176
14177    /**
14178     * The visual y position of this view, in pixels. This is equivalent to the
14179     * {@link #setTranslationY(float) translationY} property plus the current
14180     * {@link #getTop() top} property.
14181     *
14182     * @return The visual y position of this view, in pixels.
14183     */
14184    @ViewDebug.ExportedProperty(category = "drawing")
14185    public float getY() {
14186        return mTop + getTranslationY();
14187    }
14188
14189    /**
14190     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14191     * {@link #setTranslationY(float) translationY} property to be the difference between
14192     * the y value passed in and the current {@link #getTop() top} property.
14193     *
14194     * @param y The visual y position of this view, in pixels.
14195     */
14196    public void setY(float y) {
14197        setTranslationY(y - mTop);
14198    }
14199
14200    /**
14201     * The visual z position of this view, in pixels. This is equivalent to the
14202     * {@link #setTranslationZ(float) translationZ} property plus the current
14203     * {@link #getElevation() elevation} property.
14204     *
14205     * @return The visual z position of this view, in pixels.
14206     */
14207    @ViewDebug.ExportedProperty(category = "drawing")
14208    public float getZ() {
14209        return getElevation() + getTranslationZ();
14210    }
14211
14212    /**
14213     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14214     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14215     * the x value passed in and the current {@link #getElevation() elevation} property.
14216     *
14217     * @param z The visual z position of this view, in pixels.
14218     */
14219    public void setZ(float z) {
14220        setTranslationZ(z - getElevation());
14221    }
14222
14223    /**
14224     * The base elevation of this view relative to its parent, in pixels.
14225     *
14226     * @return The base depth position of the view, in pixels.
14227     */
14228    @ViewDebug.ExportedProperty(category = "drawing")
14229    public float getElevation() {
14230        return mRenderNode.getElevation();
14231    }
14232
14233    /**
14234     * Sets the base elevation of this view, in pixels.
14235     *
14236     * @attr ref android.R.styleable#View_elevation
14237     */
14238    public void setElevation(float elevation) {
14239        if (elevation != getElevation()) {
14240            invalidateViewProperty(true, false);
14241            mRenderNode.setElevation(elevation);
14242            invalidateViewProperty(false, true);
14243
14244            invalidateParentIfNeededAndWasQuickRejected();
14245        }
14246    }
14247
14248    /**
14249     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14250     * This position is post-layout, in addition to wherever the object's
14251     * layout placed it.
14252     *
14253     * @return The horizontal position of this view relative to its left position, in pixels.
14254     */
14255    @ViewDebug.ExportedProperty(category = "drawing")
14256    public float getTranslationX() {
14257        return mRenderNode.getTranslationX();
14258    }
14259
14260    /**
14261     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14262     * This effectively positions the object post-layout, in addition to wherever the object's
14263     * layout placed it.
14264     *
14265     * @param translationX The horizontal position of this view relative to its left position,
14266     * in pixels.
14267     *
14268     * @attr ref android.R.styleable#View_translationX
14269     */
14270    public void setTranslationX(float translationX) {
14271        if (translationX != getTranslationX()) {
14272            invalidateViewProperty(true, false);
14273            mRenderNode.setTranslationX(translationX);
14274            invalidateViewProperty(false, true);
14275
14276            invalidateParentIfNeededAndWasQuickRejected();
14277            notifySubtreeAccessibilityStateChangedIfNeeded();
14278        }
14279    }
14280
14281    /**
14282     * The vertical location of this view relative to its {@link #getTop() top} position.
14283     * This position is post-layout, in addition to wherever the object's
14284     * layout placed it.
14285     *
14286     * @return The vertical position of this view relative to its top position,
14287     * in pixels.
14288     */
14289    @ViewDebug.ExportedProperty(category = "drawing")
14290    public float getTranslationY() {
14291        return mRenderNode.getTranslationY();
14292    }
14293
14294    /**
14295     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14296     * This effectively positions the object post-layout, in addition to wherever the object's
14297     * layout placed it.
14298     *
14299     * @param translationY The vertical position of this view relative to its top position,
14300     * in pixels.
14301     *
14302     * @attr ref android.R.styleable#View_translationY
14303     */
14304    public void setTranslationY(float translationY) {
14305        if (translationY != getTranslationY()) {
14306            invalidateViewProperty(true, false);
14307            mRenderNode.setTranslationY(translationY);
14308            invalidateViewProperty(false, true);
14309
14310            invalidateParentIfNeededAndWasQuickRejected();
14311            notifySubtreeAccessibilityStateChangedIfNeeded();
14312        }
14313    }
14314
14315    /**
14316     * The depth location of this view relative to its {@link #getElevation() elevation}.
14317     *
14318     * @return The depth of this view relative to its elevation.
14319     */
14320    @ViewDebug.ExportedProperty(category = "drawing")
14321    public float getTranslationZ() {
14322        return mRenderNode.getTranslationZ();
14323    }
14324
14325    /**
14326     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14327     *
14328     * @attr ref android.R.styleable#View_translationZ
14329     */
14330    public void setTranslationZ(float translationZ) {
14331        if (translationZ != getTranslationZ()) {
14332            invalidateViewProperty(true, false);
14333            mRenderNode.setTranslationZ(translationZ);
14334            invalidateViewProperty(false, true);
14335
14336            invalidateParentIfNeededAndWasQuickRejected();
14337        }
14338    }
14339
14340    /** @hide */
14341    public void setAnimationMatrix(Matrix matrix) {
14342        invalidateViewProperty(true, false);
14343        mRenderNode.setAnimationMatrix(matrix);
14344        invalidateViewProperty(false, true);
14345
14346        invalidateParentIfNeededAndWasQuickRejected();
14347    }
14348
14349    /**
14350     * Returns the current StateListAnimator if exists.
14351     *
14352     * @return StateListAnimator or null if it does not exists
14353     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14354     */
14355    public StateListAnimator getStateListAnimator() {
14356        return mStateListAnimator;
14357    }
14358
14359    /**
14360     * Attaches the provided StateListAnimator to this View.
14361     * <p>
14362     * Any previously attached StateListAnimator will be detached.
14363     *
14364     * @param stateListAnimator The StateListAnimator to update the view
14365     * @see android.animation.StateListAnimator
14366     */
14367    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14368        if (mStateListAnimator == stateListAnimator) {
14369            return;
14370        }
14371        if (mStateListAnimator != null) {
14372            mStateListAnimator.setTarget(null);
14373        }
14374        mStateListAnimator = stateListAnimator;
14375        if (stateListAnimator != null) {
14376            stateListAnimator.setTarget(this);
14377            if (isAttachedToWindow()) {
14378                stateListAnimator.setState(getDrawableState());
14379            }
14380        }
14381    }
14382
14383    /**
14384     * Returns whether the Outline should be used to clip the contents of the View.
14385     * <p>
14386     * Note that this flag will only be respected if the View's Outline returns true from
14387     * {@link Outline#canClip()}.
14388     *
14389     * @see #setOutlineProvider(ViewOutlineProvider)
14390     * @see #setClipToOutline(boolean)
14391     */
14392    public final boolean getClipToOutline() {
14393        return mRenderNode.getClipToOutline();
14394    }
14395
14396    /**
14397     * Sets whether the View's Outline should be used to clip the contents of the View.
14398     * <p>
14399     * Only a single non-rectangular clip can be applied on a View at any time.
14400     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14401     * circular reveal} animation take priority over Outline clipping, and
14402     * child Outline clipping takes priority over Outline clipping done by a
14403     * parent.
14404     * <p>
14405     * Note that this flag will only be respected if the View's Outline returns true from
14406     * {@link Outline#canClip()}.
14407     *
14408     * @see #setOutlineProvider(ViewOutlineProvider)
14409     * @see #getClipToOutline()
14410     */
14411    public void setClipToOutline(boolean clipToOutline) {
14412        damageInParent();
14413        if (getClipToOutline() != clipToOutline) {
14414            mRenderNode.setClipToOutline(clipToOutline);
14415        }
14416    }
14417
14418    // correspond to the enum values of View_outlineProvider
14419    private static final int PROVIDER_BACKGROUND = 0;
14420    private static final int PROVIDER_NONE = 1;
14421    private static final int PROVIDER_BOUNDS = 2;
14422    private static final int PROVIDER_PADDED_BOUNDS = 3;
14423    private void setOutlineProviderFromAttribute(int providerInt) {
14424        switch (providerInt) {
14425            case PROVIDER_BACKGROUND:
14426                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14427                break;
14428            case PROVIDER_NONE:
14429                setOutlineProvider(null);
14430                break;
14431            case PROVIDER_BOUNDS:
14432                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14433                break;
14434            case PROVIDER_PADDED_BOUNDS:
14435                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14436                break;
14437        }
14438    }
14439
14440    /**
14441     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14442     * the shape of the shadow it casts, and enables outline clipping.
14443     * <p>
14444     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14445     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14446     * outline provider with this method allows this behavior to be overridden.
14447     * <p>
14448     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14449     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14450     * <p>
14451     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14452     *
14453     * @see #setClipToOutline(boolean)
14454     * @see #getClipToOutline()
14455     * @see #getOutlineProvider()
14456     */
14457    public void setOutlineProvider(ViewOutlineProvider provider) {
14458        mOutlineProvider = provider;
14459        invalidateOutline();
14460    }
14461
14462    /**
14463     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14464     * that defines the shape of the shadow it casts, and enables outline clipping.
14465     *
14466     * @see #setOutlineProvider(ViewOutlineProvider)
14467     */
14468    public ViewOutlineProvider getOutlineProvider() {
14469        return mOutlineProvider;
14470    }
14471
14472    /**
14473     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14474     *
14475     * @see #setOutlineProvider(ViewOutlineProvider)
14476     */
14477    public void invalidateOutline() {
14478        rebuildOutline();
14479
14480        notifySubtreeAccessibilityStateChangedIfNeeded();
14481        invalidateViewProperty(false, false);
14482    }
14483
14484    /**
14485     * Internal version of {@link #invalidateOutline()} which invalidates the
14486     * outline without invalidating the view itself. This is intended to be called from
14487     * within methods in the View class itself which are the result of the view being
14488     * invalidated already. For example, when we are drawing the background of a View,
14489     * we invalidate the outline in case it changed in the meantime, but we do not
14490     * need to invalidate the view because we're already drawing the background as part
14491     * of drawing the view in response to an earlier invalidation of the view.
14492     */
14493    private void rebuildOutline() {
14494        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14495        if (mAttachInfo == null) return;
14496
14497        if (mOutlineProvider == null) {
14498            // no provider, remove outline
14499            mRenderNode.setOutline(null);
14500        } else {
14501            final Outline outline = mAttachInfo.mTmpOutline;
14502            outline.setEmpty();
14503            outline.setAlpha(1.0f);
14504
14505            mOutlineProvider.getOutline(this, outline);
14506            mRenderNode.setOutline(outline);
14507        }
14508    }
14509
14510    /**
14511     * HierarchyViewer only
14512     *
14513     * @hide
14514     */
14515    @ViewDebug.ExportedProperty(category = "drawing")
14516    public boolean hasShadow() {
14517        return mRenderNode.hasShadow();
14518    }
14519
14520
14521    /** @hide */
14522    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14523        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14524        invalidateViewProperty(false, false);
14525    }
14526
14527    /**
14528     * Hit rectangle in parent's coordinates
14529     *
14530     * @param outRect The hit rectangle of the view.
14531     */
14532    public void getHitRect(Rect outRect) {
14533        if (hasIdentityMatrix() || mAttachInfo == null) {
14534            outRect.set(mLeft, mTop, mRight, mBottom);
14535        } else {
14536            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14537            tmpRect.set(0, 0, getWidth(), getHeight());
14538            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14539            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14540                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14541        }
14542    }
14543
14544    /**
14545     * Determines whether the given point, in local coordinates is inside the view.
14546     */
14547    /*package*/ final boolean pointInView(float localX, float localY) {
14548        return pointInView(localX, localY, 0);
14549    }
14550
14551    /**
14552     * Utility method to determine whether the given point, in local coordinates,
14553     * is inside the view, where the area of the view is expanded by the slop factor.
14554     * This method is called while processing touch-move events to determine if the event
14555     * is still within the view.
14556     *
14557     * @hide
14558     */
14559    public boolean pointInView(float localX, float localY, float slop) {
14560        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14561                localY < ((mBottom - mTop) + slop);
14562    }
14563
14564    /**
14565     * When a view has focus and the user navigates away from it, the next view is searched for
14566     * starting from the rectangle filled in by this method.
14567     *
14568     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14569     * of the view.  However, if your view maintains some idea of internal selection,
14570     * such as a cursor, or a selected row or column, you should override this method and
14571     * fill in a more specific rectangle.
14572     *
14573     * @param r The rectangle to fill in, in this view's coordinates.
14574     */
14575    public void getFocusedRect(Rect r) {
14576        getDrawingRect(r);
14577    }
14578
14579    /**
14580     * If some part of this view is not clipped by any of its parents, then
14581     * return that area in r in global (root) coordinates. To convert r to local
14582     * coordinates (without taking possible View rotations into account), offset
14583     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14584     * If the view is completely clipped or translated out, return false.
14585     *
14586     * @param r If true is returned, r holds the global coordinates of the
14587     *        visible portion of this view.
14588     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14589     *        between this view and its root. globalOffet may be null.
14590     * @return true if r is non-empty (i.e. part of the view is visible at the
14591     *         root level.
14592     */
14593    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14594        int width = mRight - mLeft;
14595        int height = mBottom - mTop;
14596        if (width > 0 && height > 0) {
14597            r.set(0, 0, width, height);
14598            if (globalOffset != null) {
14599                globalOffset.set(-mScrollX, -mScrollY);
14600            }
14601            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14602        }
14603        return false;
14604    }
14605
14606    public final boolean getGlobalVisibleRect(Rect r) {
14607        return getGlobalVisibleRect(r, null);
14608    }
14609
14610    public final boolean getLocalVisibleRect(Rect r) {
14611        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14612        if (getGlobalVisibleRect(r, offset)) {
14613            r.offset(-offset.x, -offset.y); // make r local
14614            return true;
14615        }
14616        return false;
14617    }
14618
14619    /**
14620     * Offset this view's vertical location by the specified number of pixels.
14621     *
14622     * @param offset the number of pixels to offset the view by
14623     */
14624    public void offsetTopAndBottom(int offset) {
14625        if (offset != 0) {
14626            final boolean matrixIsIdentity = hasIdentityMatrix();
14627            if (matrixIsIdentity) {
14628                if (isHardwareAccelerated()) {
14629                    invalidateViewProperty(false, false);
14630                } else {
14631                    final ViewParent p = mParent;
14632                    if (p != null && mAttachInfo != null) {
14633                        final Rect r = mAttachInfo.mTmpInvalRect;
14634                        int minTop;
14635                        int maxBottom;
14636                        int yLoc;
14637                        if (offset < 0) {
14638                            minTop = mTop + offset;
14639                            maxBottom = mBottom;
14640                            yLoc = offset;
14641                        } else {
14642                            minTop = mTop;
14643                            maxBottom = mBottom + offset;
14644                            yLoc = 0;
14645                        }
14646                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14647                        p.invalidateChild(this, r);
14648                    }
14649                }
14650            } else {
14651                invalidateViewProperty(false, false);
14652            }
14653
14654            mTop += offset;
14655            mBottom += offset;
14656            mRenderNode.offsetTopAndBottom(offset);
14657            if (isHardwareAccelerated()) {
14658                invalidateViewProperty(false, false);
14659                invalidateParentIfNeededAndWasQuickRejected();
14660            } else {
14661                if (!matrixIsIdentity) {
14662                    invalidateViewProperty(false, true);
14663                }
14664                invalidateParentIfNeeded();
14665            }
14666            notifySubtreeAccessibilityStateChangedIfNeeded();
14667        }
14668    }
14669
14670    /**
14671     * Offset this view's horizontal location by the specified amount of pixels.
14672     *
14673     * @param offset the number of pixels to offset the view by
14674     */
14675    public void offsetLeftAndRight(int offset) {
14676        if (offset != 0) {
14677            final boolean matrixIsIdentity = hasIdentityMatrix();
14678            if (matrixIsIdentity) {
14679                if (isHardwareAccelerated()) {
14680                    invalidateViewProperty(false, false);
14681                } else {
14682                    final ViewParent p = mParent;
14683                    if (p != null && mAttachInfo != null) {
14684                        final Rect r = mAttachInfo.mTmpInvalRect;
14685                        int minLeft;
14686                        int maxRight;
14687                        if (offset < 0) {
14688                            minLeft = mLeft + offset;
14689                            maxRight = mRight;
14690                        } else {
14691                            minLeft = mLeft;
14692                            maxRight = mRight + offset;
14693                        }
14694                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14695                        p.invalidateChild(this, r);
14696                    }
14697                }
14698            } else {
14699                invalidateViewProperty(false, false);
14700            }
14701
14702            mLeft += offset;
14703            mRight += offset;
14704            mRenderNode.offsetLeftAndRight(offset);
14705            if (isHardwareAccelerated()) {
14706                invalidateViewProperty(false, false);
14707                invalidateParentIfNeededAndWasQuickRejected();
14708            } else {
14709                if (!matrixIsIdentity) {
14710                    invalidateViewProperty(false, true);
14711                }
14712                invalidateParentIfNeeded();
14713            }
14714            notifySubtreeAccessibilityStateChangedIfNeeded();
14715        }
14716    }
14717
14718    /**
14719     * Get the LayoutParams associated with this view. All views should have
14720     * layout parameters. These supply parameters to the <i>parent</i> of this
14721     * view specifying how it should be arranged. There are many subclasses of
14722     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14723     * of ViewGroup that are responsible for arranging their children.
14724     *
14725     * This method may return null if this View is not attached to a parent
14726     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14727     * was not invoked successfully. When a View is attached to a parent
14728     * ViewGroup, this method must not return null.
14729     *
14730     * @return The LayoutParams associated with this view, or null if no
14731     *         parameters have been set yet
14732     */
14733    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14734    public ViewGroup.LayoutParams getLayoutParams() {
14735        return mLayoutParams;
14736    }
14737
14738    /**
14739     * Set the layout parameters associated with this view. These supply
14740     * parameters to the <i>parent</i> of this view specifying how it should be
14741     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14742     * correspond to the different subclasses of ViewGroup that are responsible
14743     * for arranging their children.
14744     *
14745     * @param params The layout parameters for this view, cannot be null
14746     */
14747    public void setLayoutParams(ViewGroup.LayoutParams params) {
14748        if (params == null) {
14749            throw new NullPointerException("Layout parameters cannot be null");
14750        }
14751        mLayoutParams = params;
14752        resolveLayoutParams();
14753        if (mParent instanceof ViewGroup) {
14754            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14755        }
14756        requestLayout();
14757    }
14758
14759    /**
14760     * Resolve the layout parameters depending on the resolved layout direction
14761     *
14762     * @hide
14763     */
14764    public void resolveLayoutParams() {
14765        if (mLayoutParams != null) {
14766            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14767        }
14768    }
14769
14770    /**
14771     * Set the scrolled position of your view. This will cause a call to
14772     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14773     * invalidated.
14774     * @param x the x position to scroll to
14775     * @param y the y position to scroll to
14776     */
14777    public void scrollTo(int x, int y) {
14778        if (mScrollX != x || mScrollY != y) {
14779            int oldX = mScrollX;
14780            int oldY = mScrollY;
14781            mScrollX = x;
14782            mScrollY = y;
14783            invalidateParentCaches();
14784            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14785            if (!awakenScrollBars()) {
14786                postInvalidateOnAnimation();
14787            }
14788        }
14789    }
14790
14791    /**
14792     * Move the scrolled position of your view. This will cause a call to
14793     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14794     * invalidated.
14795     * @param x the amount of pixels to scroll by horizontally
14796     * @param y the amount of pixels to scroll by vertically
14797     */
14798    public void scrollBy(int x, int y) {
14799        scrollTo(mScrollX + x, mScrollY + y);
14800    }
14801
14802    /**
14803     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14804     * animation to fade the scrollbars out after a default delay. If a subclass
14805     * provides animated scrolling, the start delay should equal the duration
14806     * of the scrolling animation.</p>
14807     *
14808     * <p>The animation starts only if at least one of the scrollbars is
14809     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14810     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14811     * this method returns true, and false otherwise. If the animation is
14812     * started, this method calls {@link #invalidate()}; in that case the
14813     * caller should not call {@link #invalidate()}.</p>
14814     *
14815     * <p>This method should be invoked every time a subclass directly updates
14816     * the scroll parameters.</p>
14817     *
14818     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14819     * and {@link #scrollTo(int, int)}.</p>
14820     *
14821     * @return true if the animation is played, false otherwise
14822     *
14823     * @see #awakenScrollBars(int)
14824     * @see #scrollBy(int, int)
14825     * @see #scrollTo(int, int)
14826     * @see #isHorizontalScrollBarEnabled()
14827     * @see #isVerticalScrollBarEnabled()
14828     * @see #setHorizontalScrollBarEnabled(boolean)
14829     * @see #setVerticalScrollBarEnabled(boolean)
14830     */
14831    protected boolean awakenScrollBars() {
14832        return mScrollCache != null &&
14833                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14834    }
14835
14836    /**
14837     * Trigger the scrollbars to draw.
14838     * This method differs from awakenScrollBars() only in its default duration.
14839     * initialAwakenScrollBars() will show the scroll bars for longer than
14840     * usual to give the user more of a chance to notice them.
14841     *
14842     * @return true if the animation is played, false otherwise.
14843     */
14844    private boolean initialAwakenScrollBars() {
14845        return mScrollCache != null &&
14846                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14847    }
14848
14849    /**
14850     * <p>
14851     * Trigger the scrollbars to draw. When invoked this method starts an
14852     * animation to fade the scrollbars out after a fixed delay. If a subclass
14853     * provides animated scrolling, the start delay should equal the duration of
14854     * the scrolling animation.
14855     * </p>
14856     *
14857     * <p>
14858     * The animation starts only if at least one of the scrollbars is enabled,
14859     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14860     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14861     * this method returns true, and false otherwise. If the animation is
14862     * started, this method calls {@link #invalidate()}; in that case the caller
14863     * should not call {@link #invalidate()}.
14864     * </p>
14865     *
14866     * <p>
14867     * This method should be invoked every time a subclass directly updates the
14868     * scroll parameters.
14869     * </p>
14870     *
14871     * @param startDelay the delay, in milliseconds, after which the animation
14872     *        should start; when the delay is 0, the animation starts
14873     *        immediately
14874     * @return true if the animation is played, false otherwise
14875     *
14876     * @see #scrollBy(int, int)
14877     * @see #scrollTo(int, int)
14878     * @see #isHorizontalScrollBarEnabled()
14879     * @see #isVerticalScrollBarEnabled()
14880     * @see #setHorizontalScrollBarEnabled(boolean)
14881     * @see #setVerticalScrollBarEnabled(boolean)
14882     */
14883    protected boolean awakenScrollBars(int startDelay) {
14884        return awakenScrollBars(startDelay, true);
14885    }
14886
14887    /**
14888     * <p>
14889     * Trigger the scrollbars to draw. When invoked this method starts an
14890     * animation to fade the scrollbars out after a fixed delay. If a subclass
14891     * provides animated scrolling, the start delay should equal the duration of
14892     * the scrolling animation.
14893     * </p>
14894     *
14895     * <p>
14896     * The animation starts only if at least one of the scrollbars is enabled,
14897     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14898     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14899     * this method returns true, and false otherwise. If the animation is
14900     * started, this method calls {@link #invalidate()} if the invalidate parameter
14901     * is set to true; in that case the caller
14902     * should not call {@link #invalidate()}.
14903     * </p>
14904     *
14905     * <p>
14906     * This method should be invoked every time a subclass directly updates the
14907     * scroll parameters.
14908     * </p>
14909     *
14910     * @param startDelay the delay, in milliseconds, after which the animation
14911     *        should start; when the delay is 0, the animation starts
14912     *        immediately
14913     *
14914     * @param invalidate Whether this method should call invalidate
14915     *
14916     * @return true if the animation is played, false otherwise
14917     *
14918     * @see #scrollBy(int, int)
14919     * @see #scrollTo(int, int)
14920     * @see #isHorizontalScrollBarEnabled()
14921     * @see #isVerticalScrollBarEnabled()
14922     * @see #setHorizontalScrollBarEnabled(boolean)
14923     * @see #setVerticalScrollBarEnabled(boolean)
14924     */
14925    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14926        final ScrollabilityCache scrollCache = mScrollCache;
14927
14928        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14929            return false;
14930        }
14931
14932        if (scrollCache.scrollBar == null) {
14933            scrollCache.scrollBar = new ScrollBarDrawable();
14934            scrollCache.scrollBar.setState(getDrawableState());
14935            scrollCache.scrollBar.setCallback(this);
14936        }
14937
14938        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14939
14940            if (invalidate) {
14941                // Invalidate to show the scrollbars
14942                postInvalidateOnAnimation();
14943            }
14944
14945            if (scrollCache.state == ScrollabilityCache.OFF) {
14946                // FIXME: this is copied from WindowManagerService.
14947                // We should get this value from the system when it
14948                // is possible to do so.
14949                final int KEY_REPEAT_FIRST_DELAY = 750;
14950                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14951            }
14952
14953            // Tell mScrollCache when we should start fading. This may
14954            // extend the fade start time if one was already scheduled
14955            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14956            scrollCache.fadeStartTime = fadeStartTime;
14957            scrollCache.state = ScrollabilityCache.ON;
14958
14959            // Schedule our fader to run, unscheduling any old ones first
14960            if (mAttachInfo != null) {
14961                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14962                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14963            }
14964
14965            return true;
14966        }
14967
14968        return false;
14969    }
14970
14971    /**
14972     * Do not invalidate views which are not visible and which are not running an animation. They
14973     * will not get drawn and they should not set dirty flags as if they will be drawn
14974     */
14975    private boolean skipInvalidate() {
14976        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14977                (!(mParent instanceof ViewGroup) ||
14978                        !((ViewGroup) mParent).isViewTransitioning(this));
14979    }
14980
14981    /**
14982     * Mark the area defined by dirty as needing to be drawn. If the view is
14983     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14984     * point in the future.
14985     * <p>
14986     * This must be called from a UI thread. To call from a non-UI thread, call
14987     * {@link #postInvalidate()}.
14988     * <p>
14989     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14990     * {@code dirty}.
14991     *
14992     * @param dirty the rectangle representing the bounds of the dirty region
14993     */
14994    public void invalidate(Rect dirty) {
14995        final int scrollX = mScrollX;
14996        final int scrollY = mScrollY;
14997        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14998                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14999    }
15000
15001    /**
15002     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15003     * coordinates of the dirty rect are relative to the view. If the view is
15004     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15005     * point in the future.
15006     * <p>
15007     * This must be called from a UI thread. To call from a non-UI thread, call
15008     * {@link #postInvalidate()}.
15009     *
15010     * @param l the left position of the dirty region
15011     * @param t the top position of the dirty region
15012     * @param r the right position of the dirty region
15013     * @param b the bottom position of the dirty region
15014     */
15015    public void invalidate(int l, int t, int r, int b) {
15016        final int scrollX = mScrollX;
15017        final int scrollY = mScrollY;
15018        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15019    }
15020
15021    /**
15022     * Invalidate the whole view. If the view is visible,
15023     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15024     * the future.
15025     * <p>
15026     * This must be called from a UI thread. To call from a non-UI thread, call
15027     * {@link #postInvalidate()}.
15028     */
15029    public void invalidate() {
15030        invalidate(true);
15031    }
15032
15033    /**
15034     * This is where the invalidate() work actually happens. A full invalidate()
15035     * causes the drawing cache to be invalidated, but this function can be
15036     * called with invalidateCache set to false to skip that invalidation step
15037     * for cases that do not need it (for example, a component that remains at
15038     * the same dimensions with the same content).
15039     *
15040     * @param invalidateCache Whether the drawing cache for this view should be
15041     *            invalidated as well. This is usually true for a full
15042     *            invalidate, but may be set to false if the View's contents or
15043     *            dimensions have not changed.
15044     * @hide
15045     */
15046    public void invalidate(boolean invalidateCache) {
15047        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15048    }
15049
15050    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15051            boolean fullInvalidate) {
15052        if (mGhostView != null) {
15053            mGhostView.invalidate(true);
15054            return;
15055        }
15056
15057        if (skipInvalidate()) {
15058            return;
15059        }
15060
15061        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15062                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15063                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15064                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15065            if (fullInvalidate) {
15066                mLastIsOpaque = isOpaque();
15067                mPrivateFlags &= ~PFLAG_DRAWN;
15068            }
15069
15070            mPrivateFlags |= PFLAG_DIRTY;
15071
15072            if (invalidateCache) {
15073                mPrivateFlags |= PFLAG_INVALIDATED;
15074                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15075            }
15076
15077            // Propagate the damage rectangle to the parent view.
15078            final AttachInfo ai = mAttachInfo;
15079            final ViewParent p = mParent;
15080            if (p != null && ai != null && l < r && t < b) {
15081                final Rect damage = ai.mTmpInvalRect;
15082                damage.set(l, t, r, b);
15083                p.invalidateChild(this, damage);
15084            }
15085
15086            // Damage the entire projection receiver, if necessary.
15087            if (mBackground != null && mBackground.isProjected()) {
15088                final View receiver = getProjectionReceiver();
15089                if (receiver != null) {
15090                    receiver.damageInParent();
15091                }
15092            }
15093        }
15094    }
15095
15096    /**
15097     * @return this view's projection receiver, or {@code null} if none exists
15098     */
15099    private View getProjectionReceiver() {
15100        ViewParent p = getParent();
15101        while (p != null && p instanceof View) {
15102            final View v = (View) p;
15103            if (v.isProjectionReceiver()) {
15104                return v;
15105            }
15106            p = p.getParent();
15107        }
15108
15109        return null;
15110    }
15111
15112    /**
15113     * @return whether the view is a projection receiver
15114     */
15115    private boolean isProjectionReceiver() {
15116        return mBackground != null;
15117    }
15118
15119    /**
15120     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15121     * set any flags or handle all of the cases handled by the default invalidation methods.
15122     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15123     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15124     * walk up the hierarchy, transforming the dirty rect as necessary.
15125     *
15126     * The method also handles normal invalidation logic if display list properties are not
15127     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15128     * backup approach, to handle these cases used in the various property-setting methods.
15129     *
15130     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15131     * are not being used in this view
15132     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15133     * list properties are not being used in this view
15134     */
15135    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15136        if (!isHardwareAccelerated()
15137                || !mRenderNode.isValid()
15138                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15139            if (invalidateParent) {
15140                invalidateParentCaches();
15141            }
15142            if (forceRedraw) {
15143                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15144            }
15145            invalidate(false);
15146        } else {
15147            damageInParent();
15148        }
15149    }
15150
15151    /**
15152     * Tells the parent view to damage this view's bounds.
15153     *
15154     * @hide
15155     */
15156    protected void damageInParent() {
15157        if (mParent != null && mAttachInfo != null) {
15158            mParent.onDescendantInvalidated(this, this);
15159        }
15160    }
15161
15162    /**
15163     * Utility method to transform a given Rect by the current matrix of this view.
15164     */
15165    void transformRect(final Rect rect) {
15166        if (!getMatrix().isIdentity()) {
15167            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15168            boundingRect.set(rect);
15169            getMatrix().mapRect(boundingRect);
15170            rect.set((int) Math.floor(boundingRect.left),
15171                    (int) Math.floor(boundingRect.top),
15172                    (int) Math.ceil(boundingRect.right),
15173                    (int) Math.ceil(boundingRect.bottom));
15174        }
15175    }
15176
15177    /**
15178     * Used to indicate that the parent of this view should clear its caches. This functionality
15179     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15180     * which is necessary when various parent-managed properties of the view change, such as
15181     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15182     * clears the parent caches and does not causes an invalidate event.
15183     *
15184     * @hide
15185     */
15186    protected void invalidateParentCaches() {
15187        if (mParent instanceof View) {
15188            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15189        }
15190    }
15191
15192    /**
15193     * Used to indicate that the parent of this view should be invalidated. This functionality
15194     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15195     * which is necessary when various parent-managed properties of the view change, such as
15196     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15197     * an invalidation event to the parent.
15198     *
15199     * @hide
15200     */
15201    protected void invalidateParentIfNeeded() {
15202        if (isHardwareAccelerated() && mParent instanceof View) {
15203            ((View) mParent).invalidate(true);
15204        }
15205    }
15206
15207    /**
15208     * @hide
15209     */
15210    protected void invalidateParentIfNeededAndWasQuickRejected() {
15211        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15212            // View was rejected last time it was drawn by its parent; this may have changed
15213            invalidateParentIfNeeded();
15214        }
15215    }
15216
15217    /**
15218     * Indicates whether this View is opaque. An opaque View guarantees that it will
15219     * draw all the pixels overlapping its bounds using a fully opaque color.
15220     *
15221     * Subclasses of View should override this method whenever possible to indicate
15222     * whether an instance is opaque. Opaque Views are treated in a special way by
15223     * the View hierarchy, possibly allowing it to perform optimizations during
15224     * invalidate/draw passes.
15225     *
15226     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15227     */
15228    @ViewDebug.ExportedProperty(category = "drawing")
15229    public boolean isOpaque() {
15230        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15231                getFinalAlpha() >= 1.0f;
15232    }
15233
15234    /**
15235     * @hide
15236     */
15237    protected void computeOpaqueFlags() {
15238        // Opaque if:
15239        //   - Has a background
15240        //   - Background is opaque
15241        //   - Doesn't have scrollbars or scrollbars overlay
15242
15243        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15244            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15245        } else {
15246            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15247        }
15248
15249        final int flags = mViewFlags;
15250        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15251                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15252                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15253            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15254        } else {
15255            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15256        }
15257    }
15258
15259    /**
15260     * @hide
15261     */
15262    protected boolean hasOpaqueScrollbars() {
15263        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15264    }
15265
15266    /**
15267     * @return A handler associated with the thread running the View. This
15268     * handler can be used to pump events in the UI events queue.
15269     */
15270    public Handler getHandler() {
15271        final AttachInfo attachInfo = mAttachInfo;
15272        if (attachInfo != null) {
15273            return attachInfo.mHandler;
15274        }
15275        return null;
15276    }
15277
15278    /**
15279     * Returns the queue of runnable for this view.
15280     *
15281     * @return the queue of runnables for this view
15282     */
15283    private HandlerActionQueue getRunQueue() {
15284        if (mRunQueue == null) {
15285            mRunQueue = new HandlerActionQueue();
15286        }
15287        return mRunQueue;
15288    }
15289
15290    /**
15291     * Gets the view root associated with the View.
15292     * @return The view root, or null if none.
15293     * @hide
15294     */
15295    public ViewRootImpl getViewRootImpl() {
15296        if (mAttachInfo != null) {
15297            return mAttachInfo.mViewRootImpl;
15298        }
15299        return null;
15300    }
15301
15302    /**
15303     * @hide
15304     */
15305    public ThreadedRenderer getThreadedRenderer() {
15306        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15307    }
15308
15309    /**
15310     * <p>Causes the Runnable to be added to the message queue.
15311     * The runnable will be run on the user interface thread.</p>
15312     *
15313     * @param action The Runnable that will be executed.
15314     *
15315     * @return Returns true if the Runnable was successfully placed in to the
15316     *         message queue.  Returns false on failure, usually because the
15317     *         looper processing the message queue is exiting.
15318     *
15319     * @see #postDelayed
15320     * @see #removeCallbacks
15321     */
15322    public boolean post(Runnable action) {
15323        final AttachInfo attachInfo = mAttachInfo;
15324        if (attachInfo != null) {
15325            return attachInfo.mHandler.post(action);
15326        }
15327
15328        // Postpone the runnable until we know on which thread it needs to run.
15329        // Assume that the runnable will be successfully placed after attach.
15330        getRunQueue().post(action);
15331        return true;
15332    }
15333
15334    /**
15335     * <p>Causes the Runnable to be added to the message queue, to be run
15336     * after the specified amount of time elapses.
15337     * The runnable will be run on the user interface thread.</p>
15338     *
15339     * @param action The Runnable that will be executed.
15340     * @param delayMillis The delay (in milliseconds) until the Runnable
15341     *        will be executed.
15342     *
15343     * @return true if the Runnable was successfully placed in to the
15344     *         message queue.  Returns false on failure, usually because the
15345     *         looper processing the message queue is exiting.  Note that a
15346     *         result of true does not mean the Runnable will be processed --
15347     *         if the looper is quit before the delivery time of the message
15348     *         occurs then the message will be dropped.
15349     *
15350     * @see #post
15351     * @see #removeCallbacks
15352     */
15353    public boolean postDelayed(Runnable action, long delayMillis) {
15354        final AttachInfo attachInfo = mAttachInfo;
15355        if (attachInfo != null) {
15356            return attachInfo.mHandler.postDelayed(action, delayMillis);
15357        }
15358
15359        // Postpone the runnable until we know on which thread it needs to run.
15360        // Assume that the runnable will be successfully placed after attach.
15361        getRunQueue().postDelayed(action, delayMillis);
15362        return true;
15363    }
15364
15365    /**
15366     * <p>Causes the Runnable to execute on the next animation time step.
15367     * The runnable will be run on the user interface thread.</p>
15368     *
15369     * @param action The Runnable that will be executed.
15370     *
15371     * @see #postOnAnimationDelayed
15372     * @see #removeCallbacks
15373     */
15374    public void postOnAnimation(Runnable action) {
15375        final AttachInfo attachInfo = mAttachInfo;
15376        if (attachInfo != null) {
15377            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15378                    Choreographer.CALLBACK_ANIMATION, action, null);
15379        } else {
15380            // Postpone the runnable until we know
15381            // on which thread it needs to run.
15382            getRunQueue().post(action);
15383        }
15384    }
15385
15386    /**
15387     * <p>Causes the Runnable to execute on the next animation time step,
15388     * after the specified amount of time elapses.
15389     * The runnable will be run on the user interface thread.</p>
15390     *
15391     * @param action The Runnable that will be executed.
15392     * @param delayMillis The delay (in milliseconds) until the Runnable
15393     *        will be executed.
15394     *
15395     * @see #postOnAnimation
15396     * @see #removeCallbacks
15397     */
15398    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15399        final AttachInfo attachInfo = mAttachInfo;
15400        if (attachInfo != null) {
15401            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15402                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15403        } else {
15404            // Postpone the runnable until we know
15405            // on which thread it needs to run.
15406            getRunQueue().postDelayed(action, delayMillis);
15407        }
15408    }
15409
15410    /**
15411     * <p>Removes the specified Runnable from the message queue.</p>
15412     *
15413     * @param action The Runnable to remove from the message handling queue
15414     *
15415     * @return true if this view could ask the Handler to remove the Runnable,
15416     *         false otherwise. When the returned value is true, the Runnable
15417     *         may or may not have been actually removed from the message queue
15418     *         (for instance, if the Runnable was not in the queue already.)
15419     *
15420     * @see #post
15421     * @see #postDelayed
15422     * @see #postOnAnimation
15423     * @see #postOnAnimationDelayed
15424     */
15425    public boolean removeCallbacks(Runnable action) {
15426        if (action != null) {
15427            final AttachInfo attachInfo = mAttachInfo;
15428            if (attachInfo != null) {
15429                attachInfo.mHandler.removeCallbacks(action);
15430                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15431                        Choreographer.CALLBACK_ANIMATION, action, null);
15432            }
15433            getRunQueue().removeCallbacks(action);
15434        }
15435        return true;
15436    }
15437
15438    /**
15439     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15440     * Use this to invalidate the View from a non-UI thread.</p>
15441     *
15442     * <p>This method can be invoked from outside of the UI thread
15443     * only when this View is attached to a window.</p>
15444     *
15445     * @see #invalidate()
15446     * @see #postInvalidateDelayed(long)
15447     */
15448    public void postInvalidate() {
15449        postInvalidateDelayed(0);
15450    }
15451
15452    /**
15453     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15454     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15455     *
15456     * <p>This method can be invoked from outside of the UI thread
15457     * only when this View is attached to a window.</p>
15458     *
15459     * @param left The left coordinate of the rectangle to invalidate.
15460     * @param top The top coordinate of the rectangle to invalidate.
15461     * @param right The right coordinate of the rectangle to invalidate.
15462     * @param bottom The bottom coordinate of the rectangle to invalidate.
15463     *
15464     * @see #invalidate(int, int, int, int)
15465     * @see #invalidate(Rect)
15466     * @see #postInvalidateDelayed(long, int, int, int, int)
15467     */
15468    public void postInvalidate(int left, int top, int right, int bottom) {
15469        postInvalidateDelayed(0, left, top, right, bottom);
15470    }
15471
15472    /**
15473     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15474     * loop. Waits for the specified amount of time.</p>
15475     *
15476     * <p>This method can be invoked from outside of the UI thread
15477     * only when this View is attached to a window.</p>
15478     *
15479     * @param delayMilliseconds the duration in milliseconds to delay the
15480     *         invalidation by
15481     *
15482     * @see #invalidate()
15483     * @see #postInvalidate()
15484     */
15485    public void postInvalidateDelayed(long delayMilliseconds) {
15486        // We try only with the AttachInfo because there's no point in invalidating
15487        // if we are not attached to our window
15488        final AttachInfo attachInfo = mAttachInfo;
15489        if (attachInfo != null) {
15490            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15491        }
15492    }
15493
15494    /**
15495     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15496     * through the event loop. Waits for the specified amount of time.</p>
15497     *
15498     * <p>This method can be invoked from outside of the UI thread
15499     * only when this View is attached to a window.</p>
15500     *
15501     * @param delayMilliseconds the duration in milliseconds to delay the
15502     *         invalidation by
15503     * @param left The left coordinate of the rectangle to invalidate.
15504     * @param top The top coordinate of the rectangle to invalidate.
15505     * @param right The right coordinate of the rectangle to invalidate.
15506     * @param bottom The bottom coordinate of the rectangle to invalidate.
15507     *
15508     * @see #invalidate(int, int, int, int)
15509     * @see #invalidate(Rect)
15510     * @see #postInvalidate(int, int, int, int)
15511     */
15512    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15513            int right, int bottom) {
15514
15515        // We try only with the AttachInfo because there's no point in invalidating
15516        // if we are not attached to our window
15517        final AttachInfo attachInfo = mAttachInfo;
15518        if (attachInfo != null) {
15519            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15520            info.target = this;
15521            info.left = left;
15522            info.top = top;
15523            info.right = right;
15524            info.bottom = bottom;
15525
15526            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15527        }
15528    }
15529
15530    /**
15531     * <p>Cause an invalidate to happen on the next animation time step, typically the
15532     * next display frame.</p>
15533     *
15534     * <p>This method can be invoked from outside of the UI thread
15535     * only when this View is attached to a window.</p>
15536     *
15537     * @see #invalidate()
15538     */
15539    public void postInvalidateOnAnimation() {
15540        // We try only with the AttachInfo because there's no point in invalidating
15541        // if we are not attached to our window
15542        final AttachInfo attachInfo = mAttachInfo;
15543        if (attachInfo != null) {
15544            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15545        }
15546    }
15547
15548    /**
15549     * <p>Cause an invalidate of the specified area to happen on the next animation
15550     * time step, typically the next display frame.</p>
15551     *
15552     * <p>This method can be invoked from outside of the UI thread
15553     * only when this View is attached to a window.</p>
15554     *
15555     * @param left The left coordinate of the rectangle to invalidate.
15556     * @param top The top coordinate of the rectangle to invalidate.
15557     * @param right The right coordinate of the rectangle to invalidate.
15558     * @param bottom The bottom coordinate of the rectangle to invalidate.
15559     *
15560     * @see #invalidate(int, int, int, int)
15561     * @see #invalidate(Rect)
15562     */
15563    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15564        // We try only with the AttachInfo because there's no point in invalidating
15565        // if we are not attached to our window
15566        final AttachInfo attachInfo = mAttachInfo;
15567        if (attachInfo != null) {
15568            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15569            info.target = this;
15570            info.left = left;
15571            info.top = top;
15572            info.right = right;
15573            info.bottom = bottom;
15574
15575            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15576        }
15577    }
15578
15579    /**
15580     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15581     * This event is sent at most once every
15582     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15583     */
15584    private void postSendViewScrolledAccessibilityEventCallback() {
15585        if (mSendViewScrolledAccessibilityEvent == null) {
15586            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15587        }
15588        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15589            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15590            postDelayed(mSendViewScrolledAccessibilityEvent,
15591                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15592        }
15593    }
15594
15595    /**
15596     * Called by a parent to request that a child update its values for mScrollX
15597     * and mScrollY if necessary. This will typically be done if the child is
15598     * animating a scroll using a {@link android.widget.Scroller Scroller}
15599     * object.
15600     */
15601    public void computeScroll() {
15602    }
15603
15604    /**
15605     * <p>Indicate whether the horizontal edges are faded when the view is
15606     * scrolled horizontally.</p>
15607     *
15608     * @return true if the horizontal edges should are faded on scroll, false
15609     *         otherwise
15610     *
15611     * @see #setHorizontalFadingEdgeEnabled(boolean)
15612     *
15613     * @attr ref android.R.styleable#View_requiresFadingEdge
15614     */
15615    public boolean isHorizontalFadingEdgeEnabled() {
15616        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15617    }
15618
15619    /**
15620     * <p>Define whether the horizontal edges should be faded when this view
15621     * is scrolled horizontally.</p>
15622     *
15623     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15624     *                                    be faded when the view is scrolled
15625     *                                    horizontally
15626     *
15627     * @see #isHorizontalFadingEdgeEnabled()
15628     *
15629     * @attr ref android.R.styleable#View_requiresFadingEdge
15630     */
15631    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15632        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15633            if (horizontalFadingEdgeEnabled) {
15634                initScrollCache();
15635            }
15636
15637            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15638        }
15639    }
15640
15641    /**
15642     * <p>Indicate whether the vertical edges are faded when the view is
15643     * scrolled horizontally.</p>
15644     *
15645     * @return true if the vertical edges should are faded on scroll, false
15646     *         otherwise
15647     *
15648     * @see #setVerticalFadingEdgeEnabled(boolean)
15649     *
15650     * @attr ref android.R.styleable#View_requiresFadingEdge
15651     */
15652    public boolean isVerticalFadingEdgeEnabled() {
15653        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15654    }
15655
15656    /**
15657     * <p>Define whether the vertical edges should be faded when this view
15658     * is scrolled vertically.</p>
15659     *
15660     * @param verticalFadingEdgeEnabled true if the vertical edges should
15661     *                                  be faded when the view is scrolled
15662     *                                  vertically
15663     *
15664     * @see #isVerticalFadingEdgeEnabled()
15665     *
15666     * @attr ref android.R.styleable#View_requiresFadingEdge
15667     */
15668    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15669        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15670            if (verticalFadingEdgeEnabled) {
15671                initScrollCache();
15672            }
15673
15674            mViewFlags ^= FADING_EDGE_VERTICAL;
15675        }
15676    }
15677
15678    /**
15679     * Returns the strength, or intensity, of the top faded edge. The strength is
15680     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15681     * returns 0.0 or 1.0 but no value in between.
15682     *
15683     * Subclasses should override this method to provide a smoother fade transition
15684     * when scrolling occurs.
15685     *
15686     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15687     */
15688    protected float getTopFadingEdgeStrength() {
15689        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15690    }
15691
15692    /**
15693     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15694     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15695     * returns 0.0 or 1.0 but no value in between.
15696     *
15697     * Subclasses should override this method to provide a smoother fade transition
15698     * when scrolling occurs.
15699     *
15700     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15701     */
15702    protected float getBottomFadingEdgeStrength() {
15703        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15704                computeVerticalScrollRange() ? 1.0f : 0.0f;
15705    }
15706
15707    /**
15708     * Returns the strength, or intensity, of the left faded edge. The strength is
15709     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15710     * returns 0.0 or 1.0 but no value in between.
15711     *
15712     * Subclasses should override this method to provide a smoother fade transition
15713     * when scrolling occurs.
15714     *
15715     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15716     */
15717    protected float getLeftFadingEdgeStrength() {
15718        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15719    }
15720
15721    /**
15722     * Returns the strength, or intensity, of the right faded edge. The strength is
15723     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15724     * returns 0.0 or 1.0 but no value in between.
15725     *
15726     * Subclasses should override this method to provide a smoother fade transition
15727     * when scrolling occurs.
15728     *
15729     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15730     */
15731    protected float getRightFadingEdgeStrength() {
15732        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15733                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15734    }
15735
15736    /**
15737     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15738     * scrollbar is not drawn by default.</p>
15739     *
15740     * @return true if the horizontal scrollbar should be painted, false
15741     *         otherwise
15742     *
15743     * @see #setHorizontalScrollBarEnabled(boolean)
15744     */
15745    public boolean isHorizontalScrollBarEnabled() {
15746        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15747    }
15748
15749    /**
15750     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15751     * scrollbar is not drawn by default.</p>
15752     *
15753     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15754     *                                   be painted
15755     *
15756     * @see #isHorizontalScrollBarEnabled()
15757     */
15758    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15759        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15760            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15761            computeOpaqueFlags();
15762            resolvePadding();
15763        }
15764    }
15765
15766    /**
15767     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15768     * scrollbar is not drawn by default.</p>
15769     *
15770     * @return true if the vertical scrollbar should be painted, false
15771     *         otherwise
15772     *
15773     * @see #setVerticalScrollBarEnabled(boolean)
15774     */
15775    public boolean isVerticalScrollBarEnabled() {
15776        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15777    }
15778
15779    /**
15780     * <p>Define whether the vertical scrollbar should be drawn or not. The
15781     * scrollbar is not drawn by default.</p>
15782     *
15783     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15784     *                                 be painted
15785     *
15786     * @see #isVerticalScrollBarEnabled()
15787     */
15788    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15789        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15790            mViewFlags ^= SCROLLBARS_VERTICAL;
15791            computeOpaqueFlags();
15792            resolvePadding();
15793        }
15794    }
15795
15796    /**
15797     * @hide
15798     */
15799    protected void recomputePadding() {
15800        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15801    }
15802
15803    /**
15804     * Define whether scrollbars will fade when the view is not scrolling.
15805     *
15806     * @param fadeScrollbars whether to enable fading
15807     *
15808     * @attr ref android.R.styleable#View_fadeScrollbars
15809     */
15810    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15811        initScrollCache();
15812        final ScrollabilityCache scrollabilityCache = mScrollCache;
15813        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15814        if (fadeScrollbars) {
15815            scrollabilityCache.state = ScrollabilityCache.OFF;
15816        } else {
15817            scrollabilityCache.state = ScrollabilityCache.ON;
15818        }
15819    }
15820
15821    /**
15822     *
15823     * Returns true if scrollbars will fade when this view is not scrolling
15824     *
15825     * @return true if scrollbar fading is enabled
15826     *
15827     * @attr ref android.R.styleable#View_fadeScrollbars
15828     */
15829    public boolean isScrollbarFadingEnabled() {
15830        return mScrollCache != null && mScrollCache.fadeScrollBars;
15831    }
15832
15833    /**
15834     *
15835     * Returns the delay before scrollbars fade.
15836     *
15837     * @return the delay before scrollbars fade
15838     *
15839     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15840     */
15841    public int getScrollBarDefaultDelayBeforeFade() {
15842        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15843                mScrollCache.scrollBarDefaultDelayBeforeFade;
15844    }
15845
15846    /**
15847     * Define the delay before scrollbars fade.
15848     *
15849     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15850     *
15851     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15852     */
15853    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15854        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15855    }
15856
15857    /**
15858     *
15859     * Returns the scrollbar fade duration.
15860     *
15861     * @return the scrollbar fade duration, in milliseconds
15862     *
15863     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15864     */
15865    public int getScrollBarFadeDuration() {
15866        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15867                mScrollCache.scrollBarFadeDuration;
15868    }
15869
15870    /**
15871     * Define the scrollbar fade duration.
15872     *
15873     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15874     *
15875     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15876     */
15877    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15878        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15879    }
15880
15881    /**
15882     *
15883     * Returns the scrollbar size.
15884     *
15885     * @return the scrollbar size
15886     *
15887     * @attr ref android.R.styleable#View_scrollbarSize
15888     */
15889    public int getScrollBarSize() {
15890        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15891                mScrollCache.scrollBarSize;
15892    }
15893
15894    /**
15895     * Define the scrollbar size.
15896     *
15897     * @param scrollBarSize - the scrollbar size
15898     *
15899     * @attr ref android.R.styleable#View_scrollbarSize
15900     */
15901    public void setScrollBarSize(int scrollBarSize) {
15902        getScrollCache().scrollBarSize = scrollBarSize;
15903    }
15904
15905    /**
15906     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15907     * inset. When inset, they add to the padding of the view. And the scrollbars
15908     * can be drawn inside the padding area or on the edge of the view. For example,
15909     * if a view has a background drawable and you want to draw the scrollbars
15910     * inside the padding specified by the drawable, you can use
15911     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15912     * appear at the edge of the view, ignoring the padding, then you can use
15913     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15914     * @param style the style of the scrollbars. Should be one of
15915     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15916     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15917     * @see #SCROLLBARS_INSIDE_OVERLAY
15918     * @see #SCROLLBARS_INSIDE_INSET
15919     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15920     * @see #SCROLLBARS_OUTSIDE_INSET
15921     *
15922     * @attr ref android.R.styleable#View_scrollbarStyle
15923     */
15924    public void setScrollBarStyle(@ScrollBarStyle int style) {
15925        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15926            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15927            computeOpaqueFlags();
15928            resolvePadding();
15929        }
15930    }
15931
15932    /**
15933     * <p>Returns the current scrollbar style.</p>
15934     * @return the current scrollbar style
15935     * @see #SCROLLBARS_INSIDE_OVERLAY
15936     * @see #SCROLLBARS_INSIDE_INSET
15937     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15938     * @see #SCROLLBARS_OUTSIDE_INSET
15939     *
15940     * @attr ref android.R.styleable#View_scrollbarStyle
15941     */
15942    @ViewDebug.ExportedProperty(mapping = {
15943            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15944            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15945            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15946            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15947    })
15948    @ScrollBarStyle
15949    public int getScrollBarStyle() {
15950        return mViewFlags & SCROLLBARS_STYLE_MASK;
15951    }
15952
15953    /**
15954     * <p>Compute the horizontal range that the horizontal scrollbar
15955     * represents.</p>
15956     *
15957     * <p>The range is expressed in arbitrary units that must be the same as the
15958     * units used by {@link #computeHorizontalScrollExtent()} and
15959     * {@link #computeHorizontalScrollOffset()}.</p>
15960     *
15961     * <p>The default range is the drawing width of this view.</p>
15962     *
15963     * @return the total horizontal range represented by the horizontal
15964     *         scrollbar
15965     *
15966     * @see #computeHorizontalScrollExtent()
15967     * @see #computeHorizontalScrollOffset()
15968     * @see android.widget.ScrollBarDrawable
15969     */
15970    protected int computeHorizontalScrollRange() {
15971        return getWidth();
15972    }
15973
15974    /**
15975     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15976     * within the horizontal range. This value is used to compute the position
15977     * of the thumb within the scrollbar's track.</p>
15978     *
15979     * <p>The range is expressed in arbitrary units that must be the same as the
15980     * units used by {@link #computeHorizontalScrollRange()} and
15981     * {@link #computeHorizontalScrollExtent()}.</p>
15982     *
15983     * <p>The default offset is the scroll offset of this view.</p>
15984     *
15985     * @return the horizontal offset of the scrollbar's thumb
15986     *
15987     * @see #computeHorizontalScrollRange()
15988     * @see #computeHorizontalScrollExtent()
15989     * @see android.widget.ScrollBarDrawable
15990     */
15991    protected int computeHorizontalScrollOffset() {
15992        return mScrollX;
15993    }
15994
15995    /**
15996     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15997     * within the horizontal range. This value is used to compute the length
15998     * of the thumb within the scrollbar's track.</p>
15999     *
16000     * <p>The range is expressed in arbitrary units that must be the same as the
16001     * units used by {@link #computeHorizontalScrollRange()} and
16002     * {@link #computeHorizontalScrollOffset()}.</p>
16003     *
16004     * <p>The default extent is the drawing width of this view.</p>
16005     *
16006     * @return the horizontal extent of the scrollbar's thumb
16007     *
16008     * @see #computeHorizontalScrollRange()
16009     * @see #computeHorizontalScrollOffset()
16010     * @see android.widget.ScrollBarDrawable
16011     */
16012    protected int computeHorizontalScrollExtent() {
16013        return getWidth();
16014    }
16015
16016    /**
16017     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16018     *
16019     * <p>The range is expressed in arbitrary units that must be the same as the
16020     * units used by {@link #computeVerticalScrollExtent()} and
16021     * {@link #computeVerticalScrollOffset()}.</p>
16022     *
16023     * @return the total vertical range represented by the vertical scrollbar
16024     *
16025     * <p>The default range is the drawing height of this view.</p>
16026     *
16027     * @see #computeVerticalScrollExtent()
16028     * @see #computeVerticalScrollOffset()
16029     * @see android.widget.ScrollBarDrawable
16030     */
16031    protected int computeVerticalScrollRange() {
16032        return getHeight();
16033    }
16034
16035    /**
16036     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16037     * within the horizontal range. This value is used to compute the position
16038     * of the thumb within the scrollbar's track.</p>
16039     *
16040     * <p>The range is expressed in arbitrary units that must be the same as the
16041     * units used by {@link #computeVerticalScrollRange()} and
16042     * {@link #computeVerticalScrollExtent()}.</p>
16043     *
16044     * <p>The default offset is the scroll offset of this view.</p>
16045     *
16046     * @return the vertical offset of the scrollbar's thumb
16047     *
16048     * @see #computeVerticalScrollRange()
16049     * @see #computeVerticalScrollExtent()
16050     * @see android.widget.ScrollBarDrawable
16051     */
16052    protected int computeVerticalScrollOffset() {
16053        return mScrollY;
16054    }
16055
16056    /**
16057     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16058     * within the vertical range. This value is used to compute the length
16059     * of the thumb within the scrollbar's track.</p>
16060     *
16061     * <p>The range is expressed in arbitrary units that must be the same as the
16062     * units used by {@link #computeVerticalScrollRange()} and
16063     * {@link #computeVerticalScrollOffset()}.</p>
16064     *
16065     * <p>The default extent is the drawing height of this view.</p>
16066     *
16067     * @return the vertical extent of the scrollbar's thumb
16068     *
16069     * @see #computeVerticalScrollRange()
16070     * @see #computeVerticalScrollOffset()
16071     * @see android.widget.ScrollBarDrawable
16072     */
16073    protected int computeVerticalScrollExtent() {
16074        return getHeight();
16075    }
16076
16077    /**
16078     * Check if this view can be scrolled horizontally in a certain direction.
16079     *
16080     * @param direction Negative to check scrolling left, positive to check scrolling right.
16081     * @return true if this view can be scrolled in the specified direction, false otherwise.
16082     */
16083    public boolean canScrollHorizontally(int direction) {
16084        final int offset = computeHorizontalScrollOffset();
16085        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16086        if (range == 0) return false;
16087        if (direction < 0) {
16088            return offset > 0;
16089        } else {
16090            return offset < range - 1;
16091        }
16092    }
16093
16094    /**
16095     * Check if this view can be scrolled vertically in a certain direction.
16096     *
16097     * @param direction Negative to check scrolling up, positive to check scrolling down.
16098     * @return true if this view can be scrolled in the specified direction, false otherwise.
16099     */
16100    public boolean canScrollVertically(int direction) {
16101        final int offset = computeVerticalScrollOffset();
16102        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16103        if (range == 0) return false;
16104        if (direction < 0) {
16105            return offset > 0;
16106        } else {
16107            return offset < range - 1;
16108        }
16109    }
16110
16111    void getScrollIndicatorBounds(@NonNull Rect out) {
16112        out.left = mScrollX;
16113        out.right = mScrollX + mRight - mLeft;
16114        out.top = mScrollY;
16115        out.bottom = mScrollY + mBottom - mTop;
16116    }
16117
16118    private void onDrawScrollIndicators(Canvas c) {
16119        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16120            // No scroll indicators enabled.
16121            return;
16122        }
16123
16124        final Drawable dr = mScrollIndicatorDrawable;
16125        if (dr == null) {
16126            // Scroll indicators aren't supported here.
16127            return;
16128        }
16129
16130        final int h = dr.getIntrinsicHeight();
16131        final int w = dr.getIntrinsicWidth();
16132        final Rect rect = mAttachInfo.mTmpInvalRect;
16133        getScrollIndicatorBounds(rect);
16134
16135        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16136            final boolean canScrollUp = canScrollVertically(-1);
16137            if (canScrollUp) {
16138                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16139                dr.draw(c);
16140            }
16141        }
16142
16143        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16144            final boolean canScrollDown = canScrollVertically(1);
16145            if (canScrollDown) {
16146                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16147                dr.draw(c);
16148            }
16149        }
16150
16151        final int leftRtl;
16152        final int rightRtl;
16153        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16154            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16155            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16156        } else {
16157            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16158            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16159        }
16160
16161        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16162        if ((mPrivateFlags3 & leftMask) != 0) {
16163            final boolean canScrollLeft = canScrollHorizontally(-1);
16164            if (canScrollLeft) {
16165                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16166                dr.draw(c);
16167            }
16168        }
16169
16170        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16171        if ((mPrivateFlags3 & rightMask) != 0) {
16172            final boolean canScrollRight = canScrollHorizontally(1);
16173            if (canScrollRight) {
16174                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16175                dr.draw(c);
16176            }
16177        }
16178    }
16179
16180    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16181            @Nullable Rect touchBounds) {
16182        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16183        if (bounds == null) {
16184            return;
16185        }
16186        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16187        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16188                && !isVerticalScrollBarHidden();
16189        final int size = getHorizontalScrollbarHeight();
16190        final int verticalScrollBarGap = drawVerticalScrollBar ?
16191                getVerticalScrollbarWidth() : 0;
16192        final int width = mRight - mLeft;
16193        final int height = mBottom - mTop;
16194        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16195        bounds.left = mScrollX + (mPaddingLeft & inside);
16196        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16197        bounds.bottom = bounds.top + size;
16198
16199        if (touchBounds == null) {
16200            return;
16201        }
16202        if (touchBounds != bounds) {
16203            touchBounds.set(bounds);
16204        }
16205        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16206        if (touchBounds.height() < minTouchTarget) {
16207            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16208            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16209            touchBounds.top = touchBounds.bottom - minTouchTarget;
16210        }
16211        if (touchBounds.width() < minTouchTarget) {
16212            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16213            touchBounds.left -= adjust;
16214            touchBounds.right = touchBounds.left + minTouchTarget;
16215        }
16216    }
16217
16218    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16219        if (mRoundScrollbarRenderer == null) {
16220            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16221        } else {
16222            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16223        }
16224    }
16225
16226    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16227        final int width = mRight - mLeft;
16228        final int height = mBottom - mTop;
16229        // Do not take padding into account as we always want the scrollbars
16230        // to hug the screen for round wearable devices.
16231        bounds.left = mScrollX;
16232        bounds.top = mScrollY;
16233        bounds.right = bounds.left + width;
16234        bounds.bottom = mScrollY + height;
16235    }
16236
16237    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16238            @Nullable Rect touchBounds) {
16239        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16240        if (bounds == null) {
16241            return;
16242        }
16243        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16244        final int size = getVerticalScrollbarWidth();
16245        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16246        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16247            verticalScrollbarPosition = isLayoutRtl() ?
16248                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16249        }
16250        final int width = mRight - mLeft;
16251        final int height = mBottom - mTop;
16252        switch (verticalScrollbarPosition) {
16253            default:
16254            case SCROLLBAR_POSITION_RIGHT:
16255                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16256                break;
16257            case SCROLLBAR_POSITION_LEFT:
16258                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16259                break;
16260        }
16261        bounds.top = mScrollY + (mPaddingTop & inside);
16262        bounds.right = bounds.left + size;
16263        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16264
16265        if (touchBounds == null) {
16266            return;
16267        }
16268        if (touchBounds != bounds) {
16269            touchBounds.set(bounds);
16270        }
16271        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16272        if (touchBounds.width() < minTouchTarget) {
16273            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16274            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16275                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16276                touchBounds.left = touchBounds.right - minTouchTarget;
16277            } else {
16278                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16279                touchBounds.right = touchBounds.left + minTouchTarget;
16280            }
16281        }
16282        if (touchBounds.height() < minTouchTarget) {
16283            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16284            touchBounds.top -= adjust;
16285            touchBounds.bottom = touchBounds.top + minTouchTarget;
16286        }
16287    }
16288
16289    /**
16290     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16291     * scrollbars are painted only if they have been awakened first.</p>
16292     *
16293     * @param canvas the canvas on which to draw the scrollbars
16294     *
16295     * @see #awakenScrollBars(int)
16296     */
16297    protected final void onDrawScrollBars(Canvas canvas) {
16298        // scrollbars are drawn only when the animation is running
16299        final ScrollabilityCache cache = mScrollCache;
16300
16301        if (cache != null) {
16302
16303            int state = cache.state;
16304
16305            if (state == ScrollabilityCache.OFF) {
16306                return;
16307            }
16308
16309            boolean invalidate = false;
16310
16311            if (state == ScrollabilityCache.FADING) {
16312                // We're fading -- get our fade interpolation
16313                if (cache.interpolatorValues == null) {
16314                    cache.interpolatorValues = new float[1];
16315                }
16316
16317                float[] values = cache.interpolatorValues;
16318
16319                // Stops the animation if we're done
16320                if (cache.scrollBarInterpolator.timeToValues(values) ==
16321                        Interpolator.Result.FREEZE_END) {
16322                    cache.state = ScrollabilityCache.OFF;
16323                } else {
16324                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16325                }
16326
16327                // This will make the scroll bars inval themselves after
16328                // drawing. We only want this when we're fading so that
16329                // we prevent excessive redraws
16330                invalidate = true;
16331            } else {
16332                // We're just on -- but we may have been fading before so
16333                // reset alpha
16334                cache.scrollBar.mutate().setAlpha(255);
16335            }
16336
16337            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16338            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16339                    && !isVerticalScrollBarHidden();
16340
16341            // Fork out the scroll bar drawing for round wearable devices.
16342            if (mRoundScrollbarRenderer != null) {
16343                if (drawVerticalScrollBar) {
16344                    final Rect bounds = cache.mScrollBarBounds;
16345                    getVerticalScrollBarBounds(bounds, null);
16346                    mRoundScrollbarRenderer.drawRoundScrollbars(
16347                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16348                    if (invalidate) {
16349                        invalidate();
16350                    }
16351                }
16352                // Do not draw horizontal scroll bars for round wearable devices.
16353            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16354                final ScrollBarDrawable scrollBar = cache.scrollBar;
16355
16356                if (drawHorizontalScrollBar) {
16357                    scrollBar.setParameters(computeHorizontalScrollRange(),
16358                            computeHorizontalScrollOffset(),
16359                            computeHorizontalScrollExtent(), false);
16360                    final Rect bounds = cache.mScrollBarBounds;
16361                    getHorizontalScrollBarBounds(bounds, null);
16362                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16363                            bounds.right, bounds.bottom);
16364                    if (invalidate) {
16365                        invalidate(bounds);
16366                    }
16367                }
16368
16369                if (drawVerticalScrollBar) {
16370                    scrollBar.setParameters(computeVerticalScrollRange(),
16371                            computeVerticalScrollOffset(),
16372                            computeVerticalScrollExtent(), true);
16373                    final Rect bounds = cache.mScrollBarBounds;
16374                    getVerticalScrollBarBounds(bounds, null);
16375                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16376                            bounds.right, bounds.bottom);
16377                    if (invalidate) {
16378                        invalidate(bounds);
16379                    }
16380                }
16381            }
16382        }
16383    }
16384
16385    /**
16386     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16387     * FastScroller is visible.
16388     * @return whether to temporarily hide the vertical scrollbar
16389     * @hide
16390     */
16391    protected boolean isVerticalScrollBarHidden() {
16392        return false;
16393    }
16394
16395    /**
16396     * <p>Draw the horizontal scrollbar if
16397     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16398     *
16399     * @param canvas the canvas on which to draw the scrollbar
16400     * @param scrollBar the scrollbar's drawable
16401     *
16402     * @see #isHorizontalScrollBarEnabled()
16403     * @see #computeHorizontalScrollRange()
16404     * @see #computeHorizontalScrollExtent()
16405     * @see #computeHorizontalScrollOffset()
16406     * @see android.widget.ScrollBarDrawable
16407     * @hide
16408     */
16409    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16410            int l, int t, int r, int b) {
16411        scrollBar.setBounds(l, t, r, b);
16412        scrollBar.draw(canvas);
16413    }
16414
16415    /**
16416     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16417     * returns true.</p>
16418     *
16419     * @param canvas the canvas on which to draw the scrollbar
16420     * @param scrollBar the scrollbar's drawable
16421     *
16422     * @see #isVerticalScrollBarEnabled()
16423     * @see #computeVerticalScrollRange()
16424     * @see #computeVerticalScrollExtent()
16425     * @see #computeVerticalScrollOffset()
16426     * @see android.widget.ScrollBarDrawable
16427     * @hide
16428     */
16429    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16430            int l, int t, int r, int b) {
16431        scrollBar.setBounds(l, t, r, b);
16432        scrollBar.draw(canvas);
16433    }
16434
16435    /**
16436     * Implement this to do your drawing.
16437     *
16438     * @param canvas the canvas on which the background will be drawn
16439     */
16440    protected void onDraw(Canvas canvas) {
16441    }
16442
16443    /*
16444     * Caller is responsible for calling requestLayout if necessary.
16445     * (This allows addViewInLayout to not request a new layout.)
16446     */
16447    void assignParent(ViewParent parent) {
16448        if (mParent == null) {
16449            mParent = parent;
16450        } else if (parent == null) {
16451            mParent = null;
16452        } else {
16453            throw new RuntimeException("view " + this + " being added, but"
16454                    + " it already has a parent");
16455        }
16456    }
16457
16458    /**
16459     * This is called when the view is attached to a window.  At this point it
16460     * has a Surface and will start drawing.  Note that this function is
16461     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16462     * however it may be called any time before the first onDraw -- including
16463     * before or after {@link #onMeasure(int, int)}.
16464     *
16465     * @see #onDetachedFromWindow()
16466     */
16467    @CallSuper
16468    protected void onAttachedToWindow() {
16469        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16470            mParent.requestTransparentRegion(this);
16471        }
16472
16473        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16474
16475        jumpDrawablesToCurrentState();
16476
16477        resetSubtreeAccessibilityStateChanged();
16478
16479        // rebuild, since Outline not maintained while View is detached
16480        rebuildOutline();
16481
16482        if (isFocused()) {
16483            InputMethodManager imm = InputMethodManager.peekInstance();
16484            if (imm != null) {
16485                imm.focusIn(this);
16486            }
16487        }
16488    }
16489
16490    /**
16491     * Resolve all RTL related properties.
16492     *
16493     * @return true if resolution of RTL properties has been done
16494     *
16495     * @hide
16496     */
16497    public boolean resolveRtlPropertiesIfNeeded() {
16498        if (!needRtlPropertiesResolution()) return false;
16499
16500        // Order is important here: LayoutDirection MUST be resolved first
16501        if (!isLayoutDirectionResolved()) {
16502            resolveLayoutDirection();
16503            resolveLayoutParams();
16504        }
16505        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16506        if (!isTextDirectionResolved()) {
16507            resolveTextDirection();
16508        }
16509        if (!isTextAlignmentResolved()) {
16510            resolveTextAlignment();
16511        }
16512        // Should resolve Drawables before Padding because we need the layout direction of the
16513        // Drawable to correctly resolve Padding.
16514        if (!areDrawablesResolved()) {
16515            resolveDrawables();
16516        }
16517        if (!isPaddingResolved()) {
16518            resolvePadding();
16519        }
16520        onRtlPropertiesChanged(getLayoutDirection());
16521        return true;
16522    }
16523
16524    /**
16525     * Reset resolution of all RTL related properties.
16526     *
16527     * @hide
16528     */
16529    public void resetRtlProperties() {
16530        resetResolvedLayoutDirection();
16531        resetResolvedTextDirection();
16532        resetResolvedTextAlignment();
16533        resetResolvedPadding();
16534        resetResolvedDrawables();
16535    }
16536
16537    /**
16538     * @see #onScreenStateChanged(int)
16539     */
16540    void dispatchScreenStateChanged(int screenState) {
16541        onScreenStateChanged(screenState);
16542    }
16543
16544    /**
16545     * This method is called whenever the state of the screen this view is
16546     * attached to changes. A state change will usually occurs when the screen
16547     * turns on or off (whether it happens automatically or the user does it
16548     * manually.)
16549     *
16550     * @param screenState The new state of the screen. Can be either
16551     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16552     */
16553    public void onScreenStateChanged(int screenState) {
16554    }
16555
16556    /**
16557     * @see #onMovedToDisplay(int, Configuration)
16558     */
16559    void dispatchMovedToDisplay(Display display, Configuration config) {
16560        mAttachInfo.mDisplay = display;
16561        mAttachInfo.mDisplayState = display.getState();
16562        onMovedToDisplay(display.getDisplayId(), config);
16563    }
16564
16565    /**
16566     * Called by the system when the hosting activity is moved from one display to another without
16567     * recreation. This means that the activity is declared to handle all changes to configuration
16568     * that happened when it was switched to another display, so it wasn't destroyed and created
16569     * again.
16570     *
16571     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16572     * applied configuration actually changed. It is up to app developer to choose whether to handle
16573     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16574     * call.
16575     *
16576     * <p>Use this callback to track changes to the displays if some functionality relies on an
16577     * association with some display properties.
16578     *
16579     * @param displayId The id of the display to which the view was moved.
16580     * @param config Configuration of the resources on new display after move.
16581     *
16582     * @see #onConfigurationChanged(Configuration)
16583     */
16584    public void onMovedToDisplay(int displayId, Configuration config) {
16585    }
16586
16587    /**
16588     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16589     */
16590    private boolean hasRtlSupport() {
16591        return mContext.getApplicationInfo().hasRtlSupport();
16592    }
16593
16594    /**
16595     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16596     * RTL not supported)
16597     */
16598    private boolean isRtlCompatibilityMode() {
16599        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16600        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16601    }
16602
16603    /**
16604     * @return true if RTL properties need resolution.
16605     *
16606     */
16607    private boolean needRtlPropertiesResolution() {
16608        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16609    }
16610
16611    /**
16612     * Called when any RTL property (layout direction or text direction or text alignment) has
16613     * been changed.
16614     *
16615     * Subclasses need to override this method to take care of cached information that depends on the
16616     * resolved layout direction, or to inform child views that inherit their layout direction.
16617     *
16618     * The default implementation does nothing.
16619     *
16620     * @param layoutDirection the direction of the layout
16621     *
16622     * @see #LAYOUT_DIRECTION_LTR
16623     * @see #LAYOUT_DIRECTION_RTL
16624     */
16625    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16626    }
16627
16628    /**
16629     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16630     * that the parent directionality can and will be resolved before its children.
16631     *
16632     * @return true if resolution has been done, false otherwise.
16633     *
16634     * @hide
16635     */
16636    public boolean resolveLayoutDirection() {
16637        // Clear any previous layout direction resolution
16638        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16639
16640        if (hasRtlSupport()) {
16641            // Set resolved depending on layout direction
16642            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16643                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16644                case LAYOUT_DIRECTION_INHERIT:
16645                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16646                    // later to get the correct resolved value
16647                    if (!canResolveLayoutDirection()) return false;
16648
16649                    // Parent has not yet resolved, LTR is still the default
16650                    try {
16651                        if (!mParent.isLayoutDirectionResolved()) return false;
16652
16653                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16654                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16655                        }
16656                    } catch (AbstractMethodError e) {
16657                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16658                                " does not fully implement ViewParent", e);
16659                    }
16660                    break;
16661                case LAYOUT_DIRECTION_RTL:
16662                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16663                    break;
16664                case LAYOUT_DIRECTION_LOCALE:
16665                    if((LAYOUT_DIRECTION_RTL ==
16666                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16667                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16668                    }
16669                    break;
16670                default:
16671                    // Nothing to do, LTR by default
16672            }
16673        }
16674
16675        // Set to resolved
16676        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16677        return true;
16678    }
16679
16680    /**
16681     * Check if layout direction resolution can be done.
16682     *
16683     * @return true if layout direction resolution can be done otherwise return false.
16684     */
16685    public boolean canResolveLayoutDirection() {
16686        switch (getRawLayoutDirection()) {
16687            case LAYOUT_DIRECTION_INHERIT:
16688                if (mParent != null) {
16689                    try {
16690                        return mParent.canResolveLayoutDirection();
16691                    } catch (AbstractMethodError e) {
16692                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16693                                " does not fully implement ViewParent", e);
16694                    }
16695                }
16696                return false;
16697
16698            default:
16699                return true;
16700        }
16701    }
16702
16703    /**
16704     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16705     * {@link #onMeasure(int, int)}.
16706     *
16707     * @hide
16708     */
16709    public void resetResolvedLayoutDirection() {
16710        // Reset the current resolved bits
16711        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16712    }
16713
16714    /**
16715     * @return true if the layout direction is inherited.
16716     *
16717     * @hide
16718     */
16719    public boolean isLayoutDirectionInherited() {
16720        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16721    }
16722
16723    /**
16724     * @return true if layout direction has been resolved.
16725     */
16726    public boolean isLayoutDirectionResolved() {
16727        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16728    }
16729
16730    /**
16731     * Return if padding has been resolved
16732     *
16733     * @hide
16734     */
16735    boolean isPaddingResolved() {
16736        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16737    }
16738
16739    /**
16740     * Resolves padding depending on layout direction, if applicable, and
16741     * recomputes internal padding values to adjust for scroll bars.
16742     *
16743     * @hide
16744     */
16745    public void resolvePadding() {
16746        final int resolvedLayoutDirection = getLayoutDirection();
16747
16748        if (!isRtlCompatibilityMode()) {
16749            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16750            // If start / end padding are defined, they will be resolved (hence overriding) to
16751            // left / right or right / left depending on the resolved layout direction.
16752            // If start / end padding are not defined, use the left / right ones.
16753            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16754                Rect padding = sThreadLocal.get();
16755                if (padding == null) {
16756                    padding = new Rect();
16757                    sThreadLocal.set(padding);
16758                }
16759                mBackground.getPadding(padding);
16760                if (!mLeftPaddingDefined) {
16761                    mUserPaddingLeftInitial = padding.left;
16762                }
16763                if (!mRightPaddingDefined) {
16764                    mUserPaddingRightInitial = padding.right;
16765                }
16766            }
16767            switch (resolvedLayoutDirection) {
16768                case LAYOUT_DIRECTION_RTL:
16769                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16770                        mUserPaddingRight = mUserPaddingStart;
16771                    } else {
16772                        mUserPaddingRight = mUserPaddingRightInitial;
16773                    }
16774                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16775                        mUserPaddingLeft = mUserPaddingEnd;
16776                    } else {
16777                        mUserPaddingLeft = mUserPaddingLeftInitial;
16778                    }
16779                    break;
16780                case LAYOUT_DIRECTION_LTR:
16781                default:
16782                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16783                        mUserPaddingLeft = mUserPaddingStart;
16784                    } else {
16785                        mUserPaddingLeft = mUserPaddingLeftInitial;
16786                    }
16787                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16788                        mUserPaddingRight = mUserPaddingEnd;
16789                    } else {
16790                        mUserPaddingRight = mUserPaddingRightInitial;
16791                    }
16792            }
16793
16794            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16795        }
16796
16797        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16798        onRtlPropertiesChanged(resolvedLayoutDirection);
16799
16800        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16801    }
16802
16803    /**
16804     * Reset the resolved layout direction.
16805     *
16806     * @hide
16807     */
16808    public void resetResolvedPadding() {
16809        resetResolvedPaddingInternal();
16810    }
16811
16812    /**
16813     * Used when we only want to reset *this* view's padding and not trigger overrides
16814     * in ViewGroup that reset children too.
16815     */
16816    void resetResolvedPaddingInternal() {
16817        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16818    }
16819
16820    /**
16821     * This is called when the view is detached from a window.  At this point it
16822     * no longer has a surface for drawing.
16823     *
16824     * @see #onAttachedToWindow()
16825     */
16826    @CallSuper
16827    protected void onDetachedFromWindow() {
16828    }
16829
16830    /**
16831     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16832     * after onDetachedFromWindow().
16833     *
16834     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16835     * The super method should be called at the end of the overridden method to ensure
16836     * subclasses are destroyed first
16837     *
16838     * @hide
16839     */
16840    @CallSuper
16841    protected void onDetachedFromWindowInternal() {
16842        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16843        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16844        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16845
16846        removeUnsetPressCallback();
16847        removeLongPressCallback();
16848        removePerformClickCallback();
16849        removeSendViewScrolledAccessibilityEventCallback();
16850        stopNestedScroll();
16851
16852        // Anything that started animating right before detach should already
16853        // be in its final state when re-attached.
16854        jumpDrawablesToCurrentState();
16855
16856        destroyDrawingCache();
16857
16858        cleanupDraw();
16859        mCurrentAnimation = null;
16860
16861        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16862            hideTooltip();
16863        }
16864    }
16865
16866    private void cleanupDraw() {
16867        resetDisplayList();
16868        if (mAttachInfo != null) {
16869            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16870        }
16871    }
16872
16873    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16874    }
16875
16876    /**
16877     * @return The number of times this view has been attached to a window
16878     */
16879    protected int getWindowAttachCount() {
16880        return mWindowAttachCount;
16881    }
16882
16883    /**
16884     * Retrieve a unique token identifying the window this view is attached to.
16885     * @return Return the window's token for use in
16886     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16887     */
16888    public IBinder getWindowToken() {
16889        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16890    }
16891
16892    /**
16893     * Retrieve the {@link WindowId} for the window this view is
16894     * currently attached to.
16895     */
16896    public WindowId getWindowId() {
16897        if (mAttachInfo == null) {
16898            return null;
16899        }
16900        if (mAttachInfo.mWindowId == null) {
16901            try {
16902                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16903                        mAttachInfo.mWindowToken);
16904                mAttachInfo.mWindowId = new WindowId(
16905                        mAttachInfo.mIWindowId);
16906            } catch (RemoteException e) {
16907            }
16908        }
16909        return mAttachInfo.mWindowId;
16910    }
16911
16912    /**
16913     * Retrieve a unique token identifying the top-level "real" window of
16914     * the window that this view is attached to.  That is, this is like
16915     * {@link #getWindowToken}, except if the window this view in is a panel
16916     * window (attached to another containing window), then the token of
16917     * the containing window is returned instead.
16918     *
16919     * @return Returns the associated window token, either
16920     * {@link #getWindowToken()} or the containing window's token.
16921     */
16922    public IBinder getApplicationWindowToken() {
16923        AttachInfo ai = mAttachInfo;
16924        if (ai != null) {
16925            IBinder appWindowToken = ai.mPanelParentWindowToken;
16926            if (appWindowToken == null) {
16927                appWindowToken = ai.mWindowToken;
16928            }
16929            return appWindowToken;
16930        }
16931        return null;
16932    }
16933
16934    /**
16935     * Gets the logical display to which the view's window has been attached.
16936     *
16937     * @return The logical display, or null if the view is not currently attached to a window.
16938     */
16939    public Display getDisplay() {
16940        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16941    }
16942
16943    /**
16944     * Retrieve private session object this view hierarchy is using to
16945     * communicate with the window manager.
16946     * @return the session object to communicate with the window manager
16947     */
16948    /*package*/ IWindowSession getWindowSession() {
16949        return mAttachInfo != null ? mAttachInfo.mSession : null;
16950    }
16951
16952    /**
16953     * Return the visibility value of the least visible component passed.
16954     */
16955    int combineVisibility(int vis1, int vis2) {
16956        // This works because VISIBLE < INVISIBLE < GONE.
16957        return Math.max(vis1, vis2);
16958    }
16959
16960    /**
16961     * @param info the {@link android.view.View.AttachInfo} to associated with
16962     *        this view
16963     */
16964    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16965        mAttachInfo = info;
16966        if (mOverlay != null) {
16967            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16968        }
16969        mWindowAttachCount++;
16970        // We will need to evaluate the drawable state at least once.
16971        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16972        if (mFloatingTreeObserver != null) {
16973            info.mTreeObserver.merge(mFloatingTreeObserver);
16974            mFloatingTreeObserver = null;
16975        }
16976
16977        registerPendingFrameMetricsObservers();
16978
16979        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16980            mAttachInfo.mScrollContainers.add(this);
16981            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16982        }
16983        // Transfer all pending runnables.
16984        if (mRunQueue != null) {
16985            mRunQueue.executeActions(info.mHandler);
16986            mRunQueue = null;
16987        }
16988        performCollectViewAttributes(mAttachInfo, visibility);
16989        onAttachedToWindow();
16990
16991        ListenerInfo li = mListenerInfo;
16992        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16993                li != null ? li.mOnAttachStateChangeListeners : null;
16994        if (listeners != null && listeners.size() > 0) {
16995            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16996            // perform the dispatching. The iterator is a safe guard against listeners that
16997            // could mutate the list by calling the various add/remove methods. This prevents
16998            // the array from being modified while we iterate it.
16999            for (OnAttachStateChangeListener listener : listeners) {
17000                listener.onViewAttachedToWindow(this);
17001            }
17002        }
17003
17004        int vis = info.mWindowVisibility;
17005        if (vis != GONE) {
17006            onWindowVisibilityChanged(vis);
17007            if (isShown()) {
17008                // Calling onVisibilityAggregated directly here since the subtree will also
17009                // receive dispatchAttachedToWindow and this same call
17010                onVisibilityAggregated(vis == VISIBLE);
17011            }
17012        }
17013
17014        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17015        // As all views in the subtree will already receive dispatchAttachedToWindow
17016        // traversing the subtree again here is not desired.
17017        onVisibilityChanged(this, visibility);
17018
17019        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17020            // If nobody has evaluated the drawable state yet, then do it now.
17021            refreshDrawableState();
17022        }
17023        needGlobalAttributesUpdate(false);
17024
17025        notifyEnterOrExitForAutoFillIfNeeded(true);
17026    }
17027
17028    void dispatchDetachedFromWindow() {
17029        AttachInfo info = mAttachInfo;
17030        if (info != null) {
17031            int vis = info.mWindowVisibility;
17032            if (vis != GONE) {
17033                onWindowVisibilityChanged(GONE);
17034                if (isShown()) {
17035                    // Invoking onVisibilityAggregated directly here since the subtree
17036                    // will also receive detached from window
17037                    onVisibilityAggregated(false);
17038                }
17039            }
17040        }
17041
17042        onDetachedFromWindow();
17043        onDetachedFromWindowInternal();
17044
17045        InputMethodManager imm = InputMethodManager.peekInstance();
17046        if (imm != null) {
17047            imm.onViewDetachedFromWindow(this);
17048        }
17049
17050        ListenerInfo li = mListenerInfo;
17051        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17052                li != null ? li.mOnAttachStateChangeListeners : null;
17053        if (listeners != null && listeners.size() > 0) {
17054            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17055            // perform the dispatching. The iterator is a safe guard against listeners that
17056            // could mutate the list by calling the various add/remove methods. This prevents
17057            // the array from being modified while we iterate it.
17058            for (OnAttachStateChangeListener listener : listeners) {
17059                listener.onViewDetachedFromWindow(this);
17060            }
17061        }
17062
17063        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17064            mAttachInfo.mScrollContainers.remove(this);
17065            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17066        }
17067
17068        mAttachInfo = null;
17069        if (mOverlay != null) {
17070            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17071        }
17072
17073        notifyEnterOrExitForAutoFillIfNeeded(false);
17074    }
17075
17076    /**
17077     * Cancel any deferred high-level input events that were previously posted to the event queue.
17078     *
17079     * <p>Many views post high-level events such as click handlers to the event queue
17080     * to run deferred in order to preserve a desired user experience - clearing visible
17081     * pressed states before executing, etc. This method will abort any events of this nature
17082     * that are currently in flight.</p>
17083     *
17084     * <p>Custom views that generate their own high-level deferred input events should override
17085     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17086     *
17087     * <p>This will also cancel pending input events for any child views.</p>
17088     *
17089     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17090     * This will not impact newer events posted after this call that may occur as a result of
17091     * lower-level input events still waiting in the queue. If you are trying to prevent
17092     * double-submitted  events for the duration of some sort of asynchronous transaction
17093     * you should also take other steps to protect against unexpected double inputs e.g. calling
17094     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17095     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17096     */
17097    public final void cancelPendingInputEvents() {
17098        dispatchCancelPendingInputEvents();
17099    }
17100
17101    /**
17102     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17103     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17104     */
17105    void dispatchCancelPendingInputEvents() {
17106        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17107        onCancelPendingInputEvents();
17108        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17109            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17110                    " did not call through to super.onCancelPendingInputEvents()");
17111        }
17112    }
17113
17114    /**
17115     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17116     * a parent view.
17117     *
17118     * <p>This method is responsible for removing any pending high-level input events that were
17119     * posted to the event queue to run later. Custom view classes that post their own deferred
17120     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17121     * {@link android.os.Handler} should override this method, call
17122     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17123     * </p>
17124     */
17125    public void onCancelPendingInputEvents() {
17126        removePerformClickCallback();
17127        cancelLongPress();
17128        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17129    }
17130
17131    /**
17132     * Store this view hierarchy's frozen state into the given container.
17133     *
17134     * @param container The SparseArray in which to save the view's state.
17135     *
17136     * @see #restoreHierarchyState(android.util.SparseArray)
17137     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17138     * @see #onSaveInstanceState()
17139     */
17140    public void saveHierarchyState(SparseArray<Parcelable> container) {
17141        dispatchSaveInstanceState(container);
17142    }
17143
17144    /**
17145     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17146     * this view and its children. May be overridden to modify how freezing happens to a
17147     * view's children; for example, some views may want to not store state for their children.
17148     *
17149     * @param container The SparseArray in which to save the view's state.
17150     *
17151     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17152     * @see #saveHierarchyState(android.util.SparseArray)
17153     * @see #onSaveInstanceState()
17154     */
17155    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17156        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17157            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17158            Parcelable state = onSaveInstanceState();
17159            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17160                throw new IllegalStateException(
17161                        "Derived class did not call super.onSaveInstanceState()");
17162            }
17163            if (state != null) {
17164                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17165                // + ": " + state);
17166                container.put(mID, state);
17167            }
17168        }
17169    }
17170
17171    /**
17172     * Hook allowing a view to generate a representation of its internal state
17173     * that can later be used to create a new instance with that same state.
17174     * This state should only contain information that is not persistent or can
17175     * not be reconstructed later. For example, you will never store your
17176     * current position on screen because that will be computed again when a
17177     * new instance of the view is placed in its view hierarchy.
17178     * <p>
17179     * Some examples of things you may store here: the current cursor position
17180     * in a text view (but usually not the text itself since that is stored in a
17181     * content provider or other persistent storage), the currently selected
17182     * item in a list view.
17183     *
17184     * @return Returns a Parcelable object containing the view's current dynamic
17185     *         state, or null if there is nothing interesting to save. The
17186     *         default implementation returns null.
17187     * @see #onRestoreInstanceState(android.os.Parcelable)
17188     * @see #saveHierarchyState(android.util.SparseArray)
17189     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17190     * @see #setSaveEnabled(boolean)
17191     */
17192    @CallSuper
17193    protected Parcelable onSaveInstanceState() {
17194        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17195        if (mStartActivityRequestWho != null || isAutofilled()
17196                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17197            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17198
17199            if (mStartActivityRequestWho != null) {
17200                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17201            }
17202
17203            if (isAutofilled()) {
17204                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17205            }
17206
17207            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17208                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17209            }
17210
17211            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17212            state.mIsAutofilled = isAutofilled();
17213            state.mAccessibilityViewId = mAccessibilityViewId;
17214            return state;
17215        }
17216        return BaseSavedState.EMPTY_STATE;
17217    }
17218
17219    /**
17220     * Restore this view hierarchy's frozen state from the given container.
17221     *
17222     * @param container The SparseArray which holds previously frozen states.
17223     *
17224     * @see #saveHierarchyState(android.util.SparseArray)
17225     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17226     * @see #onRestoreInstanceState(android.os.Parcelable)
17227     */
17228    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17229        dispatchRestoreInstanceState(container);
17230    }
17231
17232    /**
17233     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17234     * state for this view and its children. May be overridden to modify how restoring
17235     * happens to a view's children; for example, some views may want to not store state
17236     * for their children.
17237     *
17238     * @param container The SparseArray which holds previously saved state.
17239     *
17240     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17241     * @see #restoreHierarchyState(android.util.SparseArray)
17242     * @see #onRestoreInstanceState(android.os.Parcelable)
17243     */
17244    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17245        if (mID != NO_ID) {
17246            Parcelable state = container.get(mID);
17247            if (state != null) {
17248                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17249                // + ": " + state);
17250                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17251                onRestoreInstanceState(state);
17252                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17253                    throw new IllegalStateException(
17254                            "Derived class did not call super.onRestoreInstanceState()");
17255                }
17256            }
17257        }
17258    }
17259
17260    /**
17261     * Hook allowing a view to re-apply a representation of its internal state that had previously
17262     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17263     * null state.
17264     *
17265     * @param state The frozen state that had previously been returned by
17266     *        {@link #onSaveInstanceState}.
17267     *
17268     * @see #onSaveInstanceState()
17269     * @see #restoreHierarchyState(android.util.SparseArray)
17270     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17271     */
17272    @CallSuper
17273    protected void onRestoreInstanceState(Parcelable state) {
17274        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17275        if (state != null && !(state instanceof AbsSavedState)) {
17276            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17277                    + "received " + state.getClass().toString() + " instead. This usually happens "
17278                    + "when two views of different type have the same id in the same hierarchy. "
17279                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17280                    + "other views do not use the same id.");
17281        }
17282        if (state != null && state instanceof BaseSavedState) {
17283            BaseSavedState baseState = (BaseSavedState) state;
17284
17285            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17286                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17287            }
17288            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17289                setAutofilled(baseState.mIsAutofilled);
17290            }
17291            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17292                mAccessibilityViewId = baseState.mAccessibilityViewId;
17293            }
17294        }
17295    }
17296
17297    /**
17298     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17299     *
17300     * @return the drawing start time in milliseconds
17301     */
17302    public long getDrawingTime() {
17303        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17304    }
17305
17306    /**
17307     * <p>Enables or disables the duplication of the parent's state into this view. When
17308     * duplication is enabled, this view gets its drawable state from its parent rather
17309     * than from its own internal properties.</p>
17310     *
17311     * <p>Note: in the current implementation, setting this property to true after the
17312     * view was added to a ViewGroup might have no effect at all. This property should
17313     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17314     *
17315     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17316     * property is enabled, an exception will be thrown.</p>
17317     *
17318     * <p>Note: if the child view uses and updates additional states which are unknown to the
17319     * parent, these states should not be affected by this method.</p>
17320     *
17321     * @param enabled True to enable duplication of the parent's drawable state, false
17322     *                to disable it.
17323     *
17324     * @see #getDrawableState()
17325     * @see #isDuplicateParentStateEnabled()
17326     */
17327    public void setDuplicateParentStateEnabled(boolean enabled) {
17328        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17329    }
17330
17331    /**
17332     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17333     *
17334     * @return True if this view's drawable state is duplicated from the parent,
17335     *         false otherwise
17336     *
17337     * @see #getDrawableState()
17338     * @see #setDuplicateParentStateEnabled(boolean)
17339     */
17340    public boolean isDuplicateParentStateEnabled() {
17341        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17342    }
17343
17344    /**
17345     * <p>Specifies the type of layer backing this view. The layer can be
17346     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17347     * {@link #LAYER_TYPE_HARDWARE}.</p>
17348     *
17349     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17350     * instance that controls how the layer is composed on screen. The following
17351     * properties of the paint are taken into account when composing the layer:</p>
17352     * <ul>
17353     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17354     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17355     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17356     * </ul>
17357     *
17358     * <p>If this view has an alpha value set to < 1.0 by calling
17359     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17360     * by this view's alpha value.</p>
17361     *
17362     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17363     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17364     * for more information on when and how to use layers.</p>
17365     *
17366     * @param layerType The type of layer to use with this view, must be one of
17367     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17368     *        {@link #LAYER_TYPE_HARDWARE}
17369     * @param paint The paint used to compose the layer. This argument is optional
17370     *        and can be null. It is ignored when the layer type is
17371     *        {@link #LAYER_TYPE_NONE}
17372     *
17373     * @see #getLayerType()
17374     * @see #LAYER_TYPE_NONE
17375     * @see #LAYER_TYPE_SOFTWARE
17376     * @see #LAYER_TYPE_HARDWARE
17377     * @see #setAlpha(float)
17378     *
17379     * @attr ref android.R.styleable#View_layerType
17380     */
17381    public void setLayerType(int layerType, @Nullable Paint paint) {
17382        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17383            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17384                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17385        }
17386
17387        boolean typeChanged = mRenderNode.setLayerType(layerType);
17388
17389        if (!typeChanged) {
17390            setLayerPaint(paint);
17391            return;
17392        }
17393
17394        if (layerType != LAYER_TYPE_SOFTWARE) {
17395            // Destroy any previous software drawing cache if present
17396            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17397            // drawing cache created in View#draw when drawing to a SW canvas.
17398            destroyDrawingCache();
17399        }
17400
17401        mLayerType = layerType;
17402        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17403        mRenderNode.setLayerPaint(mLayerPaint);
17404
17405        // draw() behaves differently if we are on a layer, so we need to
17406        // invalidate() here
17407        invalidateParentCaches();
17408        invalidate(true);
17409    }
17410
17411    /**
17412     * Updates the {@link Paint} object used with the current layer (used only if the current
17413     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17414     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17415     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17416     * ensure that the view gets redrawn immediately.
17417     *
17418     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17419     * instance that controls how the layer is composed on screen. The following
17420     * properties of the paint are taken into account when composing the layer:</p>
17421     * <ul>
17422     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17423     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17424     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17425     * </ul>
17426     *
17427     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17428     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17429     *
17430     * @param paint The paint used to compose the layer. This argument is optional
17431     *        and can be null. It is ignored when the layer type is
17432     *        {@link #LAYER_TYPE_NONE}
17433     *
17434     * @see #setLayerType(int, android.graphics.Paint)
17435     */
17436    public void setLayerPaint(@Nullable Paint paint) {
17437        int layerType = getLayerType();
17438        if (layerType != LAYER_TYPE_NONE) {
17439            mLayerPaint = paint;
17440            if (layerType == LAYER_TYPE_HARDWARE) {
17441                if (mRenderNode.setLayerPaint(paint)) {
17442                    invalidateViewProperty(false, false);
17443                }
17444            } else {
17445                invalidate();
17446            }
17447        }
17448    }
17449
17450    /**
17451     * Indicates what type of layer is currently associated with this view. By default
17452     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17453     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17454     * for more information on the different types of layers.
17455     *
17456     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17457     *         {@link #LAYER_TYPE_HARDWARE}
17458     *
17459     * @see #setLayerType(int, android.graphics.Paint)
17460     * @see #buildLayer()
17461     * @see #LAYER_TYPE_NONE
17462     * @see #LAYER_TYPE_SOFTWARE
17463     * @see #LAYER_TYPE_HARDWARE
17464     */
17465    public int getLayerType() {
17466        return mLayerType;
17467    }
17468
17469    /**
17470     * Forces this view's layer to be created and this view to be rendered
17471     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17472     * invoking this method will have no effect.
17473     *
17474     * This method can for instance be used to render a view into its layer before
17475     * starting an animation. If this view is complex, rendering into the layer
17476     * before starting the animation will avoid skipping frames.
17477     *
17478     * @throws IllegalStateException If this view is not attached to a window
17479     *
17480     * @see #setLayerType(int, android.graphics.Paint)
17481     */
17482    public void buildLayer() {
17483        if (mLayerType == LAYER_TYPE_NONE) return;
17484
17485        final AttachInfo attachInfo = mAttachInfo;
17486        if (attachInfo == null) {
17487            throw new IllegalStateException("This view must be attached to a window first");
17488        }
17489
17490        if (getWidth() == 0 || getHeight() == 0) {
17491            return;
17492        }
17493
17494        switch (mLayerType) {
17495            case LAYER_TYPE_HARDWARE:
17496                updateDisplayListIfDirty();
17497                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17498                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17499                }
17500                break;
17501            case LAYER_TYPE_SOFTWARE:
17502                buildDrawingCache(true);
17503                break;
17504        }
17505    }
17506
17507    /**
17508     * Destroys all hardware rendering resources. This method is invoked
17509     * when the system needs to reclaim resources. Upon execution of this
17510     * method, you should free any OpenGL resources created by the view.
17511     *
17512     * Note: you <strong>must</strong> call
17513     * <code>super.destroyHardwareResources()</code> when overriding
17514     * this method.
17515     *
17516     * @hide
17517     */
17518    @CallSuper
17519    protected void destroyHardwareResources() {
17520        if (mOverlay != null) {
17521            mOverlay.getOverlayView().destroyHardwareResources();
17522        }
17523        if (mGhostView != null) {
17524            mGhostView.destroyHardwareResources();
17525        }
17526    }
17527
17528    /**
17529     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17530     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17531     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17532     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17533     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17534     * null.</p>
17535     *
17536     * <p>Enabling the drawing cache is similar to
17537     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17538     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17539     * drawing cache has no effect on rendering because the system uses a different mechanism
17540     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17541     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17542     * for information on how to enable software and hardware layers.</p>
17543     *
17544     * <p>This API can be used to manually generate
17545     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17546     * {@link #getDrawingCache()}.</p>
17547     *
17548     * @param enabled true to enable the drawing cache, false otherwise
17549     *
17550     * @see #isDrawingCacheEnabled()
17551     * @see #getDrawingCache()
17552     * @see #buildDrawingCache()
17553     * @see #setLayerType(int, android.graphics.Paint)
17554     */
17555    public void setDrawingCacheEnabled(boolean enabled) {
17556        mCachingFailed = false;
17557        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17558    }
17559
17560    /**
17561     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17562     *
17563     * @return true if the drawing cache is enabled
17564     *
17565     * @see #setDrawingCacheEnabled(boolean)
17566     * @see #getDrawingCache()
17567     */
17568    @ViewDebug.ExportedProperty(category = "drawing")
17569    public boolean isDrawingCacheEnabled() {
17570        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17571    }
17572
17573    /**
17574     * Debugging utility which recursively outputs the dirty state of a view and its
17575     * descendants.
17576     *
17577     * @hide
17578     */
17579    @SuppressWarnings({"UnusedDeclaration"})
17580    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17581        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17582                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17583                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17584                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17585        if (clear) {
17586            mPrivateFlags &= clearMask;
17587        }
17588        if (this instanceof ViewGroup) {
17589            ViewGroup parent = (ViewGroup) this;
17590            final int count = parent.getChildCount();
17591            for (int i = 0; i < count; i++) {
17592                final View child = parent.getChildAt(i);
17593                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17594            }
17595        }
17596    }
17597
17598    /**
17599     * This method is used by ViewGroup to cause its children to restore or recreate their
17600     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17601     * to recreate its own display list, which would happen if it went through the normal
17602     * draw/dispatchDraw mechanisms.
17603     *
17604     * @hide
17605     */
17606    protected void dispatchGetDisplayList() {}
17607
17608    /**
17609     * A view that is not attached or hardware accelerated cannot create a display list.
17610     * This method checks these conditions and returns the appropriate result.
17611     *
17612     * @return true if view has the ability to create a display list, false otherwise.
17613     *
17614     * @hide
17615     */
17616    public boolean canHaveDisplayList() {
17617        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17618    }
17619
17620    /**
17621     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17622     * @hide
17623     */
17624    @NonNull
17625    public RenderNode updateDisplayListIfDirty() {
17626        final RenderNode renderNode = mRenderNode;
17627        if (!canHaveDisplayList()) {
17628            // can't populate RenderNode, don't try
17629            return renderNode;
17630        }
17631
17632        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17633                || !renderNode.isValid()
17634                || (mRecreateDisplayList)) {
17635            // Don't need to recreate the display list, just need to tell our
17636            // children to restore/recreate theirs
17637            if (renderNode.isValid()
17638                    && !mRecreateDisplayList) {
17639                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17640                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17641                dispatchGetDisplayList();
17642
17643                return renderNode; // no work needed
17644            }
17645
17646            // If we got here, we're recreating it. Mark it as such to ensure that
17647            // we copy in child display lists into ours in drawChild()
17648            mRecreateDisplayList = true;
17649
17650            int width = mRight - mLeft;
17651            int height = mBottom - mTop;
17652            int layerType = getLayerType();
17653
17654            final DisplayListCanvas canvas = renderNode.start(width, height);
17655            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17656
17657            try {
17658                if (layerType == LAYER_TYPE_SOFTWARE) {
17659                    buildDrawingCache(true);
17660                    Bitmap cache = getDrawingCache(true);
17661                    if (cache != null) {
17662                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17663                    }
17664                } else {
17665                    computeScroll();
17666
17667                    canvas.translate(-mScrollX, -mScrollY);
17668                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17669                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17670
17671                    // Fast path for layouts with no backgrounds
17672                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17673                        dispatchDraw(canvas);
17674                        drawAutofilledHighlight(canvas);
17675                        if (mOverlay != null && !mOverlay.isEmpty()) {
17676                            mOverlay.getOverlayView().draw(canvas);
17677                        }
17678                        if (debugDraw()) {
17679                            debugDrawFocus(canvas);
17680                        }
17681                    } else {
17682                        draw(canvas);
17683                    }
17684                }
17685            } finally {
17686                renderNode.end(canvas);
17687                setDisplayListProperties(renderNode);
17688            }
17689        } else {
17690            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17691            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17692        }
17693        return renderNode;
17694    }
17695
17696    private void resetDisplayList() {
17697        mRenderNode.discardDisplayList();
17698        if (mBackgroundRenderNode != null) {
17699            mBackgroundRenderNode.discardDisplayList();
17700        }
17701    }
17702
17703    /**
17704     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17705     *
17706     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17707     *
17708     * @see #getDrawingCache(boolean)
17709     */
17710    public Bitmap getDrawingCache() {
17711        return getDrawingCache(false);
17712    }
17713
17714    /**
17715     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17716     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17717     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17718     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17719     * request the drawing cache by calling this method and draw it on screen if the
17720     * returned bitmap is not null.</p>
17721     *
17722     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17723     * this method will create a bitmap of the same size as this view. Because this bitmap
17724     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17725     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17726     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17727     * size than the view. This implies that your application must be able to handle this
17728     * size.</p>
17729     *
17730     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17731     *        the current density of the screen when the application is in compatibility
17732     *        mode.
17733     *
17734     * @return A bitmap representing this view or null if cache is disabled.
17735     *
17736     * @see #setDrawingCacheEnabled(boolean)
17737     * @see #isDrawingCacheEnabled()
17738     * @see #buildDrawingCache(boolean)
17739     * @see #destroyDrawingCache()
17740     */
17741    public Bitmap getDrawingCache(boolean autoScale) {
17742        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17743            return null;
17744        }
17745        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17746            buildDrawingCache(autoScale);
17747        }
17748        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17749    }
17750
17751    /**
17752     * <p>Frees the resources used by the drawing cache. If you call
17753     * {@link #buildDrawingCache()} manually without calling
17754     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17755     * should cleanup the cache with this method afterwards.</p>
17756     *
17757     * @see #setDrawingCacheEnabled(boolean)
17758     * @see #buildDrawingCache()
17759     * @see #getDrawingCache()
17760     */
17761    public void destroyDrawingCache() {
17762        if (mDrawingCache != null) {
17763            mDrawingCache.recycle();
17764            mDrawingCache = null;
17765        }
17766        if (mUnscaledDrawingCache != null) {
17767            mUnscaledDrawingCache.recycle();
17768            mUnscaledDrawingCache = null;
17769        }
17770    }
17771
17772    /**
17773     * Setting a solid background color for the drawing cache's bitmaps will improve
17774     * performance and memory usage. Note, though that this should only be used if this
17775     * view will always be drawn on top of a solid color.
17776     *
17777     * @param color The background color to use for the drawing cache's bitmap
17778     *
17779     * @see #setDrawingCacheEnabled(boolean)
17780     * @see #buildDrawingCache()
17781     * @see #getDrawingCache()
17782     */
17783    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17784        if (color != mDrawingCacheBackgroundColor) {
17785            mDrawingCacheBackgroundColor = color;
17786            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17787        }
17788    }
17789
17790    /**
17791     * @see #setDrawingCacheBackgroundColor(int)
17792     *
17793     * @return The background color to used for the drawing cache's bitmap
17794     */
17795    @ColorInt
17796    public int getDrawingCacheBackgroundColor() {
17797        return mDrawingCacheBackgroundColor;
17798    }
17799
17800    /**
17801     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17802     *
17803     * @see #buildDrawingCache(boolean)
17804     */
17805    public void buildDrawingCache() {
17806        buildDrawingCache(false);
17807    }
17808
17809    /**
17810     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17811     *
17812     * <p>If you call {@link #buildDrawingCache()} manually without calling
17813     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17814     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17815     *
17816     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17817     * this method will create a bitmap of the same size as this view. Because this bitmap
17818     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17819     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17820     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17821     * size than the view. This implies that your application must be able to handle this
17822     * size.</p>
17823     *
17824     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17825     * you do not need the drawing cache bitmap, calling this method will increase memory
17826     * usage and cause the view to be rendered in software once, thus negatively impacting
17827     * performance.</p>
17828     *
17829     * @see #getDrawingCache()
17830     * @see #destroyDrawingCache()
17831     */
17832    public void buildDrawingCache(boolean autoScale) {
17833        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17834                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17835            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17836                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17837                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17838            }
17839            try {
17840                buildDrawingCacheImpl(autoScale);
17841            } finally {
17842                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17843            }
17844        }
17845    }
17846
17847    /**
17848     * private, internal implementation of buildDrawingCache, used to enable tracing
17849     */
17850    private void buildDrawingCacheImpl(boolean autoScale) {
17851        mCachingFailed = false;
17852
17853        int width = mRight - mLeft;
17854        int height = mBottom - mTop;
17855
17856        final AttachInfo attachInfo = mAttachInfo;
17857        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17858
17859        if (autoScale && scalingRequired) {
17860            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17861            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17862        }
17863
17864        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17865        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17866        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17867
17868        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17869        final long drawingCacheSize =
17870                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17871        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17872            if (width > 0 && height > 0) {
17873                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17874                        + " too large to fit into a software layer (or drawing cache), needs "
17875                        + projectedBitmapSize + " bytes, only "
17876                        + drawingCacheSize + " available");
17877            }
17878            destroyDrawingCache();
17879            mCachingFailed = true;
17880            return;
17881        }
17882
17883        boolean clear = true;
17884        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17885
17886        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17887            Bitmap.Config quality;
17888            if (!opaque) {
17889                // Never pick ARGB_4444 because it looks awful
17890                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17891                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17892                    case DRAWING_CACHE_QUALITY_AUTO:
17893                    case DRAWING_CACHE_QUALITY_LOW:
17894                    case DRAWING_CACHE_QUALITY_HIGH:
17895                    default:
17896                        quality = Bitmap.Config.ARGB_8888;
17897                        break;
17898                }
17899            } else {
17900                // Optimization for translucent windows
17901                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17902                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17903            }
17904
17905            // Try to cleanup memory
17906            if (bitmap != null) bitmap.recycle();
17907
17908            try {
17909                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17910                        width, height, quality);
17911                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17912                if (autoScale) {
17913                    mDrawingCache = bitmap;
17914                } else {
17915                    mUnscaledDrawingCache = bitmap;
17916                }
17917                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17918            } catch (OutOfMemoryError e) {
17919                // If there is not enough memory to create the bitmap cache, just
17920                // ignore the issue as bitmap caches are not required to draw the
17921                // view hierarchy
17922                if (autoScale) {
17923                    mDrawingCache = null;
17924                } else {
17925                    mUnscaledDrawingCache = null;
17926                }
17927                mCachingFailed = true;
17928                return;
17929            }
17930
17931            clear = drawingCacheBackgroundColor != 0;
17932        }
17933
17934        Canvas canvas;
17935        if (attachInfo != null) {
17936            canvas = attachInfo.mCanvas;
17937            if (canvas == null) {
17938                canvas = new Canvas();
17939            }
17940            canvas.setBitmap(bitmap);
17941            // Temporarily clobber the cached Canvas in case one of our children
17942            // is also using a drawing cache. Without this, the children would
17943            // steal the canvas by attaching their own bitmap to it and bad, bad
17944            // thing would happen (invisible views, corrupted drawings, etc.)
17945            attachInfo.mCanvas = null;
17946        } else {
17947            // This case should hopefully never or seldom happen
17948            canvas = new Canvas(bitmap);
17949        }
17950
17951        if (clear) {
17952            bitmap.eraseColor(drawingCacheBackgroundColor);
17953        }
17954
17955        computeScroll();
17956        final int restoreCount = canvas.save();
17957
17958        if (autoScale && scalingRequired) {
17959            final float scale = attachInfo.mApplicationScale;
17960            canvas.scale(scale, scale);
17961        }
17962
17963        canvas.translate(-mScrollX, -mScrollY);
17964
17965        mPrivateFlags |= PFLAG_DRAWN;
17966        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17967                mLayerType != LAYER_TYPE_NONE) {
17968            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17969        }
17970
17971        // Fast path for layouts with no backgrounds
17972        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17973            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17974            dispatchDraw(canvas);
17975            drawAutofilledHighlight(canvas);
17976            if (mOverlay != null && !mOverlay.isEmpty()) {
17977                mOverlay.getOverlayView().draw(canvas);
17978            }
17979        } else {
17980            draw(canvas);
17981        }
17982
17983        canvas.restoreToCount(restoreCount);
17984        canvas.setBitmap(null);
17985
17986        if (attachInfo != null) {
17987            // Restore the cached Canvas for our siblings
17988            attachInfo.mCanvas = canvas;
17989        }
17990    }
17991
17992    /**
17993     * Create a snapshot of the view into a bitmap.  We should probably make
17994     * some form of this public, but should think about the API.
17995     *
17996     * @hide
17997     */
17998    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17999        int width = mRight - mLeft;
18000        int height = mBottom - mTop;
18001
18002        final AttachInfo attachInfo = mAttachInfo;
18003        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18004        width = (int) ((width * scale) + 0.5f);
18005        height = (int) ((height * scale) + 0.5f);
18006
18007        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18008                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18009        if (bitmap == null) {
18010            throw new OutOfMemoryError();
18011        }
18012
18013        Resources resources = getResources();
18014        if (resources != null) {
18015            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18016        }
18017
18018        Canvas canvas;
18019        if (attachInfo != null) {
18020            canvas = attachInfo.mCanvas;
18021            if (canvas == null) {
18022                canvas = new Canvas();
18023            }
18024            canvas.setBitmap(bitmap);
18025            // Temporarily clobber the cached Canvas in case one of our children
18026            // is also using a drawing cache. Without this, the children would
18027            // steal the canvas by attaching their own bitmap to it and bad, bad
18028            // things would happen (invisible views, corrupted drawings, etc.)
18029            attachInfo.mCanvas = null;
18030        } else {
18031            // This case should hopefully never or seldom happen
18032            canvas = new Canvas(bitmap);
18033        }
18034        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18035        canvas.setHwBitmapsInSwModeEnabled(true);
18036        if ((backgroundColor & 0xff000000) != 0) {
18037            bitmap.eraseColor(backgroundColor);
18038        }
18039
18040        computeScroll();
18041        final int restoreCount = canvas.save();
18042        canvas.scale(scale, scale);
18043        canvas.translate(-mScrollX, -mScrollY);
18044
18045        // Temporarily remove the dirty mask
18046        int flags = mPrivateFlags;
18047        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18048
18049        // Fast path for layouts with no backgrounds
18050        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18051            dispatchDraw(canvas);
18052            drawAutofilledHighlight(canvas);
18053            if (mOverlay != null && !mOverlay.isEmpty()) {
18054                mOverlay.getOverlayView().draw(canvas);
18055            }
18056        } else {
18057            draw(canvas);
18058        }
18059
18060        mPrivateFlags = flags;
18061
18062        canvas.restoreToCount(restoreCount);
18063        canvas.setBitmap(null);
18064        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18065
18066        if (attachInfo != null) {
18067            // Restore the cached Canvas for our siblings
18068            attachInfo.mCanvas = canvas;
18069        }
18070
18071        return bitmap;
18072    }
18073
18074    /**
18075     * Indicates whether this View is currently in edit mode. A View is usually
18076     * in edit mode when displayed within a developer tool. For instance, if
18077     * this View is being drawn by a visual user interface builder, this method
18078     * should return true.
18079     *
18080     * Subclasses should check the return value of this method to provide
18081     * different behaviors if their normal behavior might interfere with the
18082     * host environment. For instance: the class spawns a thread in its
18083     * constructor, the drawing code relies on device-specific features, etc.
18084     *
18085     * This method is usually checked in the drawing code of custom widgets.
18086     *
18087     * @return True if this View is in edit mode, false otherwise.
18088     */
18089    public boolean isInEditMode() {
18090        return false;
18091    }
18092
18093    /**
18094     * If the View draws content inside its padding and enables fading edges,
18095     * it needs to support padding offsets. Padding offsets are added to the
18096     * fading edges to extend the length of the fade so that it covers pixels
18097     * drawn inside the padding.
18098     *
18099     * Subclasses of this class should override this method if they need
18100     * to draw content inside the padding.
18101     *
18102     * @return True if padding offset must be applied, false otherwise.
18103     *
18104     * @see #getLeftPaddingOffset()
18105     * @see #getRightPaddingOffset()
18106     * @see #getTopPaddingOffset()
18107     * @see #getBottomPaddingOffset()
18108     *
18109     * @since CURRENT
18110     */
18111    protected boolean isPaddingOffsetRequired() {
18112        return false;
18113    }
18114
18115    /**
18116     * Amount by which to extend the left fading region. Called only when
18117     * {@link #isPaddingOffsetRequired()} returns true.
18118     *
18119     * @return The left padding offset in pixels.
18120     *
18121     * @see #isPaddingOffsetRequired()
18122     *
18123     * @since CURRENT
18124     */
18125    protected int getLeftPaddingOffset() {
18126        return 0;
18127    }
18128
18129    /**
18130     * Amount by which to extend the right fading region. Called only when
18131     * {@link #isPaddingOffsetRequired()} returns true.
18132     *
18133     * @return The right padding offset in pixels.
18134     *
18135     * @see #isPaddingOffsetRequired()
18136     *
18137     * @since CURRENT
18138     */
18139    protected int getRightPaddingOffset() {
18140        return 0;
18141    }
18142
18143    /**
18144     * Amount by which to extend the top fading region. Called only when
18145     * {@link #isPaddingOffsetRequired()} returns true.
18146     *
18147     * @return The top padding offset in pixels.
18148     *
18149     * @see #isPaddingOffsetRequired()
18150     *
18151     * @since CURRENT
18152     */
18153    protected int getTopPaddingOffset() {
18154        return 0;
18155    }
18156
18157    /**
18158     * Amount by which to extend the bottom fading region. Called only when
18159     * {@link #isPaddingOffsetRequired()} returns true.
18160     *
18161     * @return The bottom padding offset in pixels.
18162     *
18163     * @see #isPaddingOffsetRequired()
18164     *
18165     * @since CURRENT
18166     */
18167    protected int getBottomPaddingOffset() {
18168        return 0;
18169    }
18170
18171    /**
18172     * @hide
18173     * @param offsetRequired
18174     */
18175    protected int getFadeTop(boolean offsetRequired) {
18176        int top = mPaddingTop;
18177        if (offsetRequired) top += getTopPaddingOffset();
18178        return top;
18179    }
18180
18181    /**
18182     * @hide
18183     * @param offsetRequired
18184     */
18185    protected int getFadeHeight(boolean offsetRequired) {
18186        int padding = mPaddingTop;
18187        if (offsetRequired) padding += getTopPaddingOffset();
18188        return mBottom - mTop - mPaddingBottom - padding;
18189    }
18190
18191    /**
18192     * <p>Indicates whether this view is attached to a hardware accelerated
18193     * window or not.</p>
18194     *
18195     * <p>Even if this method returns true, it does not mean that every call
18196     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18197     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18198     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18199     * window is hardware accelerated,
18200     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18201     * return false, and this method will return true.</p>
18202     *
18203     * @return True if the view is attached to a window and the window is
18204     *         hardware accelerated; false in any other case.
18205     */
18206    @ViewDebug.ExportedProperty(category = "drawing")
18207    public boolean isHardwareAccelerated() {
18208        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18209    }
18210
18211    /**
18212     * Sets a rectangular area on this view to which the view will be clipped
18213     * when it is drawn. Setting the value to null will remove the clip bounds
18214     * and the view will draw normally, using its full bounds.
18215     *
18216     * @param clipBounds The rectangular area, in the local coordinates of
18217     * this view, to which future drawing operations will be clipped.
18218     */
18219    public void setClipBounds(Rect clipBounds) {
18220        if (clipBounds == mClipBounds
18221                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18222            return;
18223        }
18224        if (clipBounds != null) {
18225            if (mClipBounds == null) {
18226                mClipBounds = new Rect(clipBounds);
18227            } else {
18228                mClipBounds.set(clipBounds);
18229            }
18230        } else {
18231            mClipBounds = null;
18232        }
18233        mRenderNode.setClipBounds(mClipBounds);
18234        invalidateViewProperty(false, false);
18235    }
18236
18237    /**
18238     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18239     *
18240     * @return A copy of the current clip bounds if clip bounds are set,
18241     * otherwise null.
18242     */
18243    public Rect getClipBounds() {
18244        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18245    }
18246
18247
18248    /**
18249     * Populates an output rectangle with the clip bounds of the view,
18250     * returning {@code true} if successful or {@code false} if the view's
18251     * clip bounds are {@code null}.
18252     *
18253     * @param outRect rectangle in which to place the clip bounds of the view
18254     * @return {@code true} if successful or {@code false} if the view's
18255     *         clip bounds are {@code null}
18256     */
18257    public boolean getClipBounds(Rect outRect) {
18258        if (mClipBounds != null) {
18259            outRect.set(mClipBounds);
18260            return true;
18261        }
18262        return false;
18263    }
18264
18265    /**
18266     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18267     * case of an active Animation being run on the view.
18268     */
18269    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18270            Animation a, boolean scalingRequired) {
18271        Transformation invalidationTransform;
18272        final int flags = parent.mGroupFlags;
18273        final boolean initialized = a.isInitialized();
18274        if (!initialized) {
18275            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18276            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18277            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18278            onAnimationStart();
18279        }
18280
18281        final Transformation t = parent.getChildTransformation();
18282        boolean more = a.getTransformation(drawingTime, t, 1f);
18283        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18284            if (parent.mInvalidationTransformation == null) {
18285                parent.mInvalidationTransformation = new Transformation();
18286            }
18287            invalidationTransform = parent.mInvalidationTransformation;
18288            a.getTransformation(drawingTime, invalidationTransform, 1f);
18289        } else {
18290            invalidationTransform = t;
18291        }
18292
18293        if (more) {
18294            if (!a.willChangeBounds()) {
18295                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18296                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18297                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18298                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18299                    // The child need to draw an animation, potentially offscreen, so
18300                    // make sure we do not cancel invalidate requests
18301                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18302                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18303                }
18304            } else {
18305                if (parent.mInvalidateRegion == null) {
18306                    parent.mInvalidateRegion = new RectF();
18307                }
18308                final RectF region = parent.mInvalidateRegion;
18309                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18310                        invalidationTransform);
18311
18312                // The child need to draw an animation, potentially offscreen, so
18313                // make sure we do not cancel invalidate requests
18314                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18315
18316                final int left = mLeft + (int) region.left;
18317                final int top = mTop + (int) region.top;
18318                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18319                        top + (int) (region.height() + .5f));
18320            }
18321        }
18322        return more;
18323    }
18324
18325    /**
18326     * This method is called by getDisplayList() when a display list is recorded for a View.
18327     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18328     */
18329    void setDisplayListProperties(RenderNode renderNode) {
18330        if (renderNode != null) {
18331            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18332            renderNode.setClipToBounds(mParent instanceof ViewGroup
18333                    && ((ViewGroup) mParent).getClipChildren());
18334
18335            float alpha = 1;
18336            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18337                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18338                ViewGroup parentVG = (ViewGroup) mParent;
18339                final Transformation t = parentVG.getChildTransformation();
18340                if (parentVG.getChildStaticTransformation(this, t)) {
18341                    final int transformType = t.getTransformationType();
18342                    if (transformType != Transformation.TYPE_IDENTITY) {
18343                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18344                            alpha = t.getAlpha();
18345                        }
18346                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18347                            renderNode.setStaticMatrix(t.getMatrix());
18348                        }
18349                    }
18350                }
18351            }
18352            if (mTransformationInfo != null) {
18353                alpha *= getFinalAlpha();
18354                if (alpha < 1) {
18355                    final int multipliedAlpha = (int) (255 * alpha);
18356                    if (onSetAlpha(multipliedAlpha)) {
18357                        alpha = 1;
18358                    }
18359                }
18360                renderNode.setAlpha(alpha);
18361            } else if (alpha < 1) {
18362                renderNode.setAlpha(alpha);
18363            }
18364        }
18365    }
18366
18367    /**
18368     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18369     *
18370     * This is where the View specializes rendering behavior based on layer type,
18371     * and hardware acceleration.
18372     */
18373    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18374        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18375        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18376         *
18377         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18378         * HW accelerated, it can't handle drawing RenderNodes.
18379         */
18380        boolean drawingWithRenderNode = mAttachInfo != null
18381                && mAttachInfo.mHardwareAccelerated
18382                && hardwareAcceleratedCanvas;
18383
18384        boolean more = false;
18385        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18386        final int parentFlags = parent.mGroupFlags;
18387
18388        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18389            parent.getChildTransformation().clear();
18390            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18391        }
18392
18393        Transformation transformToApply = null;
18394        boolean concatMatrix = false;
18395        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18396        final Animation a = getAnimation();
18397        if (a != null) {
18398            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18399            concatMatrix = a.willChangeTransformationMatrix();
18400            if (concatMatrix) {
18401                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18402            }
18403            transformToApply = parent.getChildTransformation();
18404        } else {
18405            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18406                // No longer animating: clear out old animation matrix
18407                mRenderNode.setAnimationMatrix(null);
18408                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18409            }
18410            if (!drawingWithRenderNode
18411                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18412                final Transformation t = parent.getChildTransformation();
18413                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18414                if (hasTransform) {
18415                    final int transformType = t.getTransformationType();
18416                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18417                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18418                }
18419            }
18420        }
18421
18422        concatMatrix |= !childHasIdentityMatrix;
18423
18424        // Sets the flag as early as possible to allow draw() implementations
18425        // to call invalidate() successfully when doing animations
18426        mPrivateFlags |= PFLAG_DRAWN;
18427
18428        if (!concatMatrix &&
18429                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18430                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18431                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18432                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18433            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18434            return more;
18435        }
18436        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18437
18438        if (hardwareAcceleratedCanvas) {
18439            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18440            // retain the flag's value temporarily in the mRecreateDisplayList flag
18441            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18442            mPrivateFlags &= ~PFLAG_INVALIDATED;
18443        }
18444
18445        RenderNode renderNode = null;
18446        Bitmap cache = null;
18447        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18448        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18449             if (layerType != LAYER_TYPE_NONE) {
18450                 // If not drawing with RenderNode, treat HW layers as SW
18451                 layerType = LAYER_TYPE_SOFTWARE;
18452                 buildDrawingCache(true);
18453            }
18454            cache = getDrawingCache(true);
18455        }
18456
18457        if (drawingWithRenderNode) {
18458            // Delay getting the display list until animation-driven alpha values are
18459            // set up and possibly passed on to the view
18460            renderNode = updateDisplayListIfDirty();
18461            if (!renderNode.isValid()) {
18462                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18463                // to getDisplayList(), the display list will be marked invalid and we should not
18464                // try to use it again.
18465                renderNode = null;
18466                drawingWithRenderNode = false;
18467            }
18468        }
18469
18470        int sx = 0;
18471        int sy = 0;
18472        if (!drawingWithRenderNode) {
18473            computeScroll();
18474            sx = mScrollX;
18475            sy = mScrollY;
18476        }
18477
18478        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18479        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18480
18481        int restoreTo = -1;
18482        if (!drawingWithRenderNode || transformToApply != null) {
18483            restoreTo = canvas.save();
18484        }
18485        if (offsetForScroll) {
18486            canvas.translate(mLeft - sx, mTop - sy);
18487        } else {
18488            if (!drawingWithRenderNode) {
18489                canvas.translate(mLeft, mTop);
18490            }
18491            if (scalingRequired) {
18492                if (drawingWithRenderNode) {
18493                    // TODO: Might not need this if we put everything inside the DL
18494                    restoreTo = canvas.save();
18495                }
18496                // mAttachInfo cannot be null, otherwise scalingRequired == false
18497                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18498                canvas.scale(scale, scale);
18499            }
18500        }
18501
18502        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18503        if (transformToApply != null
18504                || alpha < 1
18505                || !hasIdentityMatrix()
18506                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18507            if (transformToApply != null || !childHasIdentityMatrix) {
18508                int transX = 0;
18509                int transY = 0;
18510
18511                if (offsetForScroll) {
18512                    transX = -sx;
18513                    transY = -sy;
18514                }
18515
18516                if (transformToApply != null) {
18517                    if (concatMatrix) {
18518                        if (drawingWithRenderNode) {
18519                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18520                        } else {
18521                            // Undo the scroll translation, apply the transformation matrix,
18522                            // then redo the scroll translate to get the correct result.
18523                            canvas.translate(-transX, -transY);
18524                            canvas.concat(transformToApply.getMatrix());
18525                            canvas.translate(transX, transY);
18526                        }
18527                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18528                    }
18529
18530                    float transformAlpha = transformToApply.getAlpha();
18531                    if (transformAlpha < 1) {
18532                        alpha *= transformAlpha;
18533                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18534                    }
18535                }
18536
18537                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18538                    canvas.translate(-transX, -transY);
18539                    canvas.concat(getMatrix());
18540                    canvas.translate(transX, transY);
18541                }
18542            }
18543
18544            // Deal with alpha if it is or used to be <1
18545            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18546                if (alpha < 1) {
18547                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18548                } else {
18549                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18550                }
18551                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18552                if (!drawingWithDrawingCache) {
18553                    final int multipliedAlpha = (int) (255 * alpha);
18554                    if (!onSetAlpha(multipliedAlpha)) {
18555                        if (drawingWithRenderNode) {
18556                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18557                        } else if (layerType == LAYER_TYPE_NONE) {
18558                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18559                                    multipliedAlpha);
18560                        }
18561                    } else {
18562                        // Alpha is handled by the child directly, clobber the layer's alpha
18563                        mPrivateFlags |= PFLAG_ALPHA_SET;
18564                    }
18565                }
18566            }
18567        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18568            onSetAlpha(255);
18569            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18570        }
18571
18572        if (!drawingWithRenderNode) {
18573            // apply clips directly, since RenderNode won't do it for this draw
18574            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18575                if (offsetForScroll) {
18576                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18577                } else {
18578                    if (!scalingRequired || cache == null) {
18579                        canvas.clipRect(0, 0, getWidth(), getHeight());
18580                    } else {
18581                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18582                    }
18583                }
18584            }
18585
18586            if (mClipBounds != null) {
18587                // clip bounds ignore scroll
18588                canvas.clipRect(mClipBounds);
18589            }
18590        }
18591
18592        if (!drawingWithDrawingCache) {
18593            if (drawingWithRenderNode) {
18594                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18595                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18596            } else {
18597                // Fast path for layouts with no backgrounds
18598                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18599                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18600                    dispatchDraw(canvas);
18601                } else {
18602                    draw(canvas);
18603                }
18604            }
18605        } else if (cache != null) {
18606            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18607            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18608                // no layer paint, use temporary paint to draw bitmap
18609                Paint cachePaint = parent.mCachePaint;
18610                if (cachePaint == null) {
18611                    cachePaint = new Paint();
18612                    cachePaint.setDither(false);
18613                    parent.mCachePaint = cachePaint;
18614                }
18615                cachePaint.setAlpha((int) (alpha * 255));
18616                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18617            } else {
18618                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18619                int layerPaintAlpha = mLayerPaint.getAlpha();
18620                if (alpha < 1) {
18621                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18622                }
18623                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18624                if (alpha < 1) {
18625                    mLayerPaint.setAlpha(layerPaintAlpha);
18626                }
18627            }
18628        }
18629
18630        if (restoreTo >= 0) {
18631            canvas.restoreToCount(restoreTo);
18632        }
18633
18634        if (a != null && !more) {
18635            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18636                onSetAlpha(255);
18637            }
18638            parent.finishAnimatingView(this, a);
18639        }
18640
18641        if (more && hardwareAcceleratedCanvas) {
18642            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18643                // alpha animations should cause the child to recreate its display list
18644                invalidate(true);
18645            }
18646        }
18647
18648        mRecreateDisplayList = false;
18649
18650        return more;
18651    }
18652
18653    static Paint getDebugPaint() {
18654        if (sDebugPaint == null) {
18655            sDebugPaint = new Paint();
18656            sDebugPaint.setAntiAlias(false);
18657        }
18658        return sDebugPaint;
18659    }
18660
18661    final int dipsToPixels(int dips) {
18662        float scale = getContext().getResources().getDisplayMetrics().density;
18663        return (int) (dips * scale + 0.5f);
18664    }
18665
18666    final private void debugDrawFocus(Canvas canvas) {
18667        if (isFocused()) {
18668            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18669            final int l = mScrollX;
18670            final int r = l + mRight - mLeft;
18671            final int t = mScrollY;
18672            final int b = t + mBottom - mTop;
18673
18674            final Paint paint = getDebugPaint();
18675            paint.setColor(DEBUG_CORNERS_COLOR);
18676
18677            // Draw squares in corners.
18678            paint.setStyle(Paint.Style.FILL);
18679            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18680            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18681            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18682            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18683
18684            // Draw big X across the view.
18685            paint.setStyle(Paint.Style.STROKE);
18686            canvas.drawLine(l, t, r, b, paint);
18687            canvas.drawLine(l, b, r, t, paint);
18688        }
18689    }
18690
18691    /**
18692     * Manually render this view (and all of its children) to the given Canvas.
18693     * The view must have already done a full layout before this function is
18694     * called.  When implementing a view, implement
18695     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18696     * If you do need to override this method, call the superclass version.
18697     *
18698     * @param canvas The Canvas to which the View is rendered.
18699     */
18700    @CallSuper
18701    public void draw(Canvas canvas) {
18702        final int privateFlags = mPrivateFlags;
18703        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18704                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18705        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18706
18707        /*
18708         * Draw traversal performs several drawing steps which must be executed
18709         * in the appropriate order:
18710         *
18711         *      1. Draw the background
18712         *      2. If necessary, save the canvas' layers to prepare for fading
18713         *      3. Draw view's content
18714         *      4. Draw children
18715         *      5. If necessary, draw the fading edges and restore layers
18716         *      6. Draw decorations (scrollbars for instance)
18717         */
18718
18719        // Step 1, draw the background, if needed
18720        int saveCount;
18721
18722        if (!dirtyOpaque) {
18723            drawBackground(canvas);
18724        }
18725
18726        // skip step 2 & 5 if possible (common case)
18727        final int viewFlags = mViewFlags;
18728        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18729        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18730        if (!verticalEdges && !horizontalEdges) {
18731            // Step 3, draw the content
18732            if (!dirtyOpaque) onDraw(canvas);
18733
18734            // Step 4, draw the children
18735            dispatchDraw(canvas);
18736
18737            drawAutofilledHighlight(canvas);
18738
18739            // Overlay is part of the content and draws beneath Foreground
18740            if (mOverlay != null && !mOverlay.isEmpty()) {
18741                mOverlay.getOverlayView().dispatchDraw(canvas);
18742            }
18743
18744            // Step 6, draw decorations (foreground, scrollbars)
18745            onDrawForeground(canvas);
18746
18747            // Step 7, draw the default focus highlight
18748            drawDefaultFocusHighlight(canvas);
18749
18750            if (debugDraw()) {
18751                debugDrawFocus(canvas);
18752            }
18753
18754            // we're done...
18755            return;
18756        }
18757
18758        /*
18759         * Here we do the full fledged routine...
18760         * (this is an uncommon case where speed matters less,
18761         * this is why we repeat some of the tests that have been
18762         * done above)
18763         */
18764
18765        boolean drawTop = false;
18766        boolean drawBottom = false;
18767        boolean drawLeft = false;
18768        boolean drawRight = false;
18769
18770        float topFadeStrength = 0.0f;
18771        float bottomFadeStrength = 0.0f;
18772        float leftFadeStrength = 0.0f;
18773        float rightFadeStrength = 0.0f;
18774
18775        // Step 2, save the canvas' layers
18776        int paddingLeft = mPaddingLeft;
18777
18778        final boolean offsetRequired = isPaddingOffsetRequired();
18779        if (offsetRequired) {
18780            paddingLeft += getLeftPaddingOffset();
18781        }
18782
18783        int left = mScrollX + paddingLeft;
18784        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18785        int top = mScrollY + getFadeTop(offsetRequired);
18786        int bottom = top + getFadeHeight(offsetRequired);
18787
18788        if (offsetRequired) {
18789            right += getRightPaddingOffset();
18790            bottom += getBottomPaddingOffset();
18791        }
18792
18793        final ScrollabilityCache scrollabilityCache = mScrollCache;
18794        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18795        int length = (int) fadeHeight;
18796
18797        // clip the fade length if top and bottom fades overlap
18798        // overlapping fades produce odd-looking artifacts
18799        if (verticalEdges && (top + length > bottom - length)) {
18800            length = (bottom - top) / 2;
18801        }
18802
18803        // also clip horizontal fades if necessary
18804        if (horizontalEdges && (left + length > right - length)) {
18805            length = (right - left) / 2;
18806        }
18807
18808        if (verticalEdges) {
18809            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18810            drawTop = topFadeStrength * fadeHeight > 1.0f;
18811            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18812            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18813        }
18814
18815        if (horizontalEdges) {
18816            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18817            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18818            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18819            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18820        }
18821
18822        saveCount = canvas.getSaveCount();
18823
18824        int solidColor = getSolidColor();
18825        if (solidColor == 0) {
18826            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18827
18828            if (drawTop) {
18829                canvas.saveLayer(left, top, right, top + length, null, flags);
18830            }
18831
18832            if (drawBottom) {
18833                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18834            }
18835
18836            if (drawLeft) {
18837                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18838            }
18839
18840            if (drawRight) {
18841                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18842            }
18843        } else {
18844            scrollabilityCache.setFadeColor(solidColor);
18845        }
18846
18847        // Step 3, draw the content
18848        if (!dirtyOpaque) onDraw(canvas);
18849
18850        // Step 4, draw the children
18851        dispatchDraw(canvas);
18852
18853        // Step 5, draw the fade effect and restore layers
18854        final Paint p = scrollabilityCache.paint;
18855        final Matrix matrix = scrollabilityCache.matrix;
18856        final Shader fade = scrollabilityCache.shader;
18857
18858        if (drawTop) {
18859            matrix.setScale(1, fadeHeight * topFadeStrength);
18860            matrix.postTranslate(left, top);
18861            fade.setLocalMatrix(matrix);
18862            p.setShader(fade);
18863            canvas.drawRect(left, top, right, top + length, p);
18864        }
18865
18866        if (drawBottom) {
18867            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18868            matrix.postRotate(180);
18869            matrix.postTranslate(left, bottom);
18870            fade.setLocalMatrix(matrix);
18871            p.setShader(fade);
18872            canvas.drawRect(left, bottom - length, right, bottom, p);
18873        }
18874
18875        if (drawLeft) {
18876            matrix.setScale(1, fadeHeight * leftFadeStrength);
18877            matrix.postRotate(-90);
18878            matrix.postTranslate(left, top);
18879            fade.setLocalMatrix(matrix);
18880            p.setShader(fade);
18881            canvas.drawRect(left, top, left + length, bottom, p);
18882        }
18883
18884        if (drawRight) {
18885            matrix.setScale(1, fadeHeight * rightFadeStrength);
18886            matrix.postRotate(90);
18887            matrix.postTranslate(right, top);
18888            fade.setLocalMatrix(matrix);
18889            p.setShader(fade);
18890            canvas.drawRect(right - length, top, right, bottom, p);
18891        }
18892
18893        canvas.restoreToCount(saveCount);
18894
18895        drawAutofilledHighlight(canvas);
18896
18897        // Overlay is part of the content and draws beneath Foreground
18898        if (mOverlay != null && !mOverlay.isEmpty()) {
18899            mOverlay.getOverlayView().dispatchDraw(canvas);
18900        }
18901
18902        // Step 6, draw decorations (foreground, scrollbars)
18903        onDrawForeground(canvas);
18904
18905        if (debugDraw()) {
18906            debugDrawFocus(canvas);
18907        }
18908    }
18909
18910    /**
18911     * Draws the background onto the specified canvas.
18912     *
18913     * @param canvas Canvas on which to draw the background
18914     */
18915    private void drawBackground(Canvas canvas) {
18916        final Drawable background = mBackground;
18917        if (background == null) {
18918            return;
18919        }
18920
18921        setBackgroundBounds();
18922
18923        // Attempt to use a display list if requested.
18924        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18925                && mAttachInfo.mThreadedRenderer != null) {
18926            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18927
18928            final RenderNode renderNode = mBackgroundRenderNode;
18929            if (renderNode != null && renderNode.isValid()) {
18930                setBackgroundRenderNodeProperties(renderNode);
18931                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18932                return;
18933            }
18934        }
18935
18936        final int scrollX = mScrollX;
18937        final int scrollY = mScrollY;
18938        if ((scrollX | scrollY) == 0) {
18939            background.draw(canvas);
18940        } else {
18941            canvas.translate(scrollX, scrollY);
18942            background.draw(canvas);
18943            canvas.translate(-scrollX, -scrollY);
18944        }
18945    }
18946
18947    /**
18948     * Sets the correct background bounds and rebuilds the outline, if needed.
18949     * <p/>
18950     * This is called by LayoutLib.
18951     */
18952    void setBackgroundBounds() {
18953        if (mBackgroundSizeChanged && mBackground != null) {
18954            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18955            mBackgroundSizeChanged = false;
18956            rebuildOutline();
18957        }
18958    }
18959
18960    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18961        renderNode.setTranslationX(mScrollX);
18962        renderNode.setTranslationY(mScrollY);
18963    }
18964
18965    /**
18966     * Creates a new display list or updates the existing display list for the
18967     * specified Drawable.
18968     *
18969     * @param drawable Drawable for which to create a display list
18970     * @param renderNode Existing RenderNode, or {@code null}
18971     * @return A valid display list for the specified drawable
18972     */
18973    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18974        if (renderNode == null) {
18975            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18976        }
18977
18978        final Rect bounds = drawable.getBounds();
18979        final int width = bounds.width();
18980        final int height = bounds.height();
18981        final DisplayListCanvas canvas = renderNode.start(width, height);
18982
18983        // Reverse left/top translation done by drawable canvas, which will
18984        // instead be applied by rendernode's LTRB bounds below. This way, the
18985        // drawable's bounds match with its rendernode bounds and its content
18986        // will lie within those bounds in the rendernode tree.
18987        canvas.translate(-bounds.left, -bounds.top);
18988
18989        try {
18990            drawable.draw(canvas);
18991        } finally {
18992            renderNode.end(canvas);
18993        }
18994
18995        // Set up drawable properties that are view-independent.
18996        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18997        renderNode.setProjectBackwards(drawable.isProjected());
18998        renderNode.setProjectionReceiver(true);
18999        renderNode.setClipToBounds(false);
19000        return renderNode;
19001    }
19002
19003    /**
19004     * Returns the overlay for this view, creating it if it does not yet exist.
19005     * Adding drawables to the overlay will cause them to be displayed whenever
19006     * the view itself is redrawn. Objects in the overlay should be actively
19007     * managed: remove them when they should not be displayed anymore. The
19008     * overlay will always have the same size as its host view.
19009     *
19010     * <p>Note: Overlays do not currently work correctly with {@link
19011     * SurfaceView} or {@link TextureView}; contents in overlays for these
19012     * types of views may not display correctly.</p>
19013     *
19014     * @return The ViewOverlay object for this view.
19015     * @see ViewOverlay
19016     */
19017    public ViewOverlay getOverlay() {
19018        if (mOverlay == null) {
19019            mOverlay = new ViewOverlay(mContext, this);
19020        }
19021        return mOverlay;
19022    }
19023
19024    /**
19025     * Override this if your view is known to always be drawn on top of a solid color background,
19026     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19027     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19028     * should be set to 0xFF.
19029     *
19030     * @see #setVerticalFadingEdgeEnabled(boolean)
19031     * @see #setHorizontalFadingEdgeEnabled(boolean)
19032     *
19033     * @return The known solid color background for this view, or 0 if the color may vary
19034     */
19035    @ViewDebug.ExportedProperty(category = "drawing")
19036    @ColorInt
19037    public int getSolidColor() {
19038        return 0;
19039    }
19040
19041    /**
19042     * Build a human readable string representation of the specified view flags.
19043     *
19044     * @param flags the view flags to convert to a string
19045     * @return a String representing the supplied flags
19046     */
19047    private static String printFlags(int flags) {
19048        String output = "";
19049        int numFlags = 0;
19050        if ((flags & FOCUSABLE) == FOCUSABLE) {
19051            output += "TAKES_FOCUS";
19052            numFlags++;
19053        }
19054
19055        switch (flags & VISIBILITY_MASK) {
19056        case INVISIBLE:
19057            if (numFlags > 0) {
19058                output += " ";
19059            }
19060            output += "INVISIBLE";
19061            // USELESS HERE numFlags++;
19062            break;
19063        case GONE:
19064            if (numFlags > 0) {
19065                output += " ";
19066            }
19067            output += "GONE";
19068            // USELESS HERE numFlags++;
19069            break;
19070        default:
19071            break;
19072        }
19073        return output;
19074    }
19075
19076    /**
19077     * Build a human readable string representation of the specified private
19078     * view flags.
19079     *
19080     * @param privateFlags the private view flags to convert to a string
19081     * @return a String representing the supplied flags
19082     */
19083    private static String printPrivateFlags(int privateFlags) {
19084        String output = "";
19085        int numFlags = 0;
19086
19087        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19088            output += "WANTS_FOCUS";
19089            numFlags++;
19090        }
19091
19092        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19093            if (numFlags > 0) {
19094                output += " ";
19095            }
19096            output += "FOCUSED";
19097            numFlags++;
19098        }
19099
19100        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19101            if (numFlags > 0) {
19102                output += " ";
19103            }
19104            output += "SELECTED";
19105            numFlags++;
19106        }
19107
19108        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19109            if (numFlags > 0) {
19110                output += " ";
19111            }
19112            output += "IS_ROOT_NAMESPACE";
19113            numFlags++;
19114        }
19115
19116        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19117            if (numFlags > 0) {
19118                output += " ";
19119            }
19120            output += "HAS_BOUNDS";
19121            numFlags++;
19122        }
19123
19124        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19125            if (numFlags > 0) {
19126                output += " ";
19127            }
19128            output += "DRAWN";
19129            // USELESS HERE numFlags++;
19130        }
19131        return output;
19132    }
19133
19134    /**
19135     * <p>Indicates whether or not this view's layout will be requested during
19136     * the next hierarchy layout pass.</p>
19137     *
19138     * @return true if the layout will be forced during next layout pass
19139     */
19140    public boolean isLayoutRequested() {
19141        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19142    }
19143
19144    /**
19145     * Return true if o is a ViewGroup that is laying out using optical bounds.
19146     * @hide
19147     */
19148    public static boolean isLayoutModeOptical(Object o) {
19149        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19150    }
19151
19152    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19153        Insets parentInsets = mParent instanceof View ?
19154                ((View) mParent).getOpticalInsets() : Insets.NONE;
19155        Insets childInsets = getOpticalInsets();
19156        return setFrame(
19157                left   + parentInsets.left - childInsets.left,
19158                top    + parentInsets.top  - childInsets.top,
19159                right  + parentInsets.left + childInsets.right,
19160                bottom + parentInsets.top  + childInsets.bottom);
19161    }
19162
19163    /**
19164     * Assign a size and position to a view and all of its
19165     * descendants
19166     *
19167     * <p>This is the second phase of the layout mechanism.
19168     * (The first is measuring). In this phase, each parent calls
19169     * layout on all of its children to position them.
19170     * This is typically done using the child measurements
19171     * that were stored in the measure pass().</p>
19172     *
19173     * <p>Derived classes should not override this method.
19174     * Derived classes with children should override
19175     * onLayout. In that method, they should
19176     * call layout on each of their children.</p>
19177     *
19178     * @param l Left position, relative to parent
19179     * @param t Top position, relative to parent
19180     * @param r Right position, relative to parent
19181     * @param b Bottom position, relative to parent
19182     */
19183    @SuppressWarnings({"unchecked"})
19184    public void layout(int l, int t, int r, int b) {
19185        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19186            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19187            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19188        }
19189
19190        int oldL = mLeft;
19191        int oldT = mTop;
19192        int oldB = mBottom;
19193        int oldR = mRight;
19194
19195        boolean changed = isLayoutModeOptical(mParent) ?
19196                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19197
19198        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19199            onLayout(changed, l, t, r, b);
19200
19201            if (shouldDrawRoundScrollbar()) {
19202                if(mRoundScrollbarRenderer == null) {
19203                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19204                }
19205            } else {
19206                mRoundScrollbarRenderer = null;
19207            }
19208
19209            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19210
19211            ListenerInfo li = mListenerInfo;
19212            if (li != null && li.mOnLayoutChangeListeners != null) {
19213                ArrayList<OnLayoutChangeListener> listenersCopy =
19214                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19215                int numListeners = listenersCopy.size();
19216                for (int i = 0; i < numListeners; ++i) {
19217                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19218                }
19219            }
19220        }
19221
19222        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19223        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19224    }
19225
19226    /**
19227     * Called from layout when this view should
19228     * assign a size and position to each of its children.
19229     *
19230     * Derived classes with children should override
19231     * this method and call layout on each of
19232     * their children.
19233     * @param changed This is a new size or position for this view
19234     * @param left Left position, relative to parent
19235     * @param top Top position, relative to parent
19236     * @param right Right position, relative to parent
19237     * @param bottom Bottom position, relative to parent
19238     */
19239    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19240    }
19241
19242    /**
19243     * Assign a size and position to this view.
19244     *
19245     * This is called from layout.
19246     *
19247     * @param left Left position, relative to parent
19248     * @param top Top position, relative to parent
19249     * @param right Right position, relative to parent
19250     * @param bottom Bottom position, relative to parent
19251     * @return true if the new size and position are different than the
19252     *         previous ones
19253     * {@hide}
19254     */
19255    protected boolean setFrame(int left, int top, int right, int bottom) {
19256        boolean changed = false;
19257
19258        if (DBG) {
19259            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19260                    + right + "," + bottom + ")");
19261        }
19262
19263        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19264            changed = true;
19265
19266            // Remember our drawn bit
19267            int drawn = mPrivateFlags & PFLAG_DRAWN;
19268
19269            int oldWidth = mRight - mLeft;
19270            int oldHeight = mBottom - mTop;
19271            int newWidth = right - left;
19272            int newHeight = bottom - top;
19273            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19274
19275            // Invalidate our old position
19276            invalidate(sizeChanged);
19277
19278            mLeft = left;
19279            mTop = top;
19280            mRight = right;
19281            mBottom = bottom;
19282            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19283
19284            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19285
19286
19287            if (sizeChanged) {
19288                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19289            }
19290
19291            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19292                // If we are visible, force the DRAWN bit to on so that
19293                // this invalidate will go through (at least to our parent).
19294                // This is because someone may have invalidated this view
19295                // before this call to setFrame came in, thereby clearing
19296                // the DRAWN bit.
19297                mPrivateFlags |= PFLAG_DRAWN;
19298                invalidate(sizeChanged);
19299                // parent display list may need to be recreated based on a change in the bounds
19300                // of any child
19301                invalidateParentCaches();
19302            }
19303
19304            // Reset drawn bit to original value (invalidate turns it off)
19305            mPrivateFlags |= drawn;
19306
19307            mBackgroundSizeChanged = true;
19308            mDefaultFocusHighlightSizeChanged = true;
19309            if (mForegroundInfo != null) {
19310                mForegroundInfo.mBoundsChanged = true;
19311            }
19312
19313            notifySubtreeAccessibilityStateChangedIfNeeded();
19314        }
19315        return changed;
19316    }
19317
19318    /**
19319     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19320     * @hide
19321     */
19322    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19323        setFrame(left, top, right, bottom);
19324    }
19325
19326    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19327        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19328        if (mOverlay != null) {
19329            mOverlay.getOverlayView().setRight(newWidth);
19330            mOverlay.getOverlayView().setBottom(newHeight);
19331        }
19332        rebuildOutline();
19333    }
19334
19335    /**
19336     * Finalize inflating a view from XML.  This is called as the last phase
19337     * of inflation, after all child views have been added.
19338     *
19339     * <p>Even if the subclass overrides onFinishInflate, they should always be
19340     * sure to call the super method, so that we get called.
19341     */
19342    @CallSuper
19343    protected void onFinishInflate() {
19344    }
19345
19346    /**
19347     * Returns the resources associated with this view.
19348     *
19349     * @return Resources object.
19350     */
19351    public Resources getResources() {
19352        return mResources;
19353    }
19354
19355    /**
19356     * Invalidates the specified Drawable.
19357     *
19358     * @param drawable the drawable to invalidate
19359     */
19360    @Override
19361    public void invalidateDrawable(@NonNull Drawable drawable) {
19362        if (verifyDrawable(drawable)) {
19363            final Rect dirty = drawable.getDirtyBounds();
19364            final int scrollX = mScrollX;
19365            final int scrollY = mScrollY;
19366
19367            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19368                    dirty.right + scrollX, dirty.bottom + scrollY);
19369            rebuildOutline();
19370        }
19371    }
19372
19373    /**
19374     * Schedules an action on a drawable to occur at a specified time.
19375     *
19376     * @param who the recipient of the action
19377     * @param what the action to run on the drawable
19378     * @param when the time at which the action must occur. Uses the
19379     *        {@link SystemClock#uptimeMillis} timebase.
19380     */
19381    @Override
19382    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19383        if (verifyDrawable(who) && what != null) {
19384            final long delay = when - SystemClock.uptimeMillis();
19385            if (mAttachInfo != null) {
19386                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19387                        Choreographer.CALLBACK_ANIMATION, what, who,
19388                        Choreographer.subtractFrameDelay(delay));
19389            } else {
19390                // Postpone the runnable until we know
19391                // on which thread it needs to run.
19392                getRunQueue().postDelayed(what, delay);
19393            }
19394        }
19395    }
19396
19397    /**
19398     * Cancels a scheduled action on a drawable.
19399     *
19400     * @param who the recipient of the action
19401     * @param what the action to cancel
19402     */
19403    @Override
19404    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19405        if (verifyDrawable(who) && what != null) {
19406            if (mAttachInfo != null) {
19407                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19408                        Choreographer.CALLBACK_ANIMATION, what, who);
19409            }
19410            getRunQueue().removeCallbacks(what);
19411        }
19412    }
19413
19414    /**
19415     * Unschedule any events associated with the given Drawable.  This can be
19416     * used when selecting a new Drawable into a view, so that the previous
19417     * one is completely unscheduled.
19418     *
19419     * @param who The Drawable to unschedule.
19420     *
19421     * @see #drawableStateChanged
19422     */
19423    public void unscheduleDrawable(Drawable who) {
19424        if (mAttachInfo != null && who != null) {
19425            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19426                    Choreographer.CALLBACK_ANIMATION, null, who);
19427        }
19428    }
19429
19430    /**
19431     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19432     * that the View directionality can and will be resolved before its Drawables.
19433     *
19434     * Will call {@link View#onResolveDrawables} when resolution is done.
19435     *
19436     * @hide
19437     */
19438    protected void resolveDrawables() {
19439        // Drawables resolution may need to happen before resolving the layout direction (which is
19440        // done only during the measure() call).
19441        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19442        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19443        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19444        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19445        // direction to be resolved as its resolved value will be the same as its raw value.
19446        if (!isLayoutDirectionResolved() &&
19447                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19448            return;
19449        }
19450
19451        final int layoutDirection = isLayoutDirectionResolved() ?
19452                getLayoutDirection() : getRawLayoutDirection();
19453
19454        if (mBackground != null) {
19455            mBackground.setLayoutDirection(layoutDirection);
19456        }
19457        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19458            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19459        }
19460        if (mDefaultFocusHighlight != null) {
19461            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19462        }
19463        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19464        onResolveDrawables(layoutDirection);
19465    }
19466
19467    boolean areDrawablesResolved() {
19468        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19469    }
19470
19471    /**
19472     * Called when layout direction has been resolved.
19473     *
19474     * The default implementation does nothing.
19475     *
19476     * @param layoutDirection The resolved layout direction.
19477     *
19478     * @see #LAYOUT_DIRECTION_LTR
19479     * @see #LAYOUT_DIRECTION_RTL
19480     *
19481     * @hide
19482     */
19483    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19484    }
19485
19486    /**
19487     * @hide
19488     */
19489    protected void resetResolvedDrawables() {
19490        resetResolvedDrawablesInternal();
19491    }
19492
19493    void resetResolvedDrawablesInternal() {
19494        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19495    }
19496
19497    /**
19498     * If your view subclass is displaying its own Drawable objects, it should
19499     * override this function and return true for any Drawable it is
19500     * displaying.  This allows animations for those drawables to be
19501     * scheduled.
19502     *
19503     * <p>Be sure to call through to the super class when overriding this
19504     * function.
19505     *
19506     * @param who The Drawable to verify.  Return true if it is one you are
19507     *            displaying, else return the result of calling through to the
19508     *            super class.
19509     *
19510     * @return boolean If true than the Drawable is being displayed in the
19511     *         view; else false and it is not allowed to animate.
19512     *
19513     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19514     * @see #drawableStateChanged()
19515     */
19516    @CallSuper
19517    protected boolean verifyDrawable(@NonNull Drawable who) {
19518        // Avoid verifying the scroll bar drawable so that we don't end up in
19519        // an invalidation loop. This effectively prevents the scroll bar
19520        // drawable from triggering invalidations and scheduling runnables.
19521        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19522                || (mDefaultFocusHighlight == who);
19523    }
19524
19525    /**
19526     * This function is called whenever the state of the view changes in such
19527     * a way that it impacts the state of drawables being shown.
19528     * <p>
19529     * If the View has a StateListAnimator, it will also be called to run necessary state
19530     * change animations.
19531     * <p>
19532     * Be sure to call through to the superclass when overriding this function.
19533     *
19534     * @see Drawable#setState(int[])
19535     */
19536    @CallSuper
19537    protected void drawableStateChanged() {
19538        final int[] state = getDrawableState();
19539        boolean changed = false;
19540
19541        final Drawable bg = mBackground;
19542        if (bg != null && bg.isStateful()) {
19543            changed |= bg.setState(state);
19544        }
19545
19546        final Drawable hl = mDefaultFocusHighlight;
19547        if (hl != null && hl.isStateful()) {
19548            changed |= hl.setState(state);
19549        }
19550
19551        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19552        if (fg != null && fg.isStateful()) {
19553            changed |= fg.setState(state);
19554        }
19555
19556        if (mScrollCache != null) {
19557            final Drawable scrollBar = mScrollCache.scrollBar;
19558            if (scrollBar != null && scrollBar.isStateful()) {
19559                changed |= scrollBar.setState(state)
19560                        && mScrollCache.state != ScrollabilityCache.OFF;
19561            }
19562        }
19563
19564        if (mStateListAnimator != null) {
19565            mStateListAnimator.setState(state);
19566        }
19567
19568        if (changed) {
19569            invalidate();
19570        }
19571    }
19572
19573    /**
19574     * This function is called whenever the view hotspot changes and needs to
19575     * be propagated to drawables or child views managed by the view.
19576     * <p>
19577     * Dispatching to child views is handled by
19578     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19579     * <p>
19580     * Be sure to call through to the superclass when overriding this function.
19581     *
19582     * @param x hotspot x coordinate
19583     * @param y hotspot y coordinate
19584     */
19585    @CallSuper
19586    public void drawableHotspotChanged(float x, float y) {
19587        if (mBackground != null) {
19588            mBackground.setHotspot(x, y);
19589        }
19590        if (mDefaultFocusHighlight != null) {
19591            mDefaultFocusHighlight.setHotspot(x, y);
19592        }
19593        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19594            mForegroundInfo.mDrawable.setHotspot(x, y);
19595        }
19596
19597        dispatchDrawableHotspotChanged(x, y);
19598    }
19599
19600    /**
19601     * Dispatches drawableHotspotChanged to all of this View's children.
19602     *
19603     * @param x hotspot x coordinate
19604     * @param y hotspot y coordinate
19605     * @see #drawableHotspotChanged(float, float)
19606     */
19607    public void dispatchDrawableHotspotChanged(float x, float y) {
19608    }
19609
19610    /**
19611     * Call this to force a view to update its drawable state. This will cause
19612     * drawableStateChanged to be called on this view. Views that are interested
19613     * in the new state should call getDrawableState.
19614     *
19615     * @see #drawableStateChanged
19616     * @see #getDrawableState
19617     */
19618    public void refreshDrawableState() {
19619        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19620        drawableStateChanged();
19621
19622        ViewParent parent = mParent;
19623        if (parent != null) {
19624            parent.childDrawableStateChanged(this);
19625        }
19626    }
19627
19628    /**
19629     * Create a default focus highlight if it doesn't exist.
19630     * @return a default focus highlight.
19631     */
19632    private Drawable getDefaultFocusHighlightDrawable() {
19633        if (mDefaultFocusHighlightCache == null) {
19634            if (mContext != null) {
19635                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
19636                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
19637                mDefaultFocusHighlightCache = ta.getDrawable(0);
19638                ta.recycle();
19639            }
19640        }
19641        return mDefaultFocusHighlightCache;
19642    }
19643
19644    /**
19645     * Set the current default focus highlight.
19646     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
19647     */
19648    private void setDefaultFocusHighlight(Drawable highlight) {
19649        mDefaultFocusHighlight = highlight;
19650        mDefaultFocusHighlightSizeChanged = true;
19651        if (highlight != null) {
19652            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19653                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19654            }
19655            highlight.setLayoutDirection(getLayoutDirection());
19656            if (highlight.isStateful()) {
19657                highlight.setState(getDrawableState());
19658            }
19659            if (isAttachedToWindow()) {
19660                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19661            }
19662            // Set callback last, since the view may still be initializing.
19663            highlight.setCallback(this);
19664        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
19665                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19666            mPrivateFlags |= PFLAG_SKIP_DRAW;
19667        }
19668        requestLayout();
19669        invalidate();
19670    }
19671
19672    /**
19673     * Check whether we need to draw a default focus highlight when this view gets focused,
19674     * which requires:
19675     * <ul>
19676     *     <li>In the background, {@link android.R.attr#state_focused} is not defined.</li>
19677     *     <li>This view is not in touch mode.</li>
19678     *     <li>This view doesn't opt out for a default focus highlight, via
19679     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
19680     *     <li>This view is attached to window.</li>
19681     * </ul>
19682     * @return {@code true} if a default focus highlight is needed.
19683     */
19684    private boolean isDefaultFocusHighlightNeeded(Drawable background) {
19685        final boolean hasFocusStateSpecified = background == null || !background.isStateful()
19686                || !background.hasFocusStateSpecified();
19687        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
19688                && isAttachedToWindow() && sUseDefaultFocusHighlight;
19689    }
19690
19691    /**
19692     * When this view is focused, switches on/off the default focused highlight.
19693     * <p>
19694     * This always happens when this view is focused, and only at this moment the default focus
19695     * highlight can be visible.
19696     */
19697    private void switchDefaultFocusHighlight() {
19698        if (isFocused()) {
19699            final boolean needed = isDefaultFocusHighlightNeeded(mBackground);
19700            final boolean active = mDefaultFocusHighlight != null;
19701            if (needed && !active) {
19702                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
19703            } else if (!needed && active) {
19704                // The highlight is no longer needed, so tear it down.
19705                setDefaultFocusHighlight(null);
19706            }
19707        }
19708    }
19709
19710    /**
19711     * Draw the default focus highlight onto the canvas.
19712     * @param canvas the canvas where we're drawing the highlight.
19713     */
19714    private void drawDefaultFocusHighlight(Canvas canvas) {
19715        if (mDefaultFocusHighlight != null) {
19716            if (mDefaultFocusHighlightSizeChanged) {
19717                mDefaultFocusHighlightSizeChanged = false;
19718                final int l = mScrollX;
19719                final int r = l + mRight - mLeft;
19720                final int t = mScrollY;
19721                final int b = t + mBottom - mTop;
19722                mDefaultFocusHighlight.setBounds(l, t, r, b);
19723            }
19724            mDefaultFocusHighlight.draw(canvas);
19725        }
19726    }
19727
19728    /**
19729     * Return an array of resource IDs of the drawable states representing the
19730     * current state of the view.
19731     *
19732     * @return The current drawable state
19733     *
19734     * @see Drawable#setState(int[])
19735     * @see #drawableStateChanged()
19736     * @see #onCreateDrawableState(int)
19737     */
19738    public final int[] getDrawableState() {
19739        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19740            return mDrawableState;
19741        } else {
19742            mDrawableState = onCreateDrawableState(0);
19743            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19744            return mDrawableState;
19745        }
19746    }
19747
19748    /**
19749     * Generate the new {@link android.graphics.drawable.Drawable} state for
19750     * this view. This is called by the view
19751     * system when the cached Drawable state is determined to be invalid.  To
19752     * retrieve the current state, you should use {@link #getDrawableState}.
19753     *
19754     * @param extraSpace if non-zero, this is the number of extra entries you
19755     * would like in the returned array in which you can place your own
19756     * states.
19757     *
19758     * @return Returns an array holding the current {@link Drawable} state of
19759     * the view.
19760     *
19761     * @see #mergeDrawableStates(int[], int[])
19762     */
19763    protected int[] onCreateDrawableState(int extraSpace) {
19764        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19765                mParent instanceof View) {
19766            return ((View) mParent).onCreateDrawableState(extraSpace);
19767        }
19768
19769        int[] drawableState;
19770
19771        int privateFlags = mPrivateFlags;
19772
19773        int viewStateIndex = 0;
19774        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19775        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19776        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19777        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19778        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19779        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19780        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19781                ThreadedRenderer.isAvailable()) {
19782            // This is set if HW acceleration is requested, even if the current
19783            // process doesn't allow it.  This is just to allow app preview
19784            // windows to better match their app.
19785            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19786        }
19787        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19788
19789        final int privateFlags2 = mPrivateFlags2;
19790        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19791            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19792        }
19793        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19794            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19795        }
19796
19797        drawableState = StateSet.get(viewStateIndex);
19798
19799        //noinspection ConstantIfStatement
19800        if (false) {
19801            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19802            Log.i("View", toString()
19803                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19804                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19805                    + " fo=" + hasFocus()
19806                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19807                    + " wf=" + hasWindowFocus()
19808                    + ": " + Arrays.toString(drawableState));
19809        }
19810
19811        if (extraSpace == 0) {
19812            return drawableState;
19813        }
19814
19815        final int[] fullState;
19816        if (drawableState != null) {
19817            fullState = new int[drawableState.length + extraSpace];
19818            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19819        } else {
19820            fullState = new int[extraSpace];
19821        }
19822
19823        return fullState;
19824    }
19825
19826    /**
19827     * Merge your own state values in <var>additionalState</var> into the base
19828     * state values <var>baseState</var> that were returned by
19829     * {@link #onCreateDrawableState(int)}.
19830     *
19831     * @param baseState The base state values returned by
19832     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19833     * own additional state values.
19834     *
19835     * @param additionalState The additional state values you would like
19836     * added to <var>baseState</var>; this array is not modified.
19837     *
19838     * @return As a convenience, the <var>baseState</var> array you originally
19839     * passed into the function is returned.
19840     *
19841     * @see #onCreateDrawableState(int)
19842     */
19843    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19844        final int N = baseState.length;
19845        int i = N - 1;
19846        while (i >= 0 && baseState[i] == 0) {
19847            i--;
19848        }
19849        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19850        return baseState;
19851    }
19852
19853    /**
19854     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19855     * on all Drawable objects associated with this view.
19856     * <p>
19857     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19858     * attached to this view.
19859     */
19860    @CallSuper
19861    public void jumpDrawablesToCurrentState() {
19862        if (mBackground != null) {
19863            mBackground.jumpToCurrentState();
19864        }
19865        if (mStateListAnimator != null) {
19866            mStateListAnimator.jumpToCurrentState();
19867        }
19868        if (mDefaultFocusHighlight != null) {
19869            mDefaultFocusHighlight.jumpToCurrentState();
19870        }
19871        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19872            mForegroundInfo.mDrawable.jumpToCurrentState();
19873        }
19874    }
19875
19876    /**
19877     * Sets the background color for this view.
19878     * @param color the color of the background
19879     */
19880    @RemotableViewMethod
19881    public void setBackgroundColor(@ColorInt int color) {
19882        if (mBackground instanceof ColorDrawable) {
19883            ((ColorDrawable) mBackground.mutate()).setColor(color);
19884            computeOpaqueFlags();
19885            mBackgroundResource = 0;
19886        } else {
19887            setBackground(new ColorDrawable(color));
19888        }
19889    }
19890
19891    /**
19892     * Set the background to a given resource. The resource should refer to
19893     * a Drawable object or 0 to remove the background.
19894     * @param resid The identifier of the resource.
19895     *
19896     * @attr ref android.R.styleable#View_background
19897     */
19898    @RemotableViewMethod
19899    public void setBackgroundResource(@DrawableRes int resid) {
19900        if (resid != 0 && resid == mBackgroundResource) {
19901            return;
19902        }
19903
19904        Drawable d = null;
19905        if (resid != 0) {
19906            d = mContext.getDrawable(resid);
19907        }
19908        setBackground(d);
19909
19910        mBackgroundResource = resid;
19911    }
19912
19913    /**
19914     * Set the background to a given Drawable, or remove the background. If the
19915     * background has padding, this View's padding is set to the background's
19916     * padding. However, when a background is removed, this View's padding isn't
19917     * touched. If setting the padding is desired, please use
19918     * {@link #setPadding(int, int, int, int)}.
19919     *
19920     * @param background The Drawable to use as the background, or null to remove the
19921     *        background
19922     */
19923    public void setBackground(Drawable background) {
19924        //noinspection deprecation
19925        setBackgroundDrawable(background);
19926    }
19927
19928    /**
19929     * @deprecated use {@link #setBackground(Drawable)} instead
19930     */
19931    @Deprecated
19932    public void setBackgroundDrawable(Drawable background) {
19933        computeOpaqueFlags();
19934
19935        if (background == mBackground) {
19936            return;
19937        }
19938
19939        boolean requestLayout = false;
19940
19941        mBackgroundResource = 0;
19942
19943        /*
19944         * Regardless of whether we're setting a new background or not, we want
19945         * to clear the previous drawable. setVisible first while we still have the callback set.
19946         */
19947        if (mBackground != null) {
19948            if (isAttachedToWindow()) {
19949                mBackground.setVisible(false, false);
19950            }
19951            mBackground.setCallback(null);
19952            unscheduleDrawable(mBackground);
19953        }
19954
19955        if (background != null) {
19956            Rect padding = sThreadLocal.get();
19957            if (padding == null) {
19958                padding = new Rect();
19959                sThreadLocal.set(padding);
19960            }
19961            resetResolvedDrawablesInternal();
19962            background.setLayoutDirection(getLayoutDirection());
19963            if (background.getPadding(padding)) {
19964                resetResolvedPaddingInternal();
19965                switch (background.getLayoutDirection()) {
19966                    case LAYOUT_DIRECTION_RTL:
19967                        mUserPaddingLeftInitial = padding.right;
19968                        mUserPaddingRightInitial = padding.left;
19969                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19970                        break;
19971                    case LAYOUT_DIRECTION_LTR:
19972                    default:
19973                        mUserPaddingLeftInitial = padding.left;
19974                        mUserPaddingRightInitial = padding.right;
19975                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19976                }
19977                mLeftPaddingDefined = false;
19978                mRightPaddingDefined = false;
19979            }
19980
19981            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19982            // if it has a different minimum size, we should layout again
19983            if (mBackground == null
19984                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19985                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19986                requestLayout = true;
19987            }
19988
19989            // Set mBackground before we set this as the callback and start making other
19990            // background drawable state change calls. In particular, the setVisible call below
19991            // can result in drawables attempting to start animations or otherwise invalidate,
19992            // which requires the view set as the callback (us) to recognize the drawable as
19993            // belonging to it as per verifyDrawable.
19994            mBackground = background;
19995            if (background.isStateful()) {
19996                background.setState(getDrawableState());
19997            }
19998            if (isAttachedToWindow()) {
19999                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20000            }
20001
20002            applyBackgroundTint();
20003
20004            // Set callback last, since the view may still be initializing.
20005            background.setCallback(this);
20006
20007            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20008                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20009                requestLayout = true;
20010            }
20011        } else {
20012            /* Remove the background */
20013            mBackground = null;
20014            if ((mViewFlags & WILL_NOT_DRAW) != 0
20015                    && (mDefaultFocusHighlight == null)
20016                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20017                mPrivateFlags |= PFLAG_SKIP_DRAW;
20018            }
20019
20020            /*
20021             * When the background is set, we try to apply its padding to this
20022             * View. When the background is removed, we don't touch this View's
20023             * padding. This is noted in the Javadocs. Hence, we don't need to
20024             * requestLayout(), the invalidate() below is sufficient.
20025             */
20026
20027            // The old background's minimum size could have affected this
20028            // View's layout, so let's requestLayout
20029            requestLayout = true;
20030        }
20031
20032        computeOpaqueFlags();
20033
20034        if (requestLayout) {
20035            requestLayout();
20036        }
20037
20038        mBackgroundSizeChanged = true;
20039        invalidate(true);
20040        invalidateOutline();
20041    }
20042
20043    /**
20044     * Gets the background drawable
20045     *
20046     * @return The drawable used as the background for this view, if any.
20047     *
20048     * @see #setBackground(Drawable)
20049     *
20050     * @attr ref android.R.styleable#View_background
20051     */
20052    public Drawable getBackground() {
20053        return mBackground;
20054    }
20055
20056    /**
20057     * Applies a tint to the background drawable. Does not modify the current tint
20058     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20059     * <p>
20060     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20061     * mutate the drawable and apply the specified tint and tint mode using
20062     * {@link Drawable#setTintList(ColorStateList)}.
20063     *
20064     * @param tint the tint to apply, may be {@code null} to clear tint
20065     *
20066     * @attr ref android.R.styleable#View_backgroundTint
20067     * @see #getBackgroundTintList()
20068     * @see Drawable#setTintList(ColorStateList)
20069     */
20070    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20071        if (mBackgroundTint == null) {
20072            mBackgroundTint = new TintInfo();
20073        }
20074        mBackgroundTint.mTintList = tint;
20075        mBackgroundTint.mHasTintList = true;
20076
20077        applyBackgroundTint();
20078    }
20079
20080    /**
20081     * Return the tint applied to the background drawable, if specified.
20082     *
20083     * @return the tint applied to the background drawable
20084     * @attr ref android.R.styleable#View_backgroundTint
20085     * @see #setBackgroundTintList(ColorStateList)
20086     */
20087    @Nullable
20088    public ColorStateList getBackgroundTintList() {
20089        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20090    }
20091
20092    /**
20093     * Specifies the blending mode used to apply the tint specified by
20094     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20095     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20096     *
20097     * @param tintMode the blending mode used to apply the tint, may be
20098     *                 {@code null} to clear tint
20099     * @attr ref android.R.styleable#View_backgroundTintMode
20100     * @see #getBackgroundTintMode()
20101     * @see Drawable#setTintMode(PorterDuff.Mode)
20102     */
20103    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20104        if (mBackgroundTint == null) {
20105            mBackgroundTint = new TintInfo();
20106        }
20107        mBackgroundTint.mTintMode = tintMode;
20108        mBackgroundTint.mHasTintMode = true;
20109
20110        applyBackgroundTint();
20111    }
20112
20113    /**
20114     * Return the blending mode used to apply the tint to the background
20115     * drawable, if specified.
20116     *
20117     * @return the blending mode used to apply the tint to the background
20118     *         drawable
20119     * @attr ref android.R.styleable#View_backgroundTintMode
20120     * @see #setBackgroundTintMode(PorterDuff.Mode)
20121     */
20122    @Nullable
20123    public PorterDuff.Mode getBackgroundTintMode() {
20124        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20125    }
20126
20127    private void applyBackgroundTint() {
20128        if (mBackground != null && mBackgroundTint != null) {
20129            final TintInfo tintInfo = mBackgroundTint;
20130            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20131                mBackground = mBackground.mutate();
20132
20133                if (tintInfo.mHasTintList) {
20134                    mBackground.setTintList(tintInfo.mTintList);
20135                }
20136
20137                if (tintInfo.mHasTintMode) {
20138                    mBackground.setTintMode(tintInfo.mTintMode);
20139                }
20140
20141                // The drawable (or one of its children) may not have been
20142                // stateful before applying the tint, so let's try again.
20143                if (mBackground.isStateful()) {
20144                    mBackground.setState(getDrawableState());
20145                }
20146            }
20147        }
20148    }
20149
20150    /**
20151     * Returns the drawable used as the foreground of this View. The
20152     * foreground drawable, if non-null, is always drawn on top of the view's content.
20153     *
20154     * @return a Drawable or null if no foreground was set
20155     *
20156     * @see #onDrawForeground(Canvas)
20157     */
20158    public Drawable getForeground() {
20159        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20160    }
20161
20162    /**
20163     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20164     *
20165     * @param foreground the Drawable to be drawn on top of the children
20166     *
20167     * @attr ref android.R.styleable#View_foreground
20168     */
20169    public void setForeground(Drawable foreground) {
20170        if (mForegroundInfo == null) {
20171            if (foreground == null) {
20172                // Nothing to do.
20173                return;
20174            }
20175            mForegroundInfo = new ForegroundInfo();
20176        }
20177
20178        if (foreground == mForegroundInfo.mDrawable) {
20179            // Nothing to do
20180            return;
20181        }
20182
20183        if (mForegroundInfo.mDrawable != null) {
20184            if (isAttachedToWindow()) {
20185                mForegroundInfo.mDrawable.setVisible(false, false);
20186            }
20187            mForegroundInfo.mDrawable.setCallback(null);
20188            unscheduleDrawable(mForegroundInfo.mDrawable);
20189        }
20190
20191        mForegroundInfo.mDrawable = foreground;
20192        mForegroundInfo.mBoundsChanged = true;
20193        if (foreground != null) {
20194            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20195                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20196            }
20197            foreground.setLayoutDirection(getLayoutDirection());
20198            if (foreground.isStateful()) {
20199                foreground.setState(getDrawableState());
20200            }
20201            applyForegroundTint();
20202            if (isAttachedToWindow()) {
20203                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20204            }
20205            // Set callback last, since the view may still be initializing.
20206            foreground.setCallback(this);
20207        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20208                && (mDefaultFocusHighlight == null)) {
20209            mPrivateFlags |= PFLAG_SKIP_DRAW;
20210        }
20211        requestLayout();
20212        invalidate();
20213    }
20214
20215    /**
20216     * Magic bit used to support features of framework-internal window decor implementation details.
20217     * This used to live exclusively in FrameLayout.
20218     *
20219     * @return true if the foreground should draw inside the padding region or false
20220     *         if it should draw inset by the view's padding
20221     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20222     */
20223    public boolean isForegroundInsidePadding() {
20224        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20225    }
20226
20227    /**
20228     * Describes how the foreground is positioned.
20229     *
20230     * @return foreground gravity.
20231     *
20232     * @see #setForegroundGravity(int)
20233     *
20234     * @attr ref android.R.styleable#View_foregroundGravity
20235     */
20236    public int getForegroundGravity() {
20237        return mForegroundInfo != null ? mForegroundInfo.mGravity
20238                : Gravity.START | Gravity.TOP;
20239    }
20240
20241    /**
20242     * Describes how the foreground is positioned. Defaults to START and TOP.
20243     *
20244     * @param gravity see {@link android.view.Gravity}
20245     *
20246     * @see #getForegroundGravity()
20247     *
20248     * @attr ref android.R.styleable#View_foregroundGravity
20249     */
20250    public void setForegroundGravity(int gravity) {
20251        if (mForegroundInfo == null) {
20252            mForegroundInfo = new ForegroundInfo();
20253        }
20254
20255        if (mForegroundInfo.mGravity != gravity) {
20256            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20257                gravity |= Gravity.START;
20258            }
20259
20260            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20261                gravity |= Gravity.TOP;
20262            }
20263
20264            mForegroundInfo.mGravity = gravity;
20265            requestLayout();
20266        }
20267    }
20268
20269    /**
20270     * Applies a tint to the foreground drawable. Does not modify the current tint
20271     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20272     * <p>
20273     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20274     * mutate the drawable and apply the specified tint and tint mode using
20275     * {@link Drawable#setTintList(ColorStateList)}.
20276     *
20277     * @param tint the tint to apply, may be {@code null} to clear tint
20278     *
20279     * @attr ref android.R.styleable#View_foregroundTint
20280     * @see #getForegroundTintList()
20281     * @see Drawable#setTintList(ColorStateList)
20282     */
20283    public void setForegroundTintList(@Nullable ColorStateList tint) {
20284        if (mForegroundInfo == null) {
20285            mForegroundInfo = new ForegroundInfo();
20286        }
20287        if (mForegroundInfo.mTintInfo == null) {
20288            mForegroundInfo.mTintInfo = new TintInfo();
20289        }
20290        mForegroundInfo.mTintInfo.mTintList = tint;
20291        mForegroundInfo.mTintInfo.mHasTintList = true;
20292
20293        applyForegroundTint();
20294    }
20295
20296    /**
20297     * Return the tint applied to the foreground drawable, if specified.
20298     *
20299     * @return the tint applied to the foreground drawable
20300     * @attr ref android.R.styleable#View_foregroundTint
20301     * @see #setForegroundTintList(ColorStateList)
20302     */
20303    @Nullable
20304    public ColorStateList getForegroundTintList() {
20305        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20306                ? mForegroundInfo.mTintInfo.mTintList : null;
20307    }
20308
20309    /**
20310     * Specifies the blending mode used to apply the tint specified by
20311     * {@link #setForegroundTintList(ColorStateList)}} to the background
20312     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20313     *
20314     * @param tintMode the blending mode used to apply the tint, may be
20315     *                 {@code null} to clear tint
20316     * @attr ref android.R.styleable#View_foregroundTintMode
20317     * @see #getForegroundTintMode()
20318     * @see Drawable#setTintMode(PorterDuff.Mode)
20319     */
20320    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20321        if (mForegroundInfo == null) {
20322            mForegroundInfo = new ForegroundInfo();
20323        }
20324        if (mForegroundInfo.mTintInfo == null) {
20325            mForegroundInfo.mTintInfo = new TintInfo();
20326        }
20327        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20328        mForegroundInfo.mTintInfo.mHasTintMode = true;
20329
20330        applyForegroundTint();
20331    }
20332
20333    /**
20334     * Return the blending mode used to apply the tint to the foreground
20335     * drawable, if specified.
20336     *
20337     * @return the blending mode used to apply the tint to the foreground
20338     *         drawable
20339     * @attr ref android.R.styleable#View_foregroundTintMode
20340     * @see #setForegroundTintMode(PorterDuff.Mode)
20341     */
20342    @Nullable
20343    public PorterDuff.Mode getForegroundTintMode() {
20344        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20345                ? mForegroundInfo.mTintInfo.mTintMode : null;
20346    }
20347
20348    private void applyForegroundTint() {
20349        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20350                && mForegroundInfo.mTintInfo != null) {
20351            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20352            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20353                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20354
20355                if (tintInfo.mHasTintList) {
20356                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20357                }
20358
20359                if (tintInfo.mHasTintMode) {
20360                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20361                }
20362
20363                // The drawable (or one of its children) may not have been
20364                // stateful before applying the tint, so let's try again.
20365                if (mForegroundInfo.mDrawable.isStateful()) {
20366                    mForegroundInfo.mDrawable.setState(getDrawableState());
20367                }
20368            }
20369        }
20370    }
20371
20372    /**
20373     * Get the drawable to be overlayed when a view is autofilled
20374     *
20375     * @return The drawable
20376     *
20377     * @throws IllegalStateException if the drawable could not be found.
20378     */
20379    @NonNull private Drawable getAutofilledDrawable() {
20380        // Lazily load the isAutofilled drawable.
20381        if (mAttachInfo.mAutofilledDrawable == null) {
20382            mAttachInfo.mAutofilledDrawable = mContext.getDrawable(R.drawable.autofilled_highlight);
20383
20384            if (mAttachInfo.mAutofilledDrawable == null) {
20385                throw new IllegalStateException(
20386                        "Could not find android:drawable/autofilled_highlight");
20387            }
20388        }
20389
20390        return mAttachInfo.mAutofilledDrawable;
20391    }
20392
20393    /**
20394     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20395     *
20396     * @param canvas The canvas to draw on
20397     */
20398    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20399        if (isAutofilled()) {
20400            Drawable autofilledHighlight = getAutofilledDrawable();
20401
20402            autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20403            autofilledHighlight.draw(canvas);
20404        }
20405    }
20406
20407    /**
20408     * Draw any foreground content for this view.
20409     *
20410     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20411     * drawable or other view-specific decorations. The foreground is drawn on top of the
20412     * primary view content.</p>
20413     *
20414     * @param canvas canvas to draw into
20415     */
20416    public void onDrawForeground(Canvas canvas) {
20417        onDrawScrollIndicators(canvas);
20418        onDrawScrollBars(canvas);
20419
20420        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20421        if (foreground != null) {
20422            if (mForegroundInfo.mBoundsChanged) {
20423                mForegroundInfo.mBoundsChanged = false;
20424                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20425                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20426
20427                if (mForegroundInfo.mInsidePadding) {
20428                    selfBounds.set(0, 0, getWidth(), getHeight());
20429                } else {
20430                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20431                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20432                }
20433
20434                final int ld = getLayoutDirection();
20435                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20436                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20437                foreground.setBounds(overlayBounds);
20438            }
20439
20440            foreground.draw(canvas);
20441        }
20442    }
20443
20444    /**
20445     * Sets the padding. The view may add on the space required to display
20446     * the scrollbars, depending on the style and visibility of the scrollbars.
20447     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20448     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20449     * from the values set in this call.
20450     *
20451     * @attr ref android.R.styleable#View_padding
20452     * @attr ref android.R.styleable#View_paddingBottom
20453     * @attr ref android.R.styleable#View_paddingLeft
20454     * @attr ref android.R.styleable#View_paddingRight
20455     * @attr ref android.R.styleable#View_paddingTop
20456     * @param left the left padding in pixels
20457     * @param top the top padding in pixels
20458     * @param right the right padding in pixels
20459     * @param bottom the bottom padding in pixels
20460     */
20461    public void setPadding(int left, int top, int right, int bottom) {
20462        resetResolvedPaddingInternal();
20463
20464        mUserPaddingStart = UNDEFINED_PADDING;
20465        mUserPaddingEnd = UNDEFINED_PADDING;
20466
20467        mUserPaddingLeftInitial = left;
20468        mUserPaddingRightInitial = right;
20469
20470        mLeftPaddingDefined = true;
20471        mRightPaddingDefined = true;
20472
20473        internalSetPadding(left, top, right, bottom);
20474    }
20475
20476    /**
20477     * @hide
20478     */
20479    protected void internalSetPadding(int left, int top, int right, int bottom) {
20480        mUserPaddingLeft = left;
20481        mUserPaddingRight = right;
20482        mUserPaddingBottom = bottom;
20483
20484        final int viewFlags = mViewFlags;
20485        boolean changed = false;
20486
20487        // Common case is there are no scroll bars.
20488        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20489            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20490                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20491                        ? 0 : getVerticalScrollbarWidth();
20492                switch (mVerticalScrollbarPosition) {
20493                    case SCROLLBAR_POSITION_DEFAULT:
20494                        if (isLayoutRtl()) {
20495                            left += offset;
20496                        } else {
20497                            right += offset;
20498                        }
20499                        break;
20500                    case SCROLLBAR_POSITION_RIGHT:
20501                        right += offset;
20502                        break;
20503                    case SCROLLBAR_POSITION_LEFT:
20504                        left += offset;
20505                        break;
20506                }
20507            }
20508            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20509                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20510                        ? 0 : getHorizontalScrollbarHeight();
20511            }
20512        }
20513
20514        if (mPaddingLeft != left) {
20515            changed = true;
20516            mPaddingLeft = left;
20517        }
20518        if (mPaddingTop != top) {
20519            changed = true;
20520            mPaddingTop = top;
20521        }
20522        if (mPaddingRight != right) {
20523            changed = true;
20524            mPaddingRight = right;
20525        }
20526        if (mPaddingBottom != bottom) {
20527            changed = true;
20528            mPaddingBottom = bottom;
20529        }
20530
20531        if (changed) {
20532            requestLayout();
20533            invalidateOutline();
20534        }
20535    }
20536
20537    /**
20538     * Sets the relative padding. The view may add on the space required to display
20539     * the scrollbars, depending on the style and visibility of the scrollbars.
20540     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20541     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20542     * from the values set in this call.
20543     *
20544     * @attr ref android.R.styleable#View_padding
20545     * @attr ref android.R.styleable#View_paddingBottom
20546     * @attr ref android.R.styleable#View_paddingStart
20547     * @attr ref android.R.styleable#View_paddingEnd
20548     * @attr ref android.R.styleable#View_paddingTop
20549     * @param start the start padding in pixels
20550     * @param top the top padding in pixels
20551     * @param end the end padding in pixels
20552     * @param bottom the bottom padding in pixels
20553     */
20554    public void setPaddingRelative(int start, int top, int end, int bottom) {
20555        resetResolvedPaddingInternal();
20556
20557        mUserPaddingStart = start;
20558        mUserPaddingEnd = end;
20559        mLeftPaddingDefined = true;
20560        mRightPaddingDefined = true;
20561
20562        switch(getLayoutDirection()) {
20563            case LAYOUT_DIRECTION_RTL:
20564                mUserPaddingLeftInitial = end;
20565                mUserPaddingRightInitial = start;
20566                internalSetPadding(end, top, start, bottom);
20567                break;
20568            case LAYOUT_DIRECTION_LTR:
20569            default:
20570                mUserPaddingLeftInitial = start;
20571                mUserPaddingRightInitial = end;
20572                internalSetPadding(start, top, end, bottom);
20573        }
20574    }
20575
20576    /**
20577     * Returns the top padding of this view.
20578     *
20579     * @return the top padding in pixels
20580     */
20581    public int getPaddingTop() {
20582        return mPaddingTop;
20583    }
20584
20585    /**
20586     * Returns the bottom padding of this view. If there are inset and enabled
20587     * scrollbars, this value may include the space required to display the
20588     * scrollbars as well.
20589     *
20590     * @return the bottom padding in pixels
20591     */
20592    public int getPaddingBottom() {
20593        return mPaddingBottom;
20594    }
20595
20596    /**
20597     * Returns the left padding of this view. If there are inset and enabled
20598     * scrollbars, this value may include the space required to display the
20599     * scrollbars as well.
20600     *
20601     * @return the left padding in pixels
20602     */
20603    public int getPaddingLeft() {
20604        if (!isPaddingResolved()) {
20605            resolvePadding();
20606        }
20607        return mPaddingLeft;
20608    }
20609
20610    /**
20611     * Returns the start padding of this view depending on its resolved layout direction.
20612     * If there are inset and enabled scrollbars, this value may include the space
20613     * required to display the scrollbars as well.
20614     *
20615     * @return the start padding in pixels
20616     */
20617    public int getPaddingStart() {
20618        if (!isPaddingResolved()) {
20619            resolvePadding();
20620        }
20621        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20622                mPaddingRight : mPaddingLeft;
20623    }
20624
20625    /**
20626     * Returns the right padding of this view. If there are inset and enabled
20627     * scrollbars, this value may include the space required to display the
20628     * scrollbars as well.
20629     *
20630     * @return the right padding in pixels
20631     */
20632    public int getPaddingRight() {
20633        if (!isPaddingResolved()) {
20634            resolvePadding();
20635        }
20636        return mPaddingRight;
20637    }
20638
20639    /**
20640     * Returns the end padding of this view depending on its resolved layout direction.
20641     * If there are inset and enabled scrollbars, this value may include the space
20642     * required to display the scrollbars as well.
20643     *
20644     * @return the end padding in pixels
20645     */
20646    public int getPaddingEnd() {
20647        if (!isPaddingResolved()) {
20648            resolvePadding();
20649        }
20650        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20651                mPaddingLeft : mPaddingRight;
20652    }
20653
20654    /**
20655     * Return if the padding has been set through relative values
20656     * {@link #setPaddingRelative(int, int, int, int)} or through
20657     * @attr ref android.R.styleable#View_paddingStart or
20658     * @attr ref android.R.styleable#View_paddingEnd
20659     *
20660     * @return true if the padding is relative or false if it is not.
20661     */
20662    public boolean isPaddingRelative() {
20663        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20664    }
20665
20666    Insets computeOpticalInsets() {
20667        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20668    }
20669
20670    /**
20671     * @hide
20672     */
20673    public void resetPaddingToInitialValues() {
20674        if (isRtlCompatibilityMode()) {
20675            mPaddingLeft = mUserPaddingLeftInitial;
20676            mPaddingRight = mUserPaddingRightInitial;
20677            return;
20678        }
20679        if (isLayoutRtl()) {
20680            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20681            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20682        } else {
20683            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20684            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20685        }
20686    }
20687
20688    /**
20689     * @hide
20690     */
20691    public Insets getOpticalInsets() {
20692        if (mLayoutInsets == null) {
20693            mLayoutInsets = computeOpticalInsets();
20694        }
20695        return mLayoutInsets;
20696    }
20697
20698    /**
20699     * Set this view's optical insets.
20700     *
20701     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20702     * property. Views that compute their own optical insets should call it as part of measurement.
20703     * This method does not request layout. If you are setting optical insets outside of
20704     * measure/layout itself you will want to call requestLayout() yourself.
20705     * </p>
20706     * @hide
20707     */
20708    public void setOpticalInsets(Insets insets) {
20709        mLayoutInsets = insets;
20710    }
20711
20712    /**
20713     * Changes the selection state of this view. A view can be selected or not.
20714     * Note that selection is not the same as focus. Views are typically
20715     * selected in the context of an AdapterView like ListView or GridView;
20716     * the selected view is the view that is highlighted.
20717     *
20718     * @param selected true if the view must be selected, false otherwise
20719     */
20720    public void setSelected(boolean selected) {
20721        //noinspection DoubleNegation
20722        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20723            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20724            if (!selected) resetPressedState();
20725            invalidate(true);
20726            refreshDrawableState();
20727            dispatchSetSelected(selected);
20728            if (selected) {
20729                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20730            } else {
20731                notifyViewAccessibilityStateChangedIfNeeded(
20732                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20733            }
20734        }
20735    }
20736
20737    /**
20738     * Dispatch setSelected to all of this View's children.
20739     *
20740     * @see #setSelected(boolean)
20741     *
20742     * @param selected The new selected state
20743     */
20744    protected void dispatchSetSelected(boolean selected) {
20745    }
20746
20747    /**
20748     * Indicates the selection state of this view.
20749     *
20750     * @return true if the view is selected, false otherwise
20751     */
20752    @ViewDebug.ExportedProperty
20753    public boolean isSelected() {
20754        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20755    }
20756
20757    /**
20758     * Changes the activated state of this view. A view can be activated or not.
20759     * Note that activation is not the same as selection.  Selection is
20760     * a transient property, representing the view (hierarchy) the user is
20761     * currently interacting with.  Activation is a longer-term state that the
20762     * user can move views in and out of.  For example, in a list view with
20763     * single or multiple selection enabled, the views in the current selection
20764     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20765     * here.)  The activated state is propagated down to children of the view it
20766     * is set on.
20767     *
20768     * @param activated true if the view must be activated, false otherwise
20769     */
20770    public void setActivated(boolean activated) {
20771        //noinspection DoubleNegation
20772        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20773            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20774            invalidate(true);
20775            refreshDrawableState();
20776            dispatchSetActivated(activated);
20777        }
20778    }
20779
20780    /**
20781     * Dispatch setActivated to all of this View's children.
20782     *
20783     * @see #setActivated(boolean)
20784     *
20785     * @param activated The new activated state
20786     */
20787    protected void dispatchSetActivated(boolean activated) {
20788    }
20789
20790    /**
20791     * Indicates the activation state of this view.
20792     *
20793     * @return true if the view is activated, false otherwise
20794     */
20795    @ViewDebug.ExportedProperty
20796    public boolean isActivated() {
20797        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20798    }
20799
20800    /**
20801     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20802     * observer can be used to get notifications when global events, like
20803     * layout, happen.
20804     *
20805     * The returned ViewTreeObserver observer is not guaranteed to remain
20806     * valid for the lifetime of this View. If the caller of this method keeps
20807     * a long-lived reference to ViewTreeObserver, it should always check for
20808     * the return value of {@link ViewTreeObserver#isAlive()}.
20809     *
20810     * @return The ViewTreeObserver for this view's hierarchy.
20811     */
20812    public ViewTreeObserver getViewTreeObserver() {
20813        if (mAttachInfo != null) {
20814            return mAttachInfo.mTreeObserver;
20815        }
20816        if (mFloatingTreeObserver == null) {
20817            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20818        }
20819        return mFloatingTreeObserver;
20820    }
20821
20822    /**
20823     * <p>Finds the topmost view in the current view hierarchy.</p>
20824     *
20825     * @return the topmost view containing this view
20826     */
20827    public View getRootView() {
20828        if (mAttachInfo != null) {
20829            final View v = mAttachInfo.mRootView;
20830            if (v != null) {
20831                return v;
20832            }
20833        }
20834
20835        View parent = this;
20836
20837        while (parent.mParent != null && parent.mParent instanceof View) {
20838            parent = (View) parent.mParent;
20839        }
20840
20841        return parent;
20842    }
20843
20844    /**
20845     * Transforms a motion event from view-local coordinates to on-screen
20846     * coordinates.
20847     *
20848     * @param ev the view-local motion event
20849     * @return false if the transformation could not be applied
20850     * @hide
20851     */
20852    public boolean toGlobalMotionEvent(MotionEvent ev) {
20853        final AttachInfo info = mAttachInfo;
20854        if (info == null) {
20855            return false;
20856        }
20857
20858        final Matrix m = info.mTmpMatrix;
20859        m.set(Matrix.IDENTITY_MATRIX);
20860        transformMatrixToGlobal(m);
20861        ev.transform(m);
20862        return true;
20863    }
20864
20865    /**
20866     * Transforms a motion event from on-screen coordinates to view-local
20867     * coordinates.
20868     *
20869     * @param ev the on-screen motion event
20870     * @return false if the transformation could not be applied
20871     * @hide
20872     */
20873    public boolean toLocalMotionEvent(MotionEvent ev) {
20874        final AttachInfo info = mAttachInfo;
20875        if (info == null) {
20876            return false;
20877        }
20878
20879        final Matrix m = info.mTmpMatrix;
20880        m.set(Matrix.IDENTITY_MATRIX);
20881        transformMatrixToLocal(m);
20882        ev.transform(m);
20883        return true;
20884    }
20885
20886    /**
20887     * Modifies the input matrix such that it maps view-local coordinates to
20888     * on-screen coordinates.
20889     *
20890     * @param m input matrix to modify
20891     * @hide
20892     */
20893    public void transformMatrixToGlobal(Matrix m) {
20894        final ViewParent parent = mParent;
20895        if (parent instanceof View) {
20896            final View vp = (View) parent;
20897            vp.transformMatrixToGlobal(m);
20898            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20899        } else if (parent instanceof ViewRootImpl) {
20900            final ViewRootImpl vr = (ViewRootImpl) parent;
20901            vr.transformMatrixToGlobal(m);
20902            m.preTranslate(0, -vr.mCurScrollY);
20903        }
20904
20905        m.preTranslate(mLeft, mTop);
20906
20907        if (!hasIdentityMatrix()) {
20908            m.preConcat(getMatrix());
20909        }
20910    }
20911
20912    /**
20913     * Modifies the input matrix such that it maps on-screen coordinates to
20914     * view-local coordinates.
20915     *
20916     * @param m input matrix to modify
20917     * @hide
20918     */
20919    public void transformMatrixToLocal(Matrix m) {
20920        final ViewParent parent = mParent;
20921        if (parent instanceof View) {
20922            final View vp = (View) parent;
20923            vp.transformMatrixToLocal(m);
20924            m.postTranslate(vp.mScrollX, vp.mScrollY);
20925        } else if (parent instanceof ViewRootImpl) {
20926            final ViewRootImpl vr = (ViewRootImpl) parent;
20927            vr.transformMatrixToLocal(m);
20928            m.postTranslate(0, vr.mCurScrollY);
20929        }
20930
20931        m.postTranslate(-mLeft, -mTop);
20932
20933        if (!hasIdentityMatrix()) {
20934            m.postConcat(getInverseMatrix());
20935        }
20936    }
20937
20938    /**
20939     * @hide
20940     */
20941    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20942            @ViewDebug.IntToString(from = 0, to = "x"),
20943            @ViewDebug.IntToString(from = 1, to = "y")
20944    })
20945    public int[] getLocationOnScreen() {
20946        int[] location = new int[2];
20947        getLocationOnScreen(location);
20948        return location;
20949    }
20950
20951    /**
20952     * <p>Computes the coordinates of this view on the screen. The argument
20953     * must be an array of two integers. After the method returns, the array
20954     * contains the x and y location in that order.</p>
20955     *
20956     * @param outLocation an array of two integers in which to hold the coordinates
20957     */
20958    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20959        getLocationInWindow(outLocation);
20960
20961        final AttachInfo info = mAttachInfo;
20962        if (info != null) {
20963            outLocation[0] += info.mWindowLeft;
20964            outLocation[1] += info.mWindowTop;
20965        }
20966    }
20967
20968    /**
20969     * <p>Computes the coordinates of this view in its window. The argument
20970     * must be an array of two integers. After the method returns, the array
20971     * contains the x and y location in that order.</p>
20972     *
20973     * @param outLocation an array of two integers in which to hold the coordinates
20974     */
20975    public void getLocationInWindow(@Size(2) int[] outLocation) {
20976        if (outLocation == null || outLocation.length < 2) {
20977            throw new IllegalArgumentException("outLocation must be an array of two integers");
20978        }
20979
20980        outLocation[0] = 0;
20981        outLocation[1] = 0;
20982
20983        transformFromViewToWindowSpace(outLocation);
20984    }
20985
20986    /** @hide */
20987    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20988        if (inOutLocation == null || inOutLocation.length < 2) {
20989            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20990        }
20991
20992        if (mAttachInfo == null) {
20993            // When the view is not attached to a window, this method does not make sense
20994            inOutLocation[0] = inOutLocation[1] = 0;
20995            return;
20996        }
20997
20998        float position[] = mAttachInfo.mTmpTransformLocation;
20999        position[0] = inOutLocation[0];
21000        position[1] = inOutLocation[1];
21001
21002        if (!hasIdentityMatrix()) {
21003            getMatrix().mapPoints(position);
21004        }
21005
21006        position[0] += mLeft;
21007        position[1] += mTop;
21008
21009        ViewParent viewParent = mParent;
21010        while (viewParent instanceof View) {
21011            final View view = (View) viewParent;
21012
21013            position[0] -= view.mScrollX;
21014            position[1] -= view.mScrollY;
21015
21016            if (!view.hasIdentityMatrix()) {
21017                view.getMatrix().mapPoints(position);
21018            }
21019
21020            position[0] += view.mLeft;
21021            position[1] += view.mTop;
21022
21023            viewParent = view.mParent;
21024         }
21025
21026        if (viewParent instanceof ViewRootImpl) {
21027            // *cough*
21028            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21029            position[1] -= vr.mCurScrollY;
21030        }
21031
21032        inOutLocation[0] = Math.round(position[0]);
21033        inOutLocation[1] = Math.round(position[1]);
21034    }
21035
21036    /**
21037     * @param id the id of the view to be found
21038     * @return the view of the specified id, null if cannot be found
21039     * @hide
21040     */
21041    protected <T extends View> T findViewTraversal(@IdRes int id) {
21042        if (id == mID) {
21043            return (T) this;
21044        }
21045        return null;
21046    }
21047
21048    /**
21049     * @param tag the tag of the view to be found
21050     * @return the view of specified tag, null if cannot be found
21051     * @hide
21052     */
21053    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21054        if (tag != null && tag.equals(mTag)) {
21055            return (T) this;
21056        }
21057        return null;
21058    }
21059
21060    /**
21061     * @param predicate The predicate to evaluate.
21062     * @param childToSkip If not null, ignores this child during the recursive traversal.
21063     * @return The first view that matches the predicate or null.
21064     * @hide
21065     */
21066    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21067            View childToSkip) {
21068        if (predicate.test(this)) {
21069            return (T) this;
21070        }
21071        return null;
21072    }
21073
21074    /**
21075     * Finds the first descendant view with the given ID, the view itself if
21076     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21077     * (< 0) or there is no matching view in the hierarchy.
21078     * <p>
21079     * <strong>Note:</strong> In most cases -- depending on compiler support --
21080     * the resulting view is automatically cast to the target class type. If
21081     * the target class type is unconstrained, an explicit cast may be
21082     * necessary.
21083     *
21084     * @param id the ID to search for
21085     * @return a view with given ID if found, or {@code null} otherwise
21086     * @see View#findViewById(int)
21087     */
21088    @Nullable
21089    public final <T extends View> T findViewById(@IdRes int id) {
21090        if (id < 0) {
21091            return null;
21092        }
21093        return findViewTraversal(id);
21094    }
21095
21096    /**
21097     * Finds a view by its unuque and stable accessibility id.
21098     *
21099     * @param accessibilityId The searched accessibility id.
21100     * @return The found view.
21101     */
21102    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
21103        if (accessibilityId < 0) {
21104            return null;
21105        }
21106        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21107        if (view != null) {
21108            return view.includeForAccessibility() ? view : null;
21109        }
21110        return null;
21111    }
21112
21113    /**
21114     * Performs the traversal to find a view by its unuque and stable accessibility id.
21115     *
21116     * <strong>Note:</strong>This method does not stop at the root namespace
21117     * boundary since the user can touch the screen at an arbitrary location
21118     * potentially crossing the root namespace bounday which will send an
21119     * accessibility event to accessibility services and they should be able
21120     * to obtain the event source. Also accessibility ids are guaranteed to be
21121     * unique in the window.
21122     *
21123     * @param accessibilityId The accessibility id.
21124     * @return The found view.
21125     * @hide
21126     */
21127    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21128        if (getAccessibilityViewId() == accessibilityId) {
21129            return (T) this;
21130        }
21131        return null;
21132    }
21133
21134    /**
21135     * Look for a child view with the given tag.  If this view has the given
21136     * tag, return this view.
21137     *
21138     * @param tag The tag to search for, using "tag.equals(getTag())".
21139     * @return The View that has the given tag in the hierarchy or null
21140     */
21141    public final <T extends View> T findViewWithTag(Object tag) {
21142        if (tag == null) {
21143            return null;
21144        }
21145        return findViewWithTagTraversal(tag);
21146    }
21147
21148    /**
21149     * Look for a child view that matches the specified predicate.
21150     * If this view matches the predicate, return this view.
21151     *
21152     * @param predicate The predicate to evaluate.
21153     * @return The first view that matches the predicate or null.
21154     * @hide
21155     */
21156    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21157        return findViewByPredicateTraversal(predicate, null);
21158    }
21159
21160    /**
21161     * Look for a child view that matches the specified predicate,
21162     * starting with the specified view and its descendents and then
21163     * recusively searching the ancestors and siblings of that view
21164     * until this view is reached.
21165     *
21166     * This method is useful in cases where the predicate does not match
21167     * a single unique view (perhaps multiple views use the same id)
21168     * and we are trying to find the view that is "closest" in scope to the
21169     * starting view.
21170     *
21171     * @param start The view to start from.
21172     * @param predicate The predicate to evaluate.
21173     * @return The first view that matches the predicate or null.
21174     * @hide
21175     */
21176    public final <T extends View> T findViewByPredicateInsideOut(
21177            View start, Predicate<View> predicate) {
21178        View childToSkip = null;
21179        for (;;) {
21180            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21181            if (view != null || start == this) {
21182                return view;
21183            }
21184
21185            ViewParent parent = start.getParent();
21186            if (parent == null || !(parent instanceof View)) {
21187                return null;
21188            }
21189
21190            childToSkip = start;
21191            start = (View) parent;
21192        }
21193    }
21194
21195    /**
21196     * Sets the identifier for this view. The identifier does not have to be
21197     * unique in this view's hierarchy. The identifier should be a positive
21198     * number.
21199     *
21200     * @see #NO_ID
21201     * @see #getId()
21202     * @see #findViewById(int)
21203     *
21204     * @param id a number used to identify the view
21205     *
21206     * @attr ref android.R.styleable#View_id
21207     */
21208    public void setId(@IdRes int id) {
21209        mID = id;
21210        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21211            mID = generateViewId();
21212        }
21213    }
21214
21215    /**
21216     * {@hide}
21217     *
21218     * @param isRoot true if the view belongs to the root namespace, false
21219     *        otherwise
21220     */
21221    public void setIsRootNamespace(boolean isRoot) {
21222        if (isRoot) {
21223            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21224        } else {
21225            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21226        }
21227    }
21228
21229    /**
21230     * {@hide}
21231     *
21232     * @return true if the view belongs to the root namespace, false otherwise
21233     */
21234    public boolean isRootNamespace() {
21235        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21236    }
21237
21238    /**
21239     * Returns this view's identifier.
21240     *
21241     * @return a positive integer used to identify the view or {@link #NO_ID}
21242     *         if the view has no ID
21243     *
21244     * @see #setId(int)
21245     * @see #findViewById(int)
21246     * @attr ref android.R.styleable#View_id
21247     */
21248    @IdRes
21249    @ViewDebug.CapturedViewProperty
21250    public int getId() {
21251        return mID;
21252    }
21253
21254    /**
21255     * Returns this view's tag.
21256     *
21257     * @return the Object stored in this view as a tag, or {@code null} if not
21258     *         set
21259     *
21260     * @see #setTag(Object)
21261     * @see #getTag(int)
21262     */
21263    @ViewDebug.ExportedProperty
21264    public Object getTag() {
21265        return mTag;
21266    }
21267
21268    /**
21269     * Sets the tag associated with this view. A tag can be used to mark
21270     * a view in its hierarchy and does not have to be unique within the
21271     * hierarchy. Tags can also be used to store data within a view without
21272     * resorting to another data structure.
21273     *
21274     * @param tag an Object to tag the view with
21275     *
21276     * @see #getTag()
21277     * @see #setTag(int, Object)
21278     */
21279    public void setTag(final Object tag) {
21280        mTag = tag;
21281    }
21282
21283    /**
21284     * Returns the tag associated with this view and the specified key.
21285     *
21286     * @param key The key identifying the tag
21287     *
21288     * @return the Object stored in this view as a tag, or {@code null} if not
21289     *         set
21290     *
21291     * @see #setTag(int, Object)
21292     * @see #getTag()
21293     */
21294    public Object getTag(int key) {
21295        if (mKeyedTags != null) return mKeyedTags.get(key);
21296        return null;
21297    }
21298
21299    /**
21300     * Sets a tag associated with this view and a key. A tag can be used
21301     * to mark a view in its hierarchy and does not have to be unique within
21302     * the hierarchy. Tags can also be used to store data within a view
21303     * without resorting to another data structure.
21304     *
21305     * The specified key should be an id declared in the resources of the
21306     * application to ensure it is unique (see the <a
21307     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21308     * Keys identified as belonging to
21309     * the Android framework or not associated with any package will cause
21310     * an {@link IllegalArgumentException} to be thrown.
21311     *
21312     * @param key The key identifying the tag
21313     * @param tag An Object to tag the view with
21314     *
21315     * @throws IllegalArgumentException If they specified key is not valid
21316     *
21317     * @see #setTag(Object)
21318     * @see #getTag(int)
21319     */
21320    public void setTag(int key, final Object tag) {
21321        // If the package id is 0x00 or 0x01, it's either an undefined package
21322        // or a framework id
21323        if ((key >>> 24) < 2) {
21324            throw new IllegalArgumentException("The key must be an application-specific "
21325                    + "resource id.");
21326        }
21327
21328        setKeyedTag(key, tag);
21329    }
21330
21331    /**
21332     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21333     * framework id.
21334     *
21335     * @hide
21336     */
21337    public void setTagInternal(int key, Object tag) {
21338        if ((key >>> 24) != 0x1) {
21339            throw new IllegalArgumentException("The key must be a framework-specific "
21340                    + "resource id.");
21341        }
21342
21343        setKeyedTag(key, tag);
21344    }
21345
21346    private void setKeyedTag(int key, Object tag) {
21347        if (mKeyedTags == null) {
21348            mKeyedTags = new SparseArray<Object>(2);
21349        }
21350
21351        mKeyedTags.put(key, tag);
21352    }
21353
21354    /**
21355     * Prints information about this view in the log output, with the tag
21356     * {@link #VIEW_LOG_TAG}.
21357     *
21358     * @hide
21359     */
21360    public void debug() {
21361        debug(0);
21362    }
21363
21364    /**
21365     * Prints information about this view in the log output, with the tag
21366     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21367     * indentation defined by the <code>depth</code>.
21368     *
21369     * @param depth the indentation level
21370     *
21371     * @hide
21372     */
21373    protected void debug(int depth) {
21374        String output = debugIndent(depth - 1);
21375
21376        output += "+ " + this;
21377        int id = getId();
21378        if (id != -1) {
21379            output += " (id=" + id + ")";
21380        }
21381        Object tag = getTag();
21382        if (tag != null) {
21383            output += " (tag=" + tag + ")";
21384        }
21385        Log.d(VIEW_LOG_TAG, output);
21386
21387        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21388            output = debugIndent(depth) + " FOCUSED";
21389            Log.d(VIEW_LOG_TAG, output);
21390        }
21391
21392        output = debugIndent(depth);
21393        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21394                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21395                + "} ";
21396        Log.d(VIEW_LOG_TAG, output);
21397
21398        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21399                || mPaddingBottom != 0) {
21400            output = debugIndent(depth);
21401            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21402                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21403            Log.d(VIEW_LOG_TAG, output);
21404        }
21405
21406        output = debugIndent(depth);
21407        output += "mMeasureWidth=" + mMeasuredWidth +
21408                " mMeasureHeight=" + mMeasuredHeight;
21409        Log.d(VIEW_LOG_TAG, output);
21410
21411        output = debugIndent(depth);
21412        if (mLayoutParams == null) {
21413            output += "BAD! no layout params";
21414        } else {
21415            output = mLayoutParams.debug(output);
21416        }
21417        Log.d(VIEW_LOG_TAG, output);
21418
21419        output = debugIndent(depth);
21420        output += "flags={";
21421        output += View.printFlags(mViewFlags);
21422        output += "}";
21423        Log.d(VIEW_LOG_TAG, output);
21424
21425        output = debugIndent(depth);
21426        output += "privateFlags={";
21427        output += View.printPrivateFlags(mPrivateFlags);
21428        output += "}";
21429        Log.d(VIEW_LOG_TAG, output);
21430    }
21431
21432    /**
21433     * Creates a string of whitespaces used for indentation.
21434     *
21435     * @param depth the indentation level
21436     * @return a String containing (depth * 2 + 3) * 2 white spaces
21437     *
21438     * @hide
21439     */
21440    protected static String debugIndent(int depth) {
21441        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21442        for (int i = 0; i < (depth * 2) + 3; i++) {
21443            spaces.append(' ').append(' ');
21444        }
21445        return spaces.toString();
21446    }
21447
21448    /**
21449     * <p>Return the offset of the widget's text baseline from the widget's top
21450     * boundary. If this widget does not support baseline alignment, this
21451     * method returns -1. </p>
21452     *
21453     * @return the offset of the baseline within the widget's bounds or -1
21454     *         if baseline alignment is not supported
21455     */
21456    @ViewDebug.ExportedProperty(category = "layout")
21457    public int getBaseline() {
21458        return -1;
21459    }
21460
21461    /**
21462     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21463     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21464     * a layout pass.
21465     *
21466     * @return whether the view hierarchy is currently undergoing a layout pass
21467     */
21468    public boolean isInLayout() {
21469        ViewRootImpl viewRoot = getViewRootImpl();
21470        return (viewRoot != null && viewRoot.isInLayout());
21471    }
21472
21473    /**
21474     * Call this when something has changed which has invalidated the
21475     * layout of this view. This will schedule a layout pass of the view
21476     * tree. This should not be called while the view hierarchy is currently in a layout
21477     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21478     * end of the current layout pass (and then layout will run again) or after the current
21479     * frame is drawn and the next layout occurs.
21480     *
21481     * <p>Subclasses which override this method should call the superclass method to
21482     * handle possible request-during-layout errors correctly.</p>
21483     */
21484    @CallSuper
21485    public void requestLayout() {
21486        if (mMeasureCache != null) mMeasureCache.clear();
21487
21488        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21489            // Only trigger request-during-layout logic if this is the view requesting it,
21490            // not the views in its parent hierarchy
21491            ViewRootImpl viewRoot = getViewRootImpl();
21492            if (viewRoot != null && viewRoot.isInLayout()) {
21493                if (!viewRoot.requestLayoutDuringLayout(this)) {
21494                    return;
21495                }
21496            }
21497            mAttachInfo.mViewRequestingLayout = this;
21498        }
21499
21500        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21501        mPrivateFlags |= PFLAG_INVALIDATED;
21502
21503        if (mParent != null && !mParent.isLayoutRequested()) {
21504            mParent.requestLayout();
21505        }
21506        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21507            mAttachInfo.mViewRequestingLayout = null;
21508        }
21509    }
21510
21511    /**
21512     * Forces this view to be laid out during the next layout pass.
21513     * This method does not call requestLayout() or forceLayout()
21514     * on the parent.
21515     */
21516    public void forceLayout() {
21517        if (mMeasureCache != null) mMeasureCache.clear();
21518
21519        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21520        mPrivateFlags |= PFLAG_INVALIDATED;
21521    }
21522
21523    /**
21524     * <p>
21525     * This is called to find out how big a view should be. The parent
21526     * supplies constraint information in the width and height parameters.
21527     * </p>
21528     *
21529     * <p>
21530     * The actual measurement work of a view is performed in
21531     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21532     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21533     * </p>
21534     *
21535     *
21536     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21537     *        parent
21538     * @param heightMeasureSpec Vertical space requirements as imposed by the
21539     *        parent
21540     *
21541     * @see #onMeasure(int, int)
21542     */
21543    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21544        boolean optical = isLayoutModeOptical(this);
21545        if (optical != isLayoutModeOptical(mParent)) {
21546            Insets insets = getOpticalInsets();
21547            int oWidth  = insets.left + insets.right;
21548            int oHeight = insets.top  + insets.bottom;
21549            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21550            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21551        }
21552
21553        // Suppress sign extension for the low bytes
21554        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21555        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21556
21557        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21558
21559        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21560        // already measured as the correct size. In API 23 and below, this
21561        // extra pass is required to make LinearLayout re-distribute weight.
21562        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21563                || heightMeasureSpec != mOldHeightMeasureSpec;
21564        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21565                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21566        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21567                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21568        final boolean needsLayout = specChanged
21569                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21570
21571        if (forceLayout || needsLayout) {
21572            // first clears the measured dimension flag
21573            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21574
21575            resolveRtlPropertiesIfNeeded();
21576
21577            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21578            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21579                // measure ourselves, this should set the measured dimension flag back
21580                onMeasure(widthMeasureSpec, heightMeasureSpec);
21581                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21582            } else {
21583                long value = mMeasureCache.valueAt(cacheIndex);
21584                // Casting a long to int drops the high 32 bits, no mask needed
21585                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21586                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21587            }
21588
21589            // flag not set, setMeasuredDimension() was not invoked, we raise
21590            // an exception to warn the developer
21591            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21592                throw new IllegalStateException("View with id " + getId() + ": "
21593                        + getClass().getName() + "#onMeasure() did not set the"
21594                        + " measured dimension by calling"
21595                        + " setMeasuredDimension()");
21596            }
21597
21598            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21599        }
21600
21601        mOldWidthMeasureSpec = widthMeasureSpec;
21602        mOldHeightMeasureSpec = heightMeasureSpec;
21603
21604        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21605                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21606    }
21607
21608    /**
21609     * <p>
21610     * Measure the view and its content to determine the measured width and the
21611     * measured height. This method is invoked by {@link #measure(int, int)} and
21612     * should be overridden by subclasses to provide accurate and efficient
21613     * measurement of their contents.
21614     * </p>
21615     *
21616     * <p>
21617     * <strong>CONTRACT:</strong> When overriding this method, you
21618     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21619     * measured width and height of this view. Failure to do so will trigger an
21620     * <code>IllegalStateException</code>, thrown by
21621     * {@link #measure(int, int)}. Calling the superclass'
21622     * {@link #onMeasure(int, int)} is a valid use.
21623     * </p>
21624     *
21625     * <p>
21626     * The base class implementation of measure defaults to the background size,
21627     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21628     * override {@link #onMeasure(int, int)} to provide better measurements of
21629     * their content.
21630     * </p>
21631     *
21632     * <p>
21633     * If this method is overridden, it is the subclass's responsibility to make
21634     * sure the measured height and width are at least the view's minimum height
21635     * and width ({@link #getSuggestedMinimumHeight()} and
21636     * {@link #getSuggestedMinimumWidth()}).
21637     * </p>
21638     *
21639     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21640     *                         The requirements are encoded with
21641     *                         {@link android.view.View.MeasureSpec}.
21642     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21643     *                         The requirements are encoded with
21644     *                         {@link android.view.View.MeasureSpec}.
21645     *
21646     * @see #getMeasuredWidth()
21647     * @see #getMeasuredHeight()
21648     * @see #setMeasuredDimension(int, int)
21649     * @see #getSuggestedMinimumHeight()
21650     * @see #getSuggestedMinimumWidth()
21651     * @see android.view.View.MeasureSpec#getMode(int)
21652     * @see android.view.View.MeasureSpec#getSize(int)
21653     */
21654    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21655        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21656                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21657    }
21658
21659    /**
21660     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21661     * measured width and measured height. Failing to do so will trigger an
21662     * exception at measurement time.</p>
21663     *
21664     * @param measuredWidth The measured width of this view.  May be a complex
21665     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21666     * {@link #MEASURED_STATE_TOO_SMALL}.
21667     * @param measuredHeight The measured height of this view.  May be a complex
21668     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21669     * {@link #MEASURED_STATE_TOO_SMALL}.
21670     */
21671    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21672        boolean optical = isLayoutModeOptical(this);
21673        if (optical != isLayoutModeOptical(mParent)) {
21674            Insets insets = getOpticalInsets();
21675            int opticalWidth  = insets.left + insets.right;
21676            int opticalHeight = insets.top  + insets.bottom;
21677
21678            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21679            measuredHeight += optical ? opticalHeight : -opticalHeight;
21680        }
21681        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21682    }
21683
21684    /**
21685     * Sets the measured dimension without extra processing for things like optical bounds.
21686     * Useful for reapplying consistent values that have already been cooked with adjustments
21687     * for optical bounds, etc. such as those from the measurement cache.
21688     *
21689     * @param measuredWidth The measured width of this view.  May be a complex
21690     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21691     * {@link #MEASURED_STATE_TOO_SMALL}.
21692     * @param measuredHeight The measured height of this view.  May be a complex
21693     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21694     * {@link #MEASURED_STATE_TOO_SMALL}.
21695     */
21696    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21697        mMeasuredWidth = measuredWidth;
21698        mMeasuredHeight = measuredHeight;
21699
21700        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21701    }
21702
21703    /**
21704     * Merge two states as returned by {@link #getMeasuredState()}.
21705     * @param curState The current state as returned from a view or the result
21706     * of combining multiple views.
21707     * @param newState The new view state to combine.
21708     * @return Returns a new integer reflecting the combination of the two
21709     * states.
21710     */
21711    public static int combineMeasuredStates(int curState, int newState) {
21712        return curState | newState;
21713    }
21714
21715    /**
21716     * Version of {@link #resolveSizeAndState(int, int, int)}
21717     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21718     */
21719    public static int resolveSize(int size, int measureSpec) {
21720        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21721    }
21722
21723    /**
21724     * Utility to reconcile a desired size and state, with constraints imposed
21725     * by a MeasureSpec. Will take the desired size, unless a different size
21726     * is imposed by the constraints. The returned value is a compound integer,
21727     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21728     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21729     * resulting size is smaller than the size the view wants to be.
21730     *
21731     * @param size How big the view wants to be.
21732     * @param measureSpec Constraints imposed by the parent.
21733     * @param childMeasuredState Size information bit mask for the view's
21734     *                           children.
21735     * @return Size information bit mask as defined by
21736     *         {@link #MEASURED_SIZE_MASK} and
21737     *         {@link #MEASURED_STATE_TOO_SMALL}.
21738     */
21739    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21740        final int specMode = MeasureSpec.getMode(measureSpec);
21741        final int specSize = MeasureSpec.getSize(measureSpec);
21742        final int result;
21743        switch (specMode) {
21744            case MeasureSpec.AT_MOST:
21745                if (specSize < size) {
21746                    result = specSize | MEASURED_STATE_TOO_SMALL;
21747                } else {
21748                    result = size;
21749                }
21750                break;
21751            case MeasureSpec.EXACTLY:
21752                result = specSize;
21753                break;
21754            case MeasureSpec.UNSPECIFIED:
21755            default:
21756                result = size;
21757        }
21758        return result | (childMeasuredState & MEASURED_STATE_MASK);
21759    }
21760
21761    /**
21762     * Utility to return a default size. Uses the supplied size if the
21763     * MeasureSpec imposed no constraints. Will get larger if allowed
21764     * by the MeasureSpec.
21765     *
21766     * @param size Default size for this view
21767     * @param measureSpec Constraints imposed by the parent
21768     * @return The size this view should be.
21769     */
21770    public static int getDefaultSize(int size, int measureSpec) {
21771        int result = size;
21772        int specMode = MeasureSpec.getMode(measureSpec);
21773        int specSize = MeasureSpec.getSize(measureSpec);
21774
21775        switch (specMode) {
21776        case MeasureSpec.UNSPECIFIED:
21777            result = size;
21778            break;
21779        case MeasureSpec.AT_MOST:
21780        case MeasureSpec.EXACTLY:
21781            result = specSize;
21782            break;
21783        }
21784        return result;
21785    }
21786
21787    /**
21788     * Returns the suggested minimum height that the view should use. This
21789     * returns the maximum of the view's minimum height
21790     * and the background's minimum height
21791     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21792     * <p>
21793     * When being used in {@link #onMeasure(int, int)}, the caller should still
21794     * ensure the returned height is within the requirements of the parent.
21795     *
21796     * @return The suggested minimum height of the view.
21797     */
21798    protected int getSuggestedMinimumHeight() {
21799        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21800
21801    }
21802
21803    /**
21804     * Returns the suggested minimum width that the view should use. This
21805     * returns the maximum of the view's minimum width
21806     * and the background's minimum width
21807     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21808     * <p>
21809     * When being used in {@link #onMeasure(int, int)}, the caller should still
21810     * ensure the returned width is within the requirements of the parent.
21811     *
21812     * @return The suggested minimum width of the view.
21813     */
21814    protected int getSuggestedMinimumWidth() {
21815        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21816    }
21817
21818    /**
21819     * Returns the minimum height of the view.
21820     *
21821     * @return the minimum height the view will try to be, in pixels
21822     *
21823     * @see #setMinimumHeight(int)
21824     *
21825     * @attr ref android.R.styleable#View_minHeight
21826     */
21827    public int getMinimumHeight() {
21828        return mMinHeight;
21829    }
21830
21831    /**
21832     * Sets the minimum height of the view. It is not guaranteed the view will
21833     * be able to achieve this minimum height (for example, if its parent layout
21834     * constrains it with less available height).
21835     *
21836     * @param minHeight The minimum height the view will try to be, in pixels
21837     *
21838     * @see #getMinimumHeight()
21839     *
21840     * @attr ref android.R.styleable#View_minHeight
21841     */
21842    @RemotableViewMethod
21843    public void setMinimumHeight(int minHeight) {
21844        mMinHeight = minHeight;
21845        requestLayout();
21846    }
21847
21848    /**
21849     * Returns the minimum width of the view.
21850     *
21851     * @return the minimum width the view will try to be, in pixels
21852     *
21853     * @see #setMinimumWidth(int)
21854     *
21855     * @attr ref android.R.styleable#View_minWidth
21856     */
21857    public int getMinimumWidth() {
21858        return mMinWidth;
21859    }
21860
21861    /**
21862     * Sets the minimum width of the view. It is not guaranteed the view will
21863     * be able to achieve this minimum width (for example, if its parent layout
21864     * constrains it with less available width).
21865     *
21866     * @param minWidth The minimum width the view will try to be, in pixels
21867     *
21868     * @see #getMinimumWidth()
21869     *
21870     * @attr ref android.R.styleable#View_minWidth
21871     */
21872    public void setMinimumWidth(int minWidth) {
21873        mMinWidth = minWidth;
21874        requestLayout();
21875
21876    }
21877
21878    /**
21879     * Get the animation currently associated with this view.
21880     *
21881     * @return The animation that is currently playing or
21882     *         scheduled to play for this view.
21883     */
21884    public Animation getAnimation() {
21885        return mCurrentAnimation;
21886    }
21887
21888    /**
21889     * Start the specified animation now.
21890     *
21891     * @param animation the animation to start now
21892     */
21893    public void startAnimation(Animation animation) {
21894        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21895        setAnimation(animation);
21896        invalidateParentCaches();
21897        invalidate(true);
21898    }
21899
21900    /**
21901     * Cancels any animations for this view.
21902     */
21903    public void clearAnimation() {
21904        if (mCurrentAnimation != null) {
21905            mCurrentAnimation.detach();
21906        }
21907        mCurrentAnimation = null;
21908        invalidateParentIfNeeded();
21909    }
21910
21911    /**
21912     * Sets the next animation to play for this view.
21913     * If you want the animation to play immediately, use
21914     * {@link #startAnimation(android.view.animation.Animation)} instead.
21915     * This method provides allows fine-grained
21916     * control over the start time and invalidation, but you
21917     * must make sure that 1) the animation has a start time set, and
21918     * 2) the view's parent (which controls animations on its children)
21919     * will be invalidated when the animation is supposed to
21920     * start.
21921     *
21922     * @param animation The next animation, or null.
21923     */
21924    public void setAnimation(Animation animation) {
21925        mCurrentAnimation = animation;
21926
21927        if (animation != null) {
21928            // If the screen is off assume the animation start time is now instead of
21929            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21930            // would cause the animation to start when the screen turns back on
21931            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21932                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21933                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21934            }
21935            animation.reset();
21936        }
21937    }
21938
21939    /**
21940     * Invoked by a parent ViewGroup to notify the start of the animation
21941     * currently associated with this view. If you override this method,
21942     * always call super.onAnimationStart();
21943     *
21944     * @see #setAnimation(android.view.animation.Animation)
21945     * @see #getAnimation()
21946     */
21947    @CallSuper
21948    protected void onAnimationStart() {
21949        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21950    }
21951
21952    /**
21953     * Invoked by a parent ViewGroup to notify the end of the animation
21954     * currently associated with this view. If you override this method,
21955     * always call super.onAnimationEnd();
21956     *
21957     * @see #setAnimation(android.view.animation.Animation)
21958     * @see #getAnimation()
21959     */
21960    @CallSuper
21961    protected void onAnimationEnd() {
21962        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21963    }
21964
21965    /**
21966     * Invoked if there is a Transform that involves alpha. Subclass that can
21967     * draw themselves with the specified alpha should return true, and then
21968     * respect that alpha when their onDraw() is called. If this returns false
21969     * then the view may be redirected to draw into an offscreen buffer to
21970     * fulfill the request, which will look fine, but may be slower than if the
21971     * subclass handles it internally. The default implementation returns false.
21972     *
21973     * @param alpha The alpha (0..255) to apply to the view's drawing
21974     * @return true if the view can draw with the specified alpha.
21975     */
21976    protected boolean onSetAlpha(int alpha) {
21977        return false;
21978    }
21979
21980    /**
21981     * This is used by the RootView to perform an optimization when
21982     * the view hierarchy contains one or several SurfaceView.
21983     * SurfaceView is always considered transparent, but its children are not,
21984     * therefore all View objects remove themselves from the global transparent
21985     * region (passed as a parameter to this function).
21986     *
21987     * @param region The transparent region for this ViewAncestor (window).
21988     *
21989     * @return Returns true if the effective visibility of the view at this
21990     * point is opaque, regardless of the transparent region; returns false
21991     * if it is possible for underlying windows to be seen behind the view.
21992     *
21993     * {@hide}
21994     */
21995    public boolean gatherTransparentRegion(Region region) {
21996        final AttachInfo attachInfo = mAttachInfo;
21997        if (region != null && attachInfo != null) {
21998            final int pflags = mPrivateFlags;
21999            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22000                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22001                // remove it from the transparent region.
22002                final int[] location = attachInfo.mTransparentLocation;
22003                getLocationInWindow(location);
22004                // When a view has Z value, then it will be better to leave some area below the view
22005                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22006                // the bottom part needs more offset than the left, top and right parts due to the
22007                // spot light effects.
22008                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22009                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22010                        location[0] + mRight - mLeft + shadowOffset,
22011                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22012            } else {
22013                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22014                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22015                    // the background drawable's non-transparent parts from this transparent region.
22016                    applyDrawableToTransparentRegion(mBackground, region);
22017                }
22018                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22019                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22020                    // Similarly, we remove the foreground drawable's non-transparent parts.
22021                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22022                }
22023                if (mDefaultFocusHighlight != null
22024                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22025                    // Similarly, we remove the default focus highlight's non-transparent parts.
22026                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22027                }
22028            }
22029        }
22030        return true;
22031    }
22032
22033    /**
22034     * Play a sound effect for this view.
22035     *
22036     * <p>The framework will play sound effects for some built in actions, such as
22037     * clicking, but you may wish to play these effects in your widget,
22038     * for instance, for internal navigation.
22039     *
22040     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22041     * {@link #isSoundEffectsEnabled()} is true.
22042     *
22043     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22044     */
22045    public void playSoundEffect(int soundConstant) {
22046        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22047            return;
22048        }
22049        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22050    }
22051
22052    /**
22053     * BZZZTT!!1!
22054     *
22055     * <p>Provide haptic feedback to the user for this view.
22056     *
22057     * <p>The framework will provide haptic feedback for some built in actions,
22058     * such as long presses, but you may wish to provide feedback for your
22059     * own widget.
22060     *
22061     * <p>The feedback will only be performed if
22062     * {@link #isHapticFeedbackEnabled()} is true.
22063     *
22064     * @param feedbackConstant One of the constants defined in
22065     * {@link HapticFeedbackConstants}
22066     */
22067    public boolean performHapticFeedback(int feedbackConstant) {
22068        return performHapticFeedback(feedbackConstant, 0);
22069    }
22070
22071    /**
22072     * BZZZTT!!1!
22073     *
22074     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22075     *
22076     * @param feedbackConstant One of the constants defined in
22077     * {@link HapticFeedbackConstants}
22078     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22079     */
22080    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22081        if (mAttachInfo == null) {
22082            return false;
22083        }
22084        //noinspection SimplifiableIfStatement
22085        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22086                && !isHapticFeedbackEnabled()) {
22087            return false;
22088        }
22089        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22090                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22091    }
22092
22093    /**
22094     * Request that the visibility of the status bar or other screen/window
22095     * decorations be changed.
22096     *
22097     * <p>This method is used to put the over device UI into temporary modes
22098     * where the user's attention is focused more on the application content,
22099     * by dimming or hiding surrounding system affordances.  This is typically
22100     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22101     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22102     * to be placed behind the action bar (and with these flags other system
22103     * affordances) so that smooth transitions between hiding and showing them
22104     * can be done.
22105     *
22106     * <p>Two representative examples of the use of system UI visibility is
22107     * implementing a content browsing application (like a magazine reader)
22108     * and a video playing application.
22109     *
22110     * <p>The first code shows a typical implementation of a View in a content
22111     * browsing application.  In this implementation, the application goes
22112     * into a content-oriented mode by hiding the status bar and action bar,
22113     * and putting the navigation elements into lights out mode.  The user can
22114     * then interact with content while in this mode.  Such an application should
22115     * provide an easy way for the user to toggle out of the mode (such as to
22116     * check information in the status bar or access notifications).  In the
22117     * implementation here, this is done simply by tapping on the content.
22118     *
22119     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22120     *      content}
22121     *
22122     * <p>This second code sample shows a typical implementation of a View
22123     * in a video playing application.  In this situation, while the video is
22124     * playing the application would like to go into a complete full-screen mode,
22125     * to use as much of the display as possible for the video.  When in this state
22126     * the user can not interact with the application; the system intercepts
22127     * touching on the screen to pop the UI out of full screen mode.  See
22128     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22129     *
22130     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22131     *      content}
22132     *
22133     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22134     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22135     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22136     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22137     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22138     */
22139    public void setSystemUiVisibility(int visibility) {
22140        if (visibility != mSystemUiVisibility) {
22141            mSystemUiVisibility = visibility;
22142            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22143                mParent.recomputeViewAttributes(this);
22144            }
22145        }
22146    }
22147
22148    /**
22149     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22150     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22151     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22152     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22153     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22154     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22155     */
22156    public int getSystemUiVisibility() {
22157        return mSystemUiVisibility;
22158    }
22159
22160    /**
22161     * Returns the current system UI visibility that is currently set for
22162     * the entire window.  This is the combination of the
22163     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22164     * views in the window.
22165     */
22166    public int getWindowSystemUiVisibility() {
22167        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22168    }
22169
22170    /**
22171     * Override to find out when the window's requested system UI visibility
22172     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22173     * This is different from the callbacks received through
22174     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22175     * in that this is only telling you about the local request of the window,
22176     * not the actual values applied by the system.
22177     */
22178    public void onWindowSystemUiVisibilityChanged(int visible) {
22179    }
22180
22181    /**
22182     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22183     * the view hierarchy.
22184     */
22185    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22186        onWindowSystemUiVisibilityChanged(visible);
22187    }
22188
22189    /**
22190     * Set a listener to receive callbacks when the visibility of the system bar changes.
22191     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22192     */
22193    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22194        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22195        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22196            mParent.recomputeViewAttributes(this);
22197        }
22198    }
22199
22200    /**
22201     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22202     * the view hierarchy.
22203     */
22204    public void dispatchSystemUiVisibilityChanged(int visibility) {
22205        ListenerInfo li = mListenerInfo;
22206        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22207            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22208                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22209        }
22210    }
22211
22212    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22213        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22214        if (val != mSystemUiVisibility) {
22215            setSystemUiVisibility(val);
22216            return true;
22217        }
22218        return false;
22219    }
22220
22221    /** @hide */
22222    public void setDisabledSystemUiVisibility(int flags) {
22223        if (mAttachInfo != null) {
22224            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22225                mAttachInfo.mDisabledSystemUiVisibility = flags;
22226                if (mParent != null) {
22227                    mParent.recomputeViewAttributes(this);
22228                }
22229            }
22230        }
22231    }
22232
22233    /**
22234     * Creates an image that the system displays during the drag and drop
22235     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22236     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22237     * appearance as the given View. The default also positions the center of the drag shadow
22238     * directly under the touch point. If no View is provided (the constructor with no parameters
22239     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22240     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22241     * default is an invisible drag shadow.
22242     * <p>
22243     * You are not required to use the View you provide to the constructor as the basis of the
22244     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22245     * anything you want as the drag shadow.
22246     * </p>
22247     * <p>
22248     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22249     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22250     *  size and position of the drag shadow. It uses this data to construct a
22251     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22252     *  so that your application can draw the shadow image in the Canvas.
22253     * </p>
22254     *
22255     * <div class="special reference">
22256     * <h3>Developer Guides</h3>
22257     * <p>For a guide to implementing drag and drop features, read the
22258     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22259     * </div>
22260     */
22261    public static class DragShadowBuilder {
22262        private final WeakReference<View> mView;
22263
22264        /**
22265         * Constructs a shadow image builder based on a View. By default, the resulting drag
22266         * shadow will have the same appearance and dimensions as the View, with the touch point
22267         * over the center of the View.
22268         * @param view A View. Any View in scope can be used.
22269         */
22270        public DragShadowBuilder(View view) {
22271            mView = new WeakReference<View>(view);
22272        }
22273
22274        /**
22275         * Construct a shadow builder object with no associated View.  This
22276         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22277         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22278         * to supply the drag shadow's dimensions and appearance without
22279         * reference to any View object. If they are not overridden, then the result is an
22280         * invisible drag shadow.
22281         */
22282        public DragShadowBuilder() {
22283            mView = new WeakReference<View>(null);
22284        }
22285
22286        /**
22287         * Returns the View object that had been passed to the
22288         * {@link #View.DragShadowBuilder(View)}
22289         * constructor.  If that View parameter was {@code null} or if the
22290         * {@link #View.DragShadowBuilder()}
22291         * constructor was used to instantiate the builder object, this method will return
22292         * null.
22293         *
22294         * @return The View object associate with this builder object.
22295         */
22296        @SuppressWarnings({"JavadocReference"})
22297        final public View getView() {
22298            return mView.get();
22299        }
22300
22301        /**
22302         * Provides the metrics for the shadow image. These include the dimensions of
22303         * the shadow image, and the point within that shadow that should
22304         * be centered under the touch location while dragging.
22305         * <p>
22306         * The default implementation sets the dimensions of the shadow to be the
22307         * same as the dimensions of the View itself and centers the shadow under
22308         * the touch point.
22309         * </p>
22310         *
22311         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22312         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22313         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22314         * image.
22315         *
22316         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22317         * shadow image that should be underneath the touch point during the drag and drop
22318         * operation. Your application must set {@link android.graphics.Point#x} to the
22319         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22320         */
22321        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22322            final View view = mView.get();
22323            if (view != null) {
22324                outShadowSize.set(view.getWidth(), view.getHeight());
22325                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22326            } else {
22327                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22328            }
22329        }
22330
22331        /**
22332         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22333         * based on the dimensions it received from the
22334         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22335         *
22336         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22337         */
22338        public void onDrawShadow(Canvas canvas) {
22339            final View view = mView.get();
22340            if (view != null) {
22341                view.draw(canvas);
22342            } else {
22343                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22344            }
22345        }
22346    }
22347
22348    /**
22349     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22350     * startDragAndDrop()} for newer platform versions.
22351     */
22352    @Deprecated
22353    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22354                                   Object myLocalState, int flags) {
22355        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22356    }
22357
22358    /**
22359     * Starts a drag and drop operation. When your application calls this method, it passes a
22360     * {@link android.view.View.DragShadowBuilder} object to the system. The
22361     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22362     * to get metrics for the drag shadow, and then calls the object's
22363     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22364     * <p>
22365     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22366     *  drag events to all the View objects in your application that are currently visible. It does
22367     *  this either by calling the View object's drag listener (an implementation of
22368     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22369     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22370     *  Both are passed a {@link android.view.DragEvent} object that has a
22371     *  {@link android.view.DragEvent#getAction()} value of
22372     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22373     * </p>
22374     * <p>
22375     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22376     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22377     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22378     * to the View the user selected for dragging.
22379     * </p>
22380     * @param data A {@link android.content.ClipData} object pointing to the data to be
22381     * transferred by the drag and drop operation.
22382     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22383     * drag shadow.
22384     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22385     * drop operation. When dispatching drag events to views in the same activity this object
22386     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22387     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22388     * will return null).
22389     * <p>
22390     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22391     * to the target Views. For example, it can contain flags that differentiate between a
22392     * a copy operation and a move operation.
22393     * </p>
22394     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22395     * flags, or any combination of the following:
22396     *     <ul>
22397     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22398     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22399     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22400     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22401     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22402     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22403     *     </ul>
22404     * @return {@code true} if the method completes successfully, or
22405     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22406     * do a drag, and so no drag operation is in progress.
22407     */
22408    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22409            Object myLocalState, int flags) {
22410        if (ViewDebug.DEBUG_DRAG) {
22411            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22412        }
22413        if (mAttachInfo == null) {
22414            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22415            return false;
22416        }
22417
22418        if (data != null) {
22419            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22420        }
22421
22422        boolean okay = false;
22423
22424        Point shadowSize = new Point();
22425        Point shadowTouchPoint = new Point();
22426        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22427
22428        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22429                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22430            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22431        }
22432
22433        if (ViewDebug.DEBUG_DRAG) {
22434            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22435                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22436        }
22437        if (mAttachInfo.mDragSurface != null) {
22438            mAttachInfo.mDragSurface.release();
22439        }
22440        mAttachInfo.mDragSurface = new Surface();
22441        try {
22442            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22443                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22444            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22445                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22446            if (mAttachInfo.mDragToken != null) {
22447                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22448                try {
22449                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22450                    shadowBuilder.onDrawShadow(canvas);
22451                } finally {
22452                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22453                }
22454
22455                final ViewRootImpl root = getViewRootImpl();
22456
22457                // Cache the local state object for delivery with DragEvents
22458                root.setLocalDragState(myLocalState);
22459
22460                // repurpose 'shadowSize' for the last touch point
22461                root.getLastTouchPoint(shadowSize);
22462
22463                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22464                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22465                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22466                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22467            }
22468        } catch (Exception e) {
22469            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22470            mAttachInfo.mDragSurface.destroy();
22471            mAttachInfo.mDragSurface = null;
22472        }
22473
22474        return okay;
22475    }
22476
22477    /**
22478     * Cancels an ongoing drag and drop operation.
22479     * <p>
22480     * A {@link android.view.DragEvent} object with
22481     * {@link android.view.DragEvent#getAction()} value of
22482     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22483     * {@link android.view.DragEvent#getResult()} value of {@code false}
22484     * will be sent to every
22485     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22486     * even if they are not currently visible.
22487     * </p>
22488     * <p>
22489     * This method can be called on any View in the same window as the View on which
22490     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22491     * was called.
22492     * </p>
22493     */
22494    public final void cancelDragAndDrop() {
22495        if (ViewDebug.DEBUG_DRAG) {
22496            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22497        }
22498        if (mAttachInfo == null) {
22499            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22500            return;
22501        }
22502        if (mAttachInfo.mDragToken != null) {
22503            try {
22504                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22505            } catch (Exception e) {
22506                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22507            }
22508            mAttachInfo.mDragToken = null;
22509        } else {
22510            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22511        }
22512    }
22513
22514    /**
22515     * Updates the drag shadow for the ongoing drag and drop operation.
22516     *
22517     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22518     * new drag shadow.
22519     */
22520    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22521        if (ViewDebug.DEBUG_DRAG) {
22522            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22523        }
22524        if (mAttachInfo == null) {
22525            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22526            return;
22527        }
22528        if (mAttachInfo.mDragToken != null) {
22529            try {
22530                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22531                try {
22532                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22533                    shadowBuilder.onDrawShadow(canvas);
22534                } finally {
22535                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22536                }
22537            } catch (Exception e) {
22538                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22539            }
22540        } else {
22541            Log.e(VIEW_LOG_TAG, "No active drag");
22542        }
22543    }
22544
22545    /**
22546     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22547     * between {startX, startY} and the new cursor positon.
22548     * @param startX horizontal coordinate where the move started.
22549     * @param startY vertical coordinate where the move started.
22550     * @return whether moving was started successfully.
22551     * @hide
22552     */
22553    public final boolean startMovingTask(float startX, float startY) {
22554        if (ViewDebug.DEBUG_POSITIONING) {
22555            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22556        }
22557        try {
22558            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22559        } catch (RemoteException e) {
22560            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22561        }
22562        return false;
22563    }
22564
22565    /**
22566     * Handles drag events sent by the system following a call to
22567     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22568     * startDragAndDrop()}.
22569     *<p>
22570     * When the system calls this method, it passes a
22571     * {@link android.view.DragEvent} object. A call to
22572     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22573     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22574     * operation.
22575     * @param event The {@link android.view.DragEvent} sent by the system.
22576     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22577     * in DragEvent, indicating the type of drag event represented by this object.
22578     * @return {@code true} if the method was successful, otherwise {@code false}.
22579     * <p>
22580     *  The method should return {@code true} in response to an action type of
22581     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22582     *  operation.
22583     * </p>
22584     * <p>
22585     *  The method should also return {@code true} in response to an action type of
22586     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22587     *  {@code false} if it didn't.
22588     * </p>
22589     * <p>
22590     *  For all other events, the return value is ignored.
22591     * </p>
22592     */
22593    public boolean onDragEvent(DragEvent event) {
22594        return false;
22595    }
22596
22597    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22598    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22599        return callDragEventHandler(event);
22600    }
22601
22602    /**
22603     * Detects if this View is enabled and has a drag event listener.
22604     * If both are true, then it calls the drag event listener with the
22605     * {@link android.view.DragEvent} it received. If the drag event listener returns
22606     * {@code true}, then dispatchDragEvent() returns {@code true}.
22607     * <p>
22608     * For all other cases, the method calls the
22609     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22610     * method and returns its result.
22611     * </p>
22612     * <p>
22613     * This ensures that a drag event is always consumed, even if the View does not have a drag
22614     * event listener. However, if the View has a listener and the listener returns true, then
22615     * onDragEvent() is not called.
22616     * </p>
22617     */
22618    public boolean dispatchDragEvent(DragEvent event) {
22619        event.mEventHandlerWasCalled = true;
22620        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22621            event.mAction == DragEvent.ACTION_DROP) {
22622            // About to deliver an event with coordinates to this view. Notify that now this view
22623            // has drag focus. This will send exit/enter events as needed.
22624            getViewRootImpl().setDragFocus(this, event);
22625        }
22626        return callDragEventHandler(event);
22627    }
22628
22629    final boolean callDragEventHandler(DragEvent event) {
22630        final boolean result;
22631
22632        ListenerInfo li = mListenerInfo;
22633        //noinspection SimplifiableIfStatement
22634        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22635                && li.mOnDragListener.onDrag(this, event)) {
22636            result = true;
22637        } else {
22638            result = onDragEvent(event);
22639        }
22640
22641        switch (event.mAction) {
22642            case DragEvent.ACTION_DRAG_ENTERED: {
22643                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22644                refreshDrawableState();
22645            } break;
22646            case DragEvent.ACTION_DRAG_EXITED: {
22647                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22648                refreshDrawableState();
22649            } break;
22650            case DragEvent.ACTION_DRAG_ENDED: {
22651                mPrivateFlags2 &= ~View.DRAG_MASK;
22652                refreshDrawableState();
22653            } break;
22654        }
22655
22656        return result;
22657    }
22658
22659    boolean canAcceptDrag() {
22660        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22661    }
22662
22663    /**
22664     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22665     * it is ever exposed at all.
22666     * @hide
22667     */
22668    public void onCloseSystemDialogs(String reason) {
22669    }
22670
22671    /**
22672     * Given a Drawable whose bounds have been set to draw into this view,
22673     * update a Region being computed for
22674     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22675     * that any non-transparent parts of the Drawable are removed from the
22676     * given transparent region.
22677     *
22678     * @param dr The Drawable whose transparency is to be applied to the region.
22679     * @param region A Region holding the current transparency information,
22680     * where any parts of the region that are set are considered to be
22681     * transparent.  On return, this region will be modified to have the
22682     * transparency information reduced by the corresponding parts of the
22683     * Drawable that are not transparent.
22684     * {@hide}
22685     */
22686    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22687        if (DBG) {
22688            Log.i("View", "Getting transparent region for: " + this);
22689        }
22690        final Region r = dr.getTransparentRegion();
22691        final Rect db = dr.getBounds();
22692        final AttachInfo attachInfo = mAttachInfo;
22693        if (r != null && attachInfo != null) {
22694            final int w = getRight()-getLeft();
22695            final int h = getBottom()-getTop();
22696            if (db.left > 0) {
22697                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22698                r.op(0, 0, db.left, h, Region.Op.UNION);
22699            }
22700            if (db.right < w) {
22701                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22702                r.op(db.right, 0, w, h, Region.Op.UNION);
22703            }
22704            if (db.top > 0) {
22705                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22706                r.op(0, 0, w, db.top, Region.Op.UNION);
22707            }
22708            if (db.bottom < h) {
22709                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22710                r.op(0, db.bottom, w, h, Region.Op.UNION);
22711            }
22712            final int[] location = attachInfo.mTransparentLocation;
22713            getLocationInWindow(location);
22714            r.translate(location[0], location[1]);
22715            region.op(r, Region.Op.INTERSECT);
22716        } else {
22717            region.op(db, Region.Op.DIFFERENCE);
22718        }
22719    }
22720
22721    private void checkForLongClick(int delayOffset, float x, float y) {
22722        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22723            mHasPerformedLongPress = false;
22724
22725            if (mPendingCheckForLongPress == null) {
22726                mPendingCheckForLongPress = new CheckForLongPress();
22727            }
22728            mPendingCheckForLongPress.setAnchor(x, y);
22729            mPendingCheckForLongPress.rememberWindowAttachCount();
22730            mPendingCheckForLongPress.rememberPressedState();
22731            postDelayed(mPendingCheckForLongPress,
22732                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22733        }
22734    }
22735
22736    /**
22737     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22738     * LayoutInflater} class, which provides a full range of options for view inflation.
22739     *
22740     * @param context The Context object for your activity or application.
22741     * @param resource The resource ID to inflate
22742     * @param root A view group that will be the parent.  Used to properly inflate the
22743     * layout_* parameters.
22744     * @see LayoutInflater
22745     */
22746    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22747        LayoutInflater factory = LayoutInflater.from(context);
22748        return factory.inflate(resource, root);
22749    }
22750
22751    /**
22752     * Scroll the view with standard behavior for scrolling beyond the normal
22753     * content boundaries. Views that call this method should override
22754     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22755     * results of an over-scroll operation.
22756     *
22757     * Views can use this method to handle any touch or fling-based scrolling.
22758     *
22759     * @param deltaX Change in X in pixels
22760     * @param deltaY Change in Y in pixels
22761     * @param scrollX Current X scroll value in pixels before applying deltaX
22762     * @param scrollY Current Y scroll value in pixels before applying deltaY
22763     * @param scrollRangeX Maximum content scroll range along the X axis
22764     * @param scrollRangeY Maximum content scroll range along the Y axis
22765     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22766     *          along the X axis.
22767     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22768     *          along the Y axis.
22769     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22770     * @return true if scrolling was clamped to an over-scroll boundary along either
22771     *          axis, false otherwise.
22772     */
22773    @SuppressWarnings({"UnusedParameters"})
22774    protected boolean overScrollBy(int deltaX, int deltaY,
22775            int scrollX, int scrollY,
22776            int scrollRangeX, int scrollRangeY,
22777            int maxOverScrollX, int maxOverScrollY,
22778            boolean isTouchEvent) {
22779        final int overScrollMode = mOverScrollMode;
22780        final boolean canScrollHorizontal =
22781                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22782        final boolean canScrollVertical =
22783                computeVerticalScrollRange() > computeVerticalScrollExtent();
22784        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22785                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22786        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22787                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22788
22789        int newScrollX = scrollX + deltaX;
22790        if (!overScrollHorizontal) {
22791            maxOverScrollX = 0;
22792        }
22793
22794        int newScrollY = scrollY + deltaY;
22795        if (!overScrollVertical) {
22796            maxOverScrollY = 0;
22797        }
22798
22799        // Clamp values if at the limits and record
22800        final int left = -maxOverScrollX;
22801        final int right = maxOverScrollX + scrollRangeX;
22802        final int top = -maxOverScrollY;
22803        final int bottom = maxOverScrollY + scrollRangeY;
22804
22805        boolean clampedX = false;
22806        if (newScrollX > right) {
22807            newScrollX = right;
22808            clampedX = true;
22809        } else if (newScrollX < left) {
22810            newScrollX = left;
22811            clampedX = true;
22812        }
22813
22814        boolean clampedY = false;
22815        if (newScrollY > bottom) {
22816            newScrollY = bottom;
22817            clampedY = true;
22818        } else if (newScrollY < top) {
22819            newScrollY = top;
22820            clampedY = true;
22821        }
22822
22823        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22824
22825        return clampedX || clampedY;
22826    }
22827
22828    /**
22829     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22830     * respond to the results of an over-scroll operation.
22831     *
22832     * @param scrollX New X scroll value in pixels
22833     * @param scrollY New Y scroll value in pixels
22834     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22835     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22836     */
22837    protected void onOverScrolled(int scrollX, int scrollY,
22838            boolean clampedX, boolean clampedY) {
22839        // Intentionally empty.
22840    }
22841
22842    /**
22843     * Returns the over-scroll mode for this view. The result will be
22844     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22845     * (allow over-scrolling only if the view content is larger than the container),
22846     * or {@link #OVER_SCROLL_NEVER}.
22847     *
22848     * @return This view's over-scroll mode.
22849     */
22850    public int getOverScrollMode() {
22851        return mOverScrollMode;
22852    }
22853
22854    /**
22855     * Set the over-scroll mode for this view. Valid over-scroll modes are
22856     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22857     * (allow over-scrolling only if the view content is larger than the container),
22858     * or {@link #OVER_SCROLL_NEVER}.
22859     *
22860     * Setting the over-scroll mode of a view will have an effect only if the
22861     * view is capable of scrolling.
22862     *
22863     * @param overScrollMode The new over-scroll mode for this view.
22864     */
22865    public void setOverScrollMode(int overScrollMode) {
22866        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22867                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22868                overScrollMode != OVER_SCROLL_NEVER) {
22869            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22870        }
22871        mOverScrollMode = overScrollMode;
22872    }
22873
22874    /**
22875     * Enable or disable nested scrolling for this view.
22876     *
22877     * <p>If this property is set to true the view will be permitted to initiate nested
22878     * scrolling operations with a compatible parent view in the current hierarchy. If this
22879     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22880     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22881     * the nested scroll.</p>
22882     *
22883     * @param enabled true to enable nested scrolling, false to disable
22884     *
22885     * @see #isNestedScrollingEnabled()
22886     */
22887    public void setNestedScrollingEnabled(boolean enabled) {
22888        if (enabled) {
22889            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22890        } else {
22891            stopNestedScroll();
22892            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22893        }
22894    }
22895
22896    /**
22897     * Returns true if nested scrolling is enabled for this view.
22898     *
22899     * <p>If nested scrolling is enabled and this View class implementation supports it,
22900     * this view will act as a nested scrolling child view when applicable, forwarding data
22901     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22902     * parent.</p>
22903     *
22904     * @return true if nested scrolling is enabled
22905     *
22906     * @see #setNestedScrollingEnabled(boolean)
22907     */
22908    public boolean isNestedScrollingEnabled() {
22909        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22910                PFLAG3_NESTED_SCROLLING_ENABLED;
22911    }
22912
22913    /**
22914     * Begin a nestable scroll operation along the given axes.
22915     *
22916     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22917     *
22918     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22919     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22920     * In the case of touch scrolling the nested scroll will be terminated automatically in
22921     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22922     * In the event of programmatic scrolling the caller must explicitly call
22923     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22924     *
22925     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22926     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22927     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22928     *
22929     * <p>At each incremental step of the scroll the caller should invoke
22930     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22931     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22932     * parent at least partially consumed the scroll and the caller should adjust the amount it
22933     * scrolls by.</p>
22934     *
22935     * <p>After applying the remainder of the scroll delta the caller should invoke
22936     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22937     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22938     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22939     * </p>
22940     *
22941     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22942     *             {@link #SCROLL_AXIS_VERTICAL}.
22943     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22944     *         the current gesture.
22945     *
22946     * @see #stopNestedScroll()
22947     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22948     * @see #dispatchNestedScroll(int, int, int, int, int[])
22949     */
22950    public boolean startNestedScroll(int axes) {
22951        if (hasNestedScrollingParent()) {
22952            // Already in progress
22953            return true;
22954        }
22955        if (isNestedScrollingEnabled()) {
22956            ViewParent p = getParent();
22957            View child = this;
22958            while (p != null) {
22959                try {
22960                    if (p.onStartNestedScroll(child, this, axes)) {
22961                        mNestedScrollingParent = p;
22962                        p.onNestedScrollAccepted(child, this, axes);
22963                        return true;
22964                    }
22965                } catch (AbstractMethodError e) {
22966                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22967                            "method onStartNestedScroll", e);
22968                    // Allow the search upward to continue
22969                }
22970                if (p instanceof View) {
22971                    child = (View) p;
22972                }
22973                p = p.getParent();
22974            }
22975        }
22976        return false;
22977    }
22978
22979    /**
22980     * Stop a nested scroll in progress.
22981     *
22982     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22983     *
22984     * @see #startNestedScroll(int)
22985     */
22986    public void stopNestedScroll() {
22987        if (mNestedScrollingParent != null) {
22988            mNestedScrollingParent.onStopNestedScroll(this);
22989            mNestedScrollingParent = null;
22990        }
22991    }
22992
22993    /**
22994     * Returns true if this view has a nested scrolling parent.
22995     *
22996     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22997     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22998     *
22999     * @return whether this view has a nested scrolling parent
23000     */
23001    public boolean hasNestedScrollingParent() {
23002        return mNestedScrollingParent != null;
23003    }
23004
23005    /**
23006     * Dispatch one step of a nested scroll in progress.
23007     *
23008     * <p>Implementations of views that support nested scrolling should call this to report
23009     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23010     * is not currently in progress or nested scrolling is not
23011     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23012     *
23013     * <p>Compatible View implementations should also call
23014     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23015     * consuming a component of the scroll event themselves.</p>
23016     *
23017     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23018     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23019     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23020     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23021     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23022     *                       in local view coordinates of this view from before this operation
23023     *                       to after it completes. View implementations may use this to adjust
23024     *                       expected input coordinate tracking.
23025     * @return true if the event was dispatched, false if it could not be dispatched.
23026     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23027     */
23028    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23029            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23030        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23031            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23032                int startX = 0;
23033                int startY = 0;
23034                if (offsetInWindow != null) {
23035                    getLocationInWindow(offsetInWindow);
23036                    startX = offsetInWindow[0];
23037                    startY = offsetInWindow[1];
23038                }
23039
23040                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23041                        dxUnconsumed, dyUnconsumed);
23042
23043                if (offsetInWindow != null) {
23044                    getLocationInWindow(offsetInWindow);
23045                    offsetInWindow[0] -= startX;
23046                    offsetInWindow[1] -= startY;
23047                }
23048                return true;
23049            } else if (offsetInWindow != null) {
23050                // No motion, no dispatch. Keep offsetInWindow up to date.
23051                offsetInWindow[0] = 0;
23052                offsetInWindow[1] = 0;
23053            }
23054        }
23055        return false;
23056    }
23057
23058    /**
23059     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23060     *
23061     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23062     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23063     * scrolling operation to consume some or all of the scroll operation before the child view
23064     * consumes it.</p>
23065     *
23066     * @param dx Horizontal scroll distance in pixels
23067     * @param dy Vertical scroll distance in pixels
23068     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23069     *                 and consumed[1] the consumed dy.
23070     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23071     *                       in local view coordinates of this view from before this operation
23072     *                       to after it completes. View implementations may use this to adjust
23073     *                       expected input coordinate tracking.
23074     * @return true if the parent consumed some or all of the scroll delta
23075     * @see #dispatchNestedScroll(int, int, int, int, int[])
23076     */
23077    public boolean dispatchNestedPreScroll(int dx, int dy,
23078            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23079        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23080            if (dx != 0 || dy != 0) {
23081                int startX = 0;
23082                int startY = 0;
23083                if (offsetInWindow != null) {
23084                    getLocationInWindow(offsetInWindow);
23085                    startX = offsetInWindow[0];
23086                    startY = offsetInWindow[1];
23087                }
23088
23089                if (consumed == null) {
23090                    if (mTempNestedScrollConsumed == null) {
23091                        mTempNestedScrollConsumed = new int[2];
23092                    }
23093                    consumed = mTempNestedScrollConsumed;
23094                }
23095                consumed[0] = 0;
23096                consumed[1] = 0;
23097                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23098
23099                if (offsetInWindow != null) {
23100                    getLocationInWindow(offsetInWindow);
23101                    offsetInWindow[0] -= startX;
23102                    offsetInWindow[1] -= startY;
23103                }
23104                return consumed[0] != 0 || consumed[1] != 0;
23105            } else if (offsetInWindow != null) {
23106                offsetInWindow[0] = 0;
23107                offsetInWindow[1] = 0;
23108            }
23109        }
23110        return false;
23111    }
23112
23113    /**
23114     * Dispatch a fling to a nested scrolling parent.
23115     *
23116     * <p>This method should be used to indicate that a nested scrolling child has detected
23117     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23118     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23119     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23120     * along a scrollable axis.</p>
23121     *
23122     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23123     * its own content, it can use this method to delegate the fling to its nested scrolling
23124     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23125     *
23126     * @param velocityX Horizontal fling velocity in pixels per second
23127     * @param velocityY Vertical fling velocity in pixels per second
23128     * @param consumed true if the child consumed the fling, false otherwise
23129     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23130     */
23131    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23132        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23133            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23134        }
23135        return false;
23136    }
23137
23138    /**
23139     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23140     *
23141     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23142     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23143     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23144     * before the child view consumes it. If this method returns <code>true</code>, a nested
23145     * parent view consumed the fling and this view should not scroll as a result.</p>
23146     *
23147     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23148     * the fling at a time. If a parent view consumed the fling this method will return false.
23149     * Custom view implementations should account for this in two ways:</p>
23150     *
23151     * <ul>
23152     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23153     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23154     *     position regardless.</li>
23155     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23156     *     even to settle back to a valid idle position.</li>
23157     * </ul>
23158     *
23159     * <p>Views should also not offer fling velocities to nested parent views along an axis
23160     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23161     * should not offer a horizontal fling velocity to its parents since scrolling along that
23162     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23163     *
23164     * @param velocityX Horizontal fling velocity in pixels per second
23165     * @param velocityY Vertical fling velocity in pixels per second
23166     * @return true if a nested scrolling parent consumed the fling
23167     */
23168    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23169        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23170            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23171        }
23172        return false;
23173    }
23174
23175    /**
23176     * Gets a scale factor that determines the distance the view should scroll
23177     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23178     * @return The vertical scroll scale factor.
23179     * @hide
23180     */
23181    protected float getVerticalScrollFactor() {
23182        if (mVerticalScrollFactor == 0) {
23183            TypedValue outValue = new TypedValue();
23184            if (!mContext.getTheme().resolveAttribute(
23185                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23186                throw new IllegalStateException(
23187                        "Expected theme to define listPreferredItemHeight.");
23188            }
23189            mVerticalScrollFactor = outValue.getDimension(
23190                    mContext.getResources().getDisplayMetrics());
23191        }
23192        return mVerticalScrollFactor;
23193    }
23194
23195    /**
23196     * Gets a scale factor that determines the distance the view should scroll
23197     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23198     * @return The horizontal scroll scale factor.
23199     * @hide
23200     */
23201    protected float getHorizontalScrollFactor() {
23202        // TODO: Should use something else.
23203        return getVerticalScrollFactor();
23204    }
23205
23206    /**
23207     * Return the value specifying the text direction or policy that was set with
23208     * {@link #setTextDirection(int)}.
23209     *
23210     * @return the defined text direction. It can be one of:
23211     *
23212     * {@link #TEXT_DIRECTION_INHERIT},
23213     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23214     * {@link #TEXT_DIRECTION_ANY_RTL},
23215     * {@link #TEXT_DIRECTION_LTR},
23216     * {@link #TEXT_DIRECTION_RTL},
23217     * {@link #TEXT_DIRECTION_LOCALE},
23218     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23219     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23220     *
23221     * @attr ref android.R.styleable#View_textDirection
23222     *
23223     * @hide
23224     */
23225    @ViewDebug.ExportedProperty(category = "text", mapping = {
23226            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23227            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23228            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23229            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23230            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23231            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23232            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23233            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23234    })
23235    public int getRawTextDirection() {
23236        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23237    }
23238
23239    /**
23240     * Set the text direction.
23241     *
23242     * @param textDirection the direction to set. Should be one of:
23243     *
23244     * {@link #TEXT_DIRECTION_INHERIT},
23245     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23246     * {@link #TEXT_DIRECTION_ANY_RTL},
23247     * {@link #TEXT_DIRECTION_LTR},
23248     * {@link #TEXT_DIRECTION_RTL},
23249     * {@link #TEXT_DIRECTION_LOCALE}
23250     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23251     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23252     *
23253     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23254     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23255     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23256     *
23257     * @attr ref android.R.styleable#View_textDirection
23258     */
23259    public void setTextDirection(int textDirection) {
23260        if (getRawTextDirection() != textDirection) {
23261            // Reset the current text direction and the resolved one
23262            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23263            resetResolvedTextDirection();
23264            // Set the new text direction
23265            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23266            // Do resolution
23267            resolveTextDirection();
23268            // Notify change
23269            onRtlPropertiesChanged(getLayoutDirection());
23270            // Refresh
23271            requestLayout();
23272            invalidate(true);
23273        }
23274    }
23275
23276    /**
23277     * Return the resolved text direction.
23278     *
23279     * @return the resolved text direction. Returns one of:
23280     *
23281     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23282     * {@link #TEXT_DIRECTION_ANY_RTL},
23283     * {@link #TEXT_DIRECTION_LTR},
23284     * {@link #TEXT_DIRECTION_RTL},
23285     * {@link #TEXT_DIRECTION_LOCALE},
23286     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23287     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23288     *
23289     * @attr ref android.R.styleable#View_textDirection
23290     */
23291    @ViewDebug.ExportedProperty(category = "text", mapping = {
23292            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23293            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23294            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23295            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23296            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23297            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23298            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23299            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23300    })
23301    public int getTextDirection() {
23302        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23303    }
23304
23305    /**
23306     * Resolve the text direction.
23307     *
23308     * @return true if resolution has been done, false otherwise.
23309     *
23310     * @hide
23311     */
23312    public boolean resolveTextDirection() {
23313        // Reset any previous text direction resolution
23314        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23315
23316        if (hasRtlSupport()) {
23317            // Set resolved text direction flag depending on text direction flag
23318            final int textDirection = getRawTextDirection();
23319            switch(textDirection) {
23320                case TEXT_DIRECTION_INHERIT:
23321                    if (!canResolveTextDirection()) {
23322                        // We cannot do the resolution if there is no parent, so use the default one
23323                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23324                        // Resolution will need to happen again later
23325                        return false;
23326                    }
23327
23328                    // Parent has not yet resolved, so we still return the default
23329                    try {
23330                        if (!mParent.isTextDirectionResolved()) {
23331                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23332                            // Resolution will need to happen again later
23333                            return false;
23334                        }
23335                    } catch (AbstractMethodError e) {
23336                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23337                                " does not fully implement ViewParent", e);
23338                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23339                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23340                        return true;
23341                    }
23342
23343                    // Set current resolved direction to the same value as the parent's one
23344                    int parentResolvedDirection;
23345                    try {
23346                        parentResolvedDirection = mParent.getTextDirection();
23347                    } catch (AbstractMethodError e) {
23348                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23349                                " does not fully implement ViewParent", e);
23350                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23351                    }
23352                    switch (parentResolvedDirection) {
23353                        case TEXT_DIRECTION_FIRST_STRONG:
23354                        case TEXT_DIRECTION_ANY_RTL:
23355                        case TEXT_DIRECTION_LTR:
23356                        case TEXT_DIRECTION_RTL:
23357                        case TEXT_DIRECTION_LOCALE:
23358                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23359                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23360                            mPrivateFlags2 |=
23361                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23362                            break;
23363                        default:
23364                            // Default resolved direction is "first strong" heuristic
23365                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23366                    }
23367                    break;
23368                case TEXT_DIRECTION_FIRST_STRONG:
23369                case TEXT_DIRECTION_ANY_RTL:
23370                case TEXT_DIRECTION_LTR:
23371                case TEXT_DIRECTION_RTL:
23372                case TEXT_DIRECTION_LOCALE:
23373                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23374                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23375                    // Resolved direction is the same as text direction
23376                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23377                    break;
23378                default:
23379                    // Default resolved direction is "first strong" heuristic
23380                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23381            }
23382        } else {
23383            // Default resolved direction is "first strong" heuristic
23384            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23385        }
23386
23387        // Set to resolved
23388        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23389        return true;
23390    }
23391
23392    /**
23393     * Check if text direction resolution can be done.
23394     *
23395     * @return true if text direction resolution can be done otherwise return false.
23396     */
23397    public boolean canResolveTextDirection() {
23398        switch (getRawTextDirection()) {
23399            case TEXT_DIRECTION_INHERIT:
23400                if (mParent != null) {
23401                    try {
23402                        return mParent.canResolveTextDirection();
23403                    } catch (AbstractMethodError e) {
23404                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23405                                " does not fully implement ViewParent", e);
23406                    }
23407                }
23408                return false;
23409
23410            default:
23411                return true;
23412        }
23413    }
23414
23415    /**
23416     * Reset resolved text direction. Text direction will be resolved during a call to
23417     * {@link #onMeasure(int, int)}.
23418     *
23419     * @hide
23420     */
23421    public void resetResolvedTextDirection() {
23422        // Reset any previous text direction resolution
23423        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23424        // Set to default value
23425        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23426    }
23427
23428    /**
23429     * @return true if text direction is inherited.
23430     *
23431     * @hide
23432     */
23433    public boolean isTextDirectionInherited() {
23434        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23435    }
23436
23437    /**
23438     * @return true if text direction is resolved.
23439     */
23440    public boolean isTextDirectionResolved() {
23441        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23442    }
23443
23444    /**
23445     * Return the value specifying the text alignment or policy that was set with
23446     * {@link #setTextAlignment(int)}.
23447     *
23448     * @return the defined text alignment. It can be one of:
23449     *
23450     * {@link #TEXT_ALIGNMENT_INHERIT},
23451     * {@link #TEXT_ALIGNMENT_GRAVITY},
23452     * {@link #TEXT_ALIGNMENT_CENTER},
23453     * {@link #TEXT_ALIGNMENT_TEXT_START},
23454     * {@link #TEXT_ALIGNMENT_TEXT_END},
23455     * {@link #TEXT_ALIGNMENT_VIEW_START},
23456     * {@link #TEXT_ALIGNMENT_VIEW_END}
23457     *
23458     * @attr ref android.R.styleable#View_textAlignment
23459     *
23460     * @hide
23461     */
23462    @ViewDebug.ExportedProperty(category = "text", mapping = {
23463            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23464            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23465            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23466            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23467            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23468            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23469            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23470    })
23471    @TextAlignment
23472    public int getRawTextAlignment() {
23473        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23474    }
23475
23476    /**
23477     * Set the text alignment.
23478     *
23479     * @param textAlignment The text alignment to set. Should be one of
23480     *
23481     * {@link #TEXT_ALIGNMENT_INHERIT},
23482     * {@link #TEXT_ALIGNMENT_GRAVITY},
23483     * {@link #TEXT_ALIGNMENT_CENTER},
23484     * {@link #TEXT_ALIGNMENT_TEXT_START},
23485     * {@link #TEXT_ALIGNMENT_TEXT_END},
23486     * {@link #TEXT_ALIGNMENT_VIEW_START},
23487     * {@link #TEXT_ALIGNMENT_VIEW_END}
23488     *
23489     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23490     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23491     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23492     *
23493     * @attr ref android.R.styleable#View_textAlignment
23494     */
23495    public void setTextAlignment(@TextAlignment int textAlignment) {
23496        if (textAlignment != getRawTextAlignment()) {
23497            // Reset the current and resolved text alignment
23498            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23499            resetResolvedTextAlignment();
23500            // Set the new text alignment
23501            mPrivateFlags2 |=
23502                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23503            // Do resolution
23504            resolveTextAlignment();
23505            // Notify change
23506            onRtlPropertiesChanged(getLayoutDirection());
23507            // Refresh
23508            requestLayout();
23509            invalidate(true);
23510        }
23511    }
23512
23513    /**
23514     * Return the resolved text alignment.
23515     *
23516     * @return the resolved text alignment. Returns one of:
23517     *
23518     * {@link #TEXT_ALIGNMENT_GRAVITY},
23519     * {@link #TEXT_ALIGNMENT_CENTER},
23520     * {@link #TEXT_ALIGNMENT_TEXT_START},
23521     * {@link #TEXT_ALIGNMENT_TEXT_END},
23522     * {@link #TEXT_ALIGNMENT_VIEW_START},
23523     * {@link #TEXT_ALIGNMENT_VIEW_END}
23524     *
23525     * @attr ref android.R.styleable#View_textAlignment
23526     */
23527    @ViewDebug.ExportedProperty(category = "text", mapping = {
23528            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23529            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23530            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23531            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23532            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23533            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23534            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23535    })
23536    @TextAlignment
23537    public int getTextAlignment() {
23538        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23539                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23540    }
23541
23542    /**
23543     * Resolve the text alignment.
23544     *
23545     * @return true if resolution has been done, false otherwise.
23546     *
23547     * @hide
23548     */
23549    public boolean resolveTextAlignment() {
23550        // Reset any previous text alignment resolution
23551        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23552
23553        if (hasRtlSupport()) {
23554            // Set resolved text alignment flag depending on text alignment flag
23555            final int textAlignment = getRawTextAlignment();
23556            switch (textAlignment) {
23557                case TEXT_ALIGNMENT_INHERIT:
23558                    // Check if we can resolve the text alignment
23559                    if (!canResolveTextAlignment()) {
23560                        // We cannot do the resolution if there is no parent so use the default
23561                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23562                        // Resolution will need to happen again later
23563                        return false;
23564                    }
23565
23566                    // Parent has not yet resolved, so we still return the default
23567                    try {
23568                        if (!mParent.isTextAlignmentResolved()) {
23569                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23570                            // Resolution will need to happen again later
23571                            return false;
23572                        }
23573                    } catch (AbstractMethodError e) {
23574                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23575                                " does not fully implement ViewParent", e);
23576                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23577                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23578                        return true;
23579                    }
23580
23581                    int parentResolvedTextAlignment;
23582                    try {
23583                        parentResolvedTextAlignment = mParent.getTextAlignment();
23584                    } catch (AbstractMethodError e) {
23585                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23586                                " does not fully implement ViewParent", e);
23587                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23588                    }
23589                    switch (parentResolvedTextAlignment) {
23590                        case TEXT_ALIGNMENT_GRAVITY:
23591                        case TEXT_ALIGNMENT_TEXT_START:
23592                        case TEXT_ALIGNMENT_TEXT_END:
23593                        case TEXT_ALIGNMENT_CENTER:
23594                        case TEXT_ALIGNMENT_VIEW_START:
23595                        case TEXT_ALIGNMENT_VIEW_END:
23596                            // Resolved text alignment is the same as the parent resolved
23597                            // text alignment
23598                            mPrivateFlags2 |=
23599                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23600                            break;
23601                        default:
23602                            // Use default resolved text alignment
23603                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23604                    }
23605                    break;
23606                case TEXT_ALIGNMENT_GRAVITY:
23607                case TEXT_ALIGNMENT_TEXT_START:
23608                case TEXT_ALIGNMENT_TEXT_END:
23609                case TEXT_ALIGNMENT_CENTER:
23610                case TEXT_ALIGNMENT_VIEW_START:
23611                case TEXT_ALIGNMENT_VIEW_END:
23612                    // Resolved text alignment is the same as text alignment
23613                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23614                    break;
23615                default:
23616                    // Use default resolved text alignment
23617                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23618            }
23619        } else {
23620            // Use default resolved text alignment
23621            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23622        }
23623
23624        // Set the resolved
23625        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23626        return true;
23627    }
23628
23629    /**
23630     * Check if text alignment resolution can be done.
23631     *
23632     * @return true if text alignment resolution can be done otherwise return false.
23633     */
23634    public boolean canResolveTextAlignment() {
23635        switch (getRawTextAlignment()) {
23636            case TEXT_DIRECTION_INHERIT:
23637                if (mParent != null) {
23638                    try {
23639                        return mParent.canResolveTextAlignment();
23640                    } catch (AbstractMethodError e) {
23641                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23642                                " does not fully implement ViewParent", e);
23643                    }
23644                }
23645                return false;
23646
23647            default:
23648                return true;
23649        }
23650    }
23651
23652    /**
23653     * Reset resolved text alignment. Text alignment will be resolved during a call to
23654     * {@link #onMeasure(int, int)}.
23655     *
23656     * @hide
23657     */
23658    public void resetResolvedTextAlignment() {
23659        // Reset any previous text alignment resolution
23660        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23661        // Set to default
23662        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23663    }
23664
23665    /**
23666     * @return true if text alignment is inherited.
23667     *
23668     * @hide
23669     */
23670    public boolean isTextAlignmentInherited() {
23671        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23672    }
23673
23674    /**
23675     * @return true if text alignment is resolved.
23676     */
23677    public boolean isTextAlignmentResolved() {
23678        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23679    }
23680
23681    /**
23682     * Generate a value suitable for use in {@link #setId(int)}.
23683     * This value will not collide with ID values generated at build time by aapt for R.id.
23684     *
23685     * @return a generated ID value
23686     */
23687    public static int generateViewId() {
23688        for (;;) {
23689            final int result = sNextGeneratedId.get();
23690            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23691            int newValue = result + 1;
23692            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23693            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23694                return result;
23695            }
23696        }
23697    }
23698
23699    private static boolean isViewIdGenerated(int id) {
23700        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23701    }
23702
23703    /**
23704     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23705     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23706     *                           a normal View or a ViewGroup with
23707     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23708     * @hide
23709     */
23710    public void captureTransitioningViews(List<View> transitioningViews) {
23711        if (getVisibility() == View.VISIBLE) {
23712            transitioningViews.add(this);
23713        }
23714    }
23715
23716    /**
23717     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23718     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23719     * @hide
23720     */
23721    public void findNamedViews(Map<String, View> namedElements) {
23722        if (getVisibility() == VISIBLE || mGhostView != null) {
23723            String transitionName = getTransitionName();
23724            if (transitionName != null) {
23725                namedElements.put(transitionName, this);
23726            }
23727        }
23728    }
23729
23730    /**
23731     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23732     * The default implementation does not care the location or event types, but some subclasses
23733     * may use it (such as WebViews).
23734     * @param event The MotionEvent from a mouse
23735     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23736     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23737     * @see PointerIcon
23738     */
23739    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23740        final float x = event.getX(pointerIndex);
23741        final float y = event.getY(pointerIndex);
23742        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23743            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23744        }
23745        return mPointerIcon;
23746    }
23747
23748    /**
23749     * Set the pointer icon for the current view.
23750     * Passing {@code null} will restore the pointer icon to its default value.
23751     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23752     */
23753    public void setPointerIcon(PointerIcon pointerIcon) {
23754        mPointerIcon = pointerIcon;
23755        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23756            return;
23757        }
23758        try {
23759            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23760        } catch (RemoteException e) {
23761        }
23762    }
23763
23764    /**
23765     * Gets the pointer icon for the current view.
23766     */
23767    public PointerIcon getPointerIcon() {
23768        return mPointerIcon;
23769    }
23770
23771    /**
23772     * Checks pointer capture status.
23773     *
23774     * @return true if the view has pointer capture.
23775     * @see #requestPointerCapture()
23776     * @see #hasPointerCapture()
23777     */
23778    public boolean hasPointerCapture() {
23779        final ViewRootImpl viewRootImpl = getViewRootImpl();
23780        if (viewRootImpl == null) {
23781            return false;
23782        }
23783        return viewRootImpl.hasPointerCapture();
23784    }
23785
23786    /**
23787     * Requests pointer capture mode.
23788     * <p>
23789     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23790     * change its position. Further mouse will be dispatched with the source
23791     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23792     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23793     * (touchscreens, or stylus) will not be affected.
23794     * <p>
23795     * If the window already has pointer capture, this call does nothing.
23796     * <p>
23797     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23798     * automatically when the window loses focus.
23799     *
23800     * @see #releasePointerCapture()
23801     * @see #hasPointerCapture()
23802     */
23803    public void requestPointerCapture() {
23804        final ViewRootImpl viewRootImpl = getViewRootImpl();
23805        if (viewRootImpl != null) {
23806            viewRootImpl.requestPointerCapture(true);
23807        }
23808    }
23809
23810
23811    /**
23812     * Releases the pointer capture.
23813     * <p>
23814     * If the window does not have pointer capture, this call will do nothing.
23815     * @see #requestPointerCapture()
23816     * @see #hasPointerCapture()
23817     */
23818    public void releasePointerCapture() {
23819        final ViewRootImpl viewRootImpl = getViewRootImpl();
23820        if (viewRootImpl != null) {
23821            viewRootImpl.requestPointerCapture(false);
23822        }
23823    }
23824
23825    /**
23826     * Called when the window has just acquired or lost pointer capture.
23827     *
23828     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23829     */
23830    @CallSuper
23831    public void onPointerCaptureChange(boolean hasCapture) {
23832    }
23833
23834    /**
23835     * @see #onPointerCaptureChange
23836     */
23837    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23838        onPointerCaptureChange(hasCapture);
23839    }
23840
23841    /**
23842     * Implement this method to handle captured pointer events
23843     *
23844     * @param event The captured pointer event.
23845     * @return True if the event was handled, false otherwise.
23846     * @see #requestPointerCapture()
23847     */
23848    public boolean onCapturedPointerEvent(MotionEvent event) {
23849        return false;
23850    }
23851
23852    /**
23853     * Interface definition for a callback to be invoked when a captured pointer event
23854     * is being dispatched this view. The callback will be invoked before the event is
23855     * given to the view.
23856     */
23857    public interface OnCapturedPointerListener {
23858        /**
23859         * Called when a captured pointer event is dispatched to a view.
23860         * @param view The view this event has been dispatched to.
23861         * @param event The captured event.
23862         * @return True if the listener has consumed the event, false otherwise.
23863         */
23864        boolean onCapturedPointer(View view, MotionEvent event);
23865    }
23866
23867    /**
23868     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23869     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23870     */
23871    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23872        getListenerInfo().mOnCapturedPointerListener = l;
23873    }
23874
23875    // Properties
23876    //
23877    /**
23878     * A Property wrapper around the <code>alpha</code> functionality handled by the
23879     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23880     */
23881    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23882        @Override
23883        public void setValue(View object, float value) {
23884            object.setAlpha(value);
23885        }
23886
23887        @Override
23888        public Float get(View object) {
23889            return object.getAlpha();
23890        }
23891    };
23892
23893    /**
23894     * A Property wrapper around the <code>translationX</code> functionality handled by the
23895     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23896     */
23897    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23898        @Override
23899        public void setValue(View object, float value) {
23900            object.setTranslationX(value);
23901        }
23902
23903                @Override
23904        public Float get(View object) {
23905            return object.getTranslationX();
23906        }
23907    };
23908
23909    /**
23910     * A Property wrapper around the <code>translationY</code> functionality handled by the
23911     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23912     */
23913    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23914        @Override
23915        public void setValue(View object, float value) {
23916            object.setTranslationY(value);
23917        }
23918
23919        @Override
23920        public Float get(View object) {
23921            return object.getTranslationY();
23922        }
23923    };
23924
23925    /**
23926     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23927     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23928     */
23929    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23930        @Override
23931        public void setValue(View object, float value) {
23932            object.setTranslationZ(value);
23933        }
23934
23935        @Override
23936        public Float get(View object) {
23937            return object.getTranslationZ();
23938        }
23939    };
23940
23941    /**
23942     * A Property wrapper around the <code>x</code> functionality handled by the
23943     * {@link View#setX(float)} and {@link View#getX()} methods.
23944     */
23945    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23946        @Override
23947        public void setValue(View object, float value) {
23948            object.setX(value);
23949        }
23950
23951        @Override
23952        public Float get(View object) {
23953            return object.getX();
23954        }
23955    };
23956
23957    /**
23958     * A Property wrapper around the <code>y</code> functionality handled by the
23959     * {@link View#setY(float)} and {@link View#getY()} methods.
23960     */
23961    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23962        @Override
23963        public void setValue(View object, float value) {
23964            object.setY(value);
23965        }
23966
23967        @Override
23968        public Float get(View object) {
23969            return object.getY();
23970        }
23971    };
23972
23973    /**
23974     * A Property wrapper around the <code>z</code> functionality handled by the
23975     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23976     */
23977    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23978        @Override
23979        public void setValue(View object, float value) {
23980            object.setZ(value);
23981        }
23982
23983        @Override
23984        public Float get(View object) {
23985            return object.getZ();
23986        }
23987    };
23988
23989    /**
23990     * A Property wrapper around the <code>rotation</code> functionality handled by the
23991     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23992     */
23993    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23994        @Override
23995        public void setValue(View object, float value) {
23996            object.setRotation(value);
23997        }
23998
23999        @Override
24000        public Float get(View object) {
24001            return object.getRotation();
24002        }
24003    };
24004
24005    /**
24006     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24007     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24008     */
24009    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24010        @Override
24011        public void setValue(View object, float value) {
24012            object.setRotationX(value);
24013        }
24014
24015        @Override
24016        public Float get(View object) {
24017            return object.getRotationX();
24018        }
24019    };
24020
24021    /**
24022     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24023     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24024     */
24025    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24026        @Override
24027        public void setValue(View object, float value) {
24028            object.setRotationY(value);
24029        }
24030
24031        @Override
24032        public Float get(View object) {
24033            return object.getRotationY();
24034        }
24035    };
24036
24037    /**
24038     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24039     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24040     */
24041    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24042        @Override
24043        public void setValue(View object, float value) {
24044            object.setScaleX(value);
24045        }
24046
24047        @Override
24048        public Float get(View object) {
24049            return object.getScaleX();
24050        }
24051    };
24052
24053    /**
24054     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24055     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24056     */
24057    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24058        @Override
24059        public void setValue(View object, float value) {
24060            object.setScaleY(value);
24061        }
24062
24063        @Override
24064        public Float get(View object) {
24065            return object.getScaleY();
24066        }
24067    };
24068
24069    /**
24070     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24071     * Each MeasureSpec represents a requirement for either the width or the height.
24072     * A MeasureSpec is comprised of a size and a mode. There are three possible
24073     * modes:
24074     * <dl>
24075     * <dt>UNSPECIFIED</dt>
24076     * <dd>
24077     * The parent has not imposed any constraint on the child. It can be whatever size
24078     * it wants.
24079     * </dd>
24080     *
24081     * <dt>EXACTLY</dt>
24082     * <dd>
24083     * The parent has determined an exact size for the child. The child is going to be
24084     * given those bounds regardless of how big it wants to be.
24085     * </dd>
24086     *
24087     * <dt>AT_MOST</dt>
24088     * <dd>
24089     * The child can be as large as it wants up to the specified size.
24090     * </dd>
24091     * </dl>
24092     *
24093     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24094     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24095     */
24096    public static class MeasureSpec {
24097        private static final int MODE_SHIFT = 30;
24098        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24099
24100        /** @hide */
24101        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24102        @Retention(RetentionPolicy.SOURCE)
24103        public @interface MeasureSpecMode {}
24104
24105        /**
24106         * Measure specification mode: The parent has not imposed any constraint
24107         * on the child. It can be whatever size it wants.
24108         */
24109        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24110
24111        /**
24112         * Measure specification mode: The parent has determined an exact size
24113         * for the child. The child is going to be given those bounds regardless
24114         * of how big it wants to be.
24115         */
24116        public static final int EXACTLY     = 1 << MODE_SHIFT;
24117
24118        /**
24119         * Measure specification mode: The child can be as large as it wants up
24120         * to the specified size.
24121         */
24122        public static final int AT_MOST     = 2 << MODE_SHIFT;
24123
24124        /**
24125         * Creates a measure specification based on the supplied size and mode.
24126         *
24127         * The mode must always be one of the following:
24128         * <ul>
24129         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24130         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24131         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24132         * </ul>
24133         *
24134         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24135         * implementation was such that the order of arguments did not matter
24136         * and overflow in either value could impact the resulting MeasureSpec.
24137         * {@link android.widget.RelativeLayout} was affected by this bug.
24138         * Apps targeting API levels greater than 17 will get the fixed, more strict
24139         * behavior.</p>
24140         *
24141         * @param size the size of the measure specification
24142         * @param mode the mode of the measure specification
24143         * @return the measure specification based on size and mode
24144         */
24145        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24146                                          @MeasureSpecMode int mode) {
24147            if (sUseBrokenMakeMeasureSpec) {
24148                return size + mode;
24149            } else {
24150                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24151            }
24152        }
24153
24154        /**
24155         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24156         * will automatically get a size of 0. Older apps expect this.
24157         *
24158         * @hide internal use only for compatibility with system widgets and older apps
24159         */
24160        public static int makeSafeMeasureSpec(int size, int mode) {
24161            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24162                return 0;
24163            }
24164            return makeMeasureSpec(size, mode);
24165        }
24166
24167        /**
24168         * Extracts the mode from the supplied measure specification.
24169         *
24170         * @param measureSpec the measure specification to extract the mode from
24171         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24172         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24173         *         {@link android.view.View.MeasureSpec#EXACTLY}
24174         */
24175        @MeasureSpecMode
24176        public static int getMode(int measureSpec) {
24177            //noinspection ResourceType
24178            return (measureSpec & MODE_MASK);
24179        }
24180
24181        /**
24182         * Extracts the size from the supplied measure specification.
24183         *
24184         * @param measureSpec the measure specification to extract the size from
24185         * @return the size in pixels defined in the supplied measure specification
24186         */
24187        public static int getSize(int measureSpec) {
24188            return (measureSpec & ~MODE_MASK);
24189        }
24190
24191        static int adjust(int measureSpec, int delta) {
24192            final int mode = getMode(measureSpec);
24193            int size = getSize(measureSpec);
24194            if (mode == UNSPECIFIED) {
24195                // No need to adjust size for UNSPECIFIED mode.
24196                return makeMeasureSpec(size, UNSPECIFIED);
24197            }
24198            size += delta;
24199            if (size < 0) {
24200                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24201                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24202                size = 0;
24203            }
24204            return makeMeasureSpec(size, mode);
24205        }
24206
24207        /**
24208         * Returns a String representation of the specified measure
24209         * specification.
24210         *
24211         * @param measureSpec the measure specification to convert to a String
24212         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24213         */
24214        public static String toString(int measureSpec) {
24215            int mode = getMode(measureSpec);
24216            int size = getSize(measureSpec);
24217
24218            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24219
24220            if (mode == UNSPECIFIED)
24221                sb.append("UNSPECIFIED ");
24222            else if (mode == EXACTLY)
24223                sb.append("EXACTLY ");
24224            else if (mode == AT_MOST)
24225                sb.append("AT_MOST ");
24226            else
24227                sb.append(mode).append(" ");
24228
24229            sb.append(size);
24230            return sb.toString();
24231        }
24232    }
24233
24234    private final class CheckForLongPress implements Runnable {
24235        private int mOriginalWindowAttachCount;
24236        private float mX;
24237        private float mY;
24238        private boolean mOriginalPressedState;
24239
24240        @Override
24241        public void run() {
24242            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24243                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24244                if (performLongClick(mX, mY)) {
24245                    mHasPerformedLongPress = true;
24246                }
24247            }
24248        }
24249
24250        public void setAnchor(float x, float y) {
24251            mX = x;
24252            mY = y;
24253        }
24254
24255        public void rememberWindowAttachCount() {
24256            mOriginalWindowAttachCount = mWindowAttachCount;
24257        }
24258
24259        public void rememberPressedState() {
24260            mOriginalPressedState = isPressed();
24261        }
24262    }
24263
24264    private final class CheckForTap implements Runnable {
24265        public float x;
24266        public float y;
24267
24268        @Override
24269        public void run() {
24270            mPrivateFlags &= ~PFLAG_PREPRESSED;
24271            setPressed(true, x, y);
24272            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24273        }
24274    }
24275
24276    private final class PerformClick implements Runnable {
24277        @Override
24278        public void run() {
24279            performClick();
24280        }
24281    }
24282
24283    /**
24284     * This method returns a ViewPropertyAnimator object, which can be used to animate
24285     * specific properties on this View.
24286     *
24287     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24288     */
24289    public ViewPropertyAnimator animate() {
24290        if (mAnimator == null) {
24291            mAnimator = new ViewPropertyAnimator(this);
24292        }
24293        return mAnimator;
24294    }
24295
24296    /**
24297     * Sets the name of the View to be used to identify Views in Transitions.
24298     * Names should be unique in the View hierarchy.
24299     *
24300     * @param transitionName The name of the View to uniquely identify it for Transitions.
24301     */
24302    public final void setTransitionName(String transitionName) {
24303        mTransitionName = transitionName;
24304    }
24305
24306    /**
24307     * Returns the name of the View to be used to identify Views in Transitions.
24308     * Names should be unique in the View hierarchy.
24309     *
24310     * <p>This returns null if the View has not been given a name.</p>
24311     *
24312     * @return The name used of the View to be used to identify Views in Transitions or null
24313     * if no name has been given.
24314     */
24315    @ViewDebug.ExportedProperty
24316    public String getTransitionName() {
24317        return mTransitionName;
24318    }
24319
24320    /**
24321     * @hide
24322     */
24323    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24324        // Do nothing.
24325    }
24326
24327    /**
24328     * Interface definition for a callback to be invoked when a hardware key event is
24329     * dispatched to this view. The callback will be invoked before the key event is
24330     * given to the view. This is only useful for hardware keyboards; a software input
24331     * method has no obligation to trigger this listener.
24332     */
24333    public interface OnKeyListener {
24334        /**
24335         * Called when a hardware key is dispatched to a view. This allows listeners to
24336         * get a chance to respond before the target view.
24337         * <p>Key presses in software keyboards will generally NOT trigger this method,
24338         * although some may elect to do so in some situations. Do not assume a
24339         * software input method has to be key-based; even if it is, it may use key presses
24340         * in a different way than you expect, so there is no way to reliably catch soft
24341         * input key presses.
24342         *
24343         * @param v The view the key has been dispatched to.
24344         * @param keyCode The code for the physical key that was pressed
24345         * @param event The KeyEvent object containing full information about
24346         *        the event.
24347         * @return True if the listener has consumed the event, false otherwise.
24348         */
24349        boolean onKey(View v, int keyCode, KeyEvent event);
24350    }
24351
24352    /**
24353     * Interface definition for a callback to be invoked when a touch event is
24354     * dispatched to this view. The callback will be invoked before the touch
24355     * event is given to the view.
24356     */
24357    public interface OnTouchListener {
24358        /**
24359         * Called when a touch event is dispatched to a view. This allows listeners to
24360         * get a chance to respond before the target view.
24361         *
24362         * @param v The view the touch event has been dispatched to.
24363         * @param event The MotionEvent object containing full information about
24364         *        the event.
24365         * @return True if the listener has consumed the event, false otherwise.
24366         */
24367        boolean onTouch(View v, MotionEvent event);
24368    }
24369
24370    /**
24371     * Interface definition for a callback to be invoked when a hover event is
24372     * dispatched to this view. The callback will be invoked before the hover
24373     * event is given to the view.
24374     */
24375    public interface OnHoverListener {
24376        /**
24377         * Called when a hover event is dispatched to a view. This allows listeners to
24378         * get a chance to respond before the target view.
24379         *
24380         * @param v The view the hover event has been dispatched to.
24381         * @param event The MotionEvent object containing full information about
24382         *        the event.
24383         * @return True if the listener has consumed the event, false otherwise.
24384         */
24385        boolean onHover(View v, MotionEvent event);
24386    }
24387
24388    /**
24389     * Interface definition for a callback to be invoked when a generic motion event is
24390     * dispatched to this view. The callback will be invoked before the generic motion
24391     * event is given to the view.
24392     */
24393    public interface OnGenericMotionListener {
24394        /**
24395         * Called when a generic motion event is dispatched to a view. This allows listeners to
24396         * get a chance to respond before the target view.
24397         *
24398         * @param v The view the generic motion event has been dispatched to.
24399         * @param event The MotionEvent object containing full information about
24400         *        the event.
24401         * @return True if the listener has consumed the event, false otherwise.
24402         */
24403        boolean onGenericMotion(View v, MotionEvent event);
24404    }
24405
24406    /**
24407     * Interface definition for a callback to be invoked when a view has been clicked and held.
24408     */
24409    public interface OnLongClickListener {
24410        /**
24411         * Called when a view has been clicked and held.
24412         *
24413         * @param v The view that was clicked and held.
24414         *
24415         * @return true if the callback consumed the long click, false otherwise.
24416         */
24417        boolean onLongClick(View v);
24418    }
24419
24420    /**
24421     * Interface definition for a callback to be invoked when a drag is being dispatched
24422     * to this view.  The callback will be invoked before the hosting view's own
24423     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24424     * onDrag(event) behavior, it should return 'false' from this callback.
24425     *
24426     * <div class="special reference">
24427     * <h3>Developer Guides</h3>
24428     * <p>For a guide to implementing drag and drop features, read the
24429     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24430     * </div>
24431     */
24432    public interface OnDragListener {
24433        /**
24434         * Called when a drag event is dispatched to a view. This allows listeners
24435         * to get a chance to override base View behavior.
24436         *
24437         * @param v The View that received the drag event.
24438         * @param event The {@link android.view.DragEvent} object for the drag event.
24439         * @return {@code true} if the drag event was handled successfully, or {@code false}
24440         * if the drag event was not handled. Note that {@code false} will trigger the View
24441         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24442         */
24443        boolean onDrag(View v, DragEvent event);
24444    }
24445
24446    /**
24447     * Interface definition for a callback to be invoked when the focus state of
24448     * a view changed.
24449     */
24450    public interface OnFocusChangeListener {
24451        /**
24452         * Called when the focus state of a view has changed.
24453         *
24454         * @param v The view whose state has changed.
24455         * @param hasFocus The new focus state of v.
24456         */
24457        void onFocusChange(View v, boolean hasFocus);
24458    }
24459
24460    /**
24461     * Interface definition for a callback to be invoked when a view is clicked.
24462     */
24463    public interface OnClickListener {
24464        /**
24465         * Called when a view has been clicked.
24466         *
24467         * @param v The view that was clicked.
24468         */
24469        void onClick(View v);
24470    }
24471
24472    /**
24473     * Interface definition for a callback to be invoked when a view is context clicked.
24474     */
24475    public interface OnContextClickListener {
24476        /**
24477         * Called when a view is context clicked.
24478         *
24479         * @param v The view that has been context clicked.
24480         * @return true if the callback consumed the context click, false otherwise.
24481         */
24482        boolean onContextClick(View v);
24483    }
24484
24485    /**
24486     * Interface definition for a callback to be invoked when the context menu
24487     * for this view is being built.
24488     */
24489    public interface OnCreateContextMenuListener {
24490        /**
24491         * Called when the context menu for this view is being built. It is not
24492         * safe to hold onto the menu after this method returns.
24493         *
24494         * @param menu The context menu that is being built
24495         * @param v The view for which the context menu is being built
24496         * @param menuInfo Extra information about the item for which the
24497         *            context menu should be shown. This information will vary
24498         *            depending on the class of v.
24499         */
24500        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24501    }
24502
24503    /**
24504     * Interface definition for a callback to be invoked when the status bar changes
24505     * visibility.  This reports <strong>global</strong> changes to the system UI
24506     * state, not what the application is requesting.
24507     *
24508     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24509     */
24510    public interface OnSystemUiVisibilityChangeListener {
24511        /**
24512         * Called when the status bar changes visibility because of a call to
24513         * {@link View#setSystemUiVisibility(int)}.
24514         *
24515         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24516         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24517         * This tells you the <strong>global</strong> state of these UI visibility
24518         * flags, not what your app is currently applying.
24519         */
24520        public void onSystemUiVisibilityChange(int visibility);
24521    }
24522
24523    /**
24524     * Interface definition for a callback to be invoked when this view is attached
24525     * or detached from its window.
24526     */
24527    public interface OnAttachStateChangeListener {
24528        /**
24529         * Called when the view is attached to a window.
24530         * @param v The view that was attached
24531         */
24532        public void onViewAttachedToWindow(View v);
24533        /**
24534         * Called when the view is detached from a window.
24535         * @param v The view that was detached
24536         */
24537        public void onViewDetachedFromWindow(View v);
24538    }
24539
24540    /**
24541     * Listener for applying window insets on a view in a custom way.
24542     *
24543     * <p>Apps may choose to implement this interface if they want to apply custom policy
24544     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24545     * is set, its
24546     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24547     * method will be called instead of the View's own
24548     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24549     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24550     * the View's normal behavior as part of its own.</p>
24551     */
24552    public interface OnApplyWindowInsetsListener {
24553        /**
24554         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24555         * on a View, this listener method will be called instead of the view's own
24556         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24557         *
24558         * @param v The view applying window insets
24559         * @param insets The insets to apply
24560         * @return The insets supplied, minus any insets that were consumed
24561         */
24562        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24563    }
24564
24565    private final class UnsetPressedState implements Runnable {
24566        @Override
24567        public void run() {
24568            setPressed(false);
24569        }
24570    }
24571
24572    /**
24573     * When a view becomes invisible checks if autofill considers the view invisible too. This
24574     * happens after the regular removal operation to make sure the operation is finished by the
24575     * time this is called.
24576     */
24577    private static class VisibilityChangeForAutofillHandler extends Handler {
24578        private final AutofillManager mAfm;
24579        private final View mView;
24580
24581        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
24582                @NonNull View view) {
24583            mAfm = afm;
24584            mView = view;
24585        }
24586
24587        @Override
24588        public void handleMessage(Message msg) {
24589            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
24590        }
24591    }
24592
24593    /**
24594     * Base class for derived classes that want to save and restore their own
24595     * state in {@link android.view.View#onSaveInstanceState()}.
24596     */
24597    public static class BaseSavedState extends AbsSavedState {
24598        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24599        static final int IS_AUTOFILLED = 0b10;
24600        static final int ACCESSIBILITY_ID = 0b100;
24601
24602        // Flags that describe what data in this state is valid
24603        int mSavedData;
24604        String mStartActivityRequestWhoSaved;
24605        boolean mIsAutofilled;
24606        int mAccessibilityViewId;
24607
24608        /**
24609         * Constructor used when reading from a parcel. Reads the state of the superclass.
24610         *
24611         * @param source parcel to read from
24612         */
24613        public BaseSavedState(Parcel source) {
24614            this(source, null);
24615        }
24616
24617        /**
24618         * Constructor used when reading from a parcel using a given class loader.
24619         * Reads the state of the superclass.
24620         *
24621         * @param source parcel to read from
24622         * @param loader ClassLoader to use for reading
24623         */
24624        public BaseSavedState(Parcel source, ClassLoader loader) {
24625            super(source, loader);
24626            mSavedData = source.readInt();
24627            mStartActivityRequestWhoSaved = source.readString();
24628            mIsAutofilled = source.readBoolean();
24629            mAccessibilityViewId = source.readInt();
24630        }
24631
24632        /**
24633         * Constructor called by derived classes when creating their SavedState objects
24634         *
24635         * @param superState The state of the superclass of this view
24636         */
24637        public BaseSavedState(Parcelable superState) {
24638            super(superState);
24639        }
24640
24641        @Override
24642        public void writeToParcel(Parcel out, int flags) {
24643            super.writeToParcel(out, flags);
24644
24645            out.writeInt(mSavedData);
24646            out.writeString(mStartActivityRequestWhoSaved);
24647            out.writeBoolean(mIsAutofilled);
24648            out.writeInt(mAccessibilityViewId);
24649        }
24650
24651        public static final Parcelable.Creator<BaseSavedState> CREATOR
24652                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24653            @Override
24654            public BaseSavedState createFromParcel(Parcel in) {
24655                return new BaseSavedState(in);
24656            }
24657
24658            @Override
24659            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24660                return new BaseSavedState(in, loader);
24661            }
24662
24663            @Override
24664            public BaseSavedState[] newArray(int size) {
24665                return new BaseSavedState[size];
24666            }
24667        };
24668    }
24669
24670    /**
24671     * A set of information given to a view when it is attached to its parent
24672     * window.
24673     */
24674    final static class AttachInfo {
24675        interface Callbacks {
24676            void playSoundEffect(int effectId);
24677            boolean performHapticFeedback(int effectId, boolean always);
24678        }
24679
24680        /**
24681         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24682         * to a Handler. This class contains the target (View) to invalidate and
24683         * the coordinates of the dirty rectangle.
24684         *
24685         * For performance purposes, this class also implements a pool of up to
24686         * POOL_LIMIT objects that get reused. This reduces memory allocations
24687         * whenever possible.
24688         */
24689        static class InvalidateInfo {
24690            private static final int POOL_LIMIT = 10;
24691
24692            private static final SynchronizedPool<InvalidateInfo> sPool =
24693                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24694
24695            View target;
24696
24697            int left;
24698            int top;
24699            int right;
24700            int bottom;
24701
24702            public static InvalidateInfo obtain() {
24703                InvalidateInfo instance = sPool.acquire();
24704                return (instance != null) ? instance : new InvalidateInfo();
24705            }
24706
24707            public void recycle() {
24708                target = null;
24709                sPool.release(this);
24710            }
24711        }
24712
24713        final IWindowSession mSession;
24714
24715        final IWindow mWindow;
24716
24717        final IBinder mWindowToken;
24718
24719        Display mDisplay;
24720
24721        final Callbacks mRootCallbacks;
24722
24723        IWindowId mIWindowId;
24724        WindowId mWindowId;
24725
24726        /**
24727         * The top view of the hierarchy.
24728         */
24729        View mRootView;
24730
24731        IBinder mPanelParentWindowToken;
24732
24733        boolean mHardwareAccelerated;
24734        boolean mHardwareAccelerationRequested;
24735        ThreadedRenderer mThreadedRenderer;
24736        List<RenderNode> mPendingAnimatingRenderNodes;
24737
24738        /**
24739         * The state of the display to which the window is attached, as reported
24740         * by {@link Display#getState()}.  Note that the display state constants
24741         * declared by {@link Display} do not exactly line up with the screen state
24742         * constants declared by {@link View} (there are more display states than
24743         * screen states).
24744         */
24745        int mDisplayState = Display.STATE_UNKNOWN;
24746
24747        /**
24748         * Scale factor used by the compatibility mode
24749         */
24750        float mApplicationScale;
24751
24752        /**
24753         * Indicates whether the application is in compatibility mode
24754         */
24755        boolean mScalingRequired;
24756
24757        /**
24758         * Left position of this view's window
24759         */
24760        int mWindowLeft;
24761
24762        /**
24763         * Top position of this view's window
24764         */
24765        int mWindowTop;
24766
24767        /**
24768         * Indicates whether views need to use 32-bit drawing caches
24769         */
24770        boolean mUse32BitDrawingCache;
24771
24772        /**
24773         * For windows that are full-screen but using insets to layout inside
24774         * of the screen areas, these are the current insets to appear inside
24775         * the overscan area of the display.
24776         */
24777        final Rect mOverscanInsets = new Rect();
24778
24779        /**
24780         * For windows that are full-screen but using insets to layout inside
24781         * of the screen decorations, these are the current insets for the
24782         * content of the window.
24783         */
24784        final Rect mContentInsets = new Rect();
24785
24786        /**
24787         * For windows that are full-screen but using insets to layout inside
24788         * of the screen decorations, these are the current insets for the
24789         * actual visible parts of the window.
24790         */
24791        final Rect mVisibleInsets = new Rect();
24792
24793        /**
24794         * For windows that are full-screen but using insets to layout inside
24795         * of the screen decorations, these are the current insets for the
24796         * stable system windows.
24797         */
24798        final Rect mStableInsets = new Rect();
24799
24800        /**
24801         * For windows that include areas that are not covered by real surface these are the outsets
24802         * for real surface.
24803         */
24804        final Rect mOutsets = new Rect();
24805
24806        /**
24807         * In multi-window we force show the navigation bar. Because we don't want that the surface
24808         * size changes in this mode, we instead have a flag whether the navigation bar size should
24809         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24810         */
24811        boolean mAlwaysConsumeNavBar;
24812
24813        /**
24814         * The internal insets given by this window.  This value is
24815         * supplied by the client (through
24816         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24817         * be given to the window manager when changed to be used in laying
24818         * out windows behind it.
24819         */
24820        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24821                = new ViewTreeObserver.InternalInsetsInfo();
24822
24823        /**
24824         * Set to true when mGivenInternalInsets is non-empty.
24825         */
24826        boolean mHasNonEmptyGivenInternalInsets;
24827
24828        /**
24829         * All views in the window's hierarchy that serve as scroll containers,
24830         * used to determine if the window can be resized or must be panned
24831         * to adjust for a soft input area.
24832         */
24833        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24834
24835        final KeyEvent.DispatcherState mKeyDispatchState
24836                = new KeyEvent.DispatcherState();
24837
24838        /**
24839         * Indicates whether the view's window currently has the focus.
24840         */
24841        boolean mHasWindowFocus;
24842
24843        /**
24844         * The current visibility of the window.
24845         */
24846        int mWindowVisibility;
24847
24848        /**
24849         * Indicates the time at which drawing started to occur.
24850         */
24851        long mDrawingTime;
24852
24853        /**
24854         * Indicates whether or not ignoring the DIRTY_MASK flags.
24855         */
24856        boolean mIgnoreDirtyState;
24857
24858        /**
24859         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24860         * to avoid clearing that flag prematurely.
24861         */
24862        boolean mSetIgnoreDirtyState = false;
24863
24864        /**
24865         * Indicates whether the view's window is currently in touch mode.
24866         */
24867        boolean mInTouchMode;
24868
24869        /**
24870         * Indicates whether the view has requested unbuffered input dispatching for the current
24871         * event stream.
24872         */
24873        boolean mUnbufferedDispatchRequested;
24874
24875        /**
24876         * Indicates that ViewAncestor should trigger a global layout change
24877         * the next time it performs a traversal
24878         */
24879        boolean mRecomputeGlobalAttributes;
24880
24881        /**
24882         * Always report new attributes at next traversal.
24883         */
24884        boolean mForceReportNewAttributes;
24885
24886        /**
24887         * Set during a traveral if any views want to keep the screen on.
24888         */
24889        boolean mKeepScreenOn;
24890
24891        /**
24892         * Set during a traveral if the light center needs to be updated.
24893         */
24894        boolean mNeedsUpdateLightCenter;
24895
24896        /**
24897         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24898         */
24899        int mSystemUiVisibility;
24900
24901        /**
24902         * Hack to force certain system UI visibility flags to be cleared.
24903         */
24904        int mDisabledSystemUiVisibility;
24905
24906        /**
24907         * Last global system UI visibility reported by the window manager.
24908         */
24909        int mGlobalSystemUiVisibility = -1;
24910
24911        /**
24912         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24913         * attached.
24914         */
24915        boolean mHasSystemUiListeners;
24916
24917        /**
24918         * Set if the window has requested to extend into the overscan region
24919         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24920         */
24921        boolean mOverscanRequested;
24922
24923        /**
24924         * Set if the visibility of any views has changed.
24925         */
24926        boolean mViewVisibilityChanged;
24927
24928        /**
24929         * Set to true if a view has been scrolled.
24930         */
24931        boolean mViewScrollChanged;
24932
24933        /**
24934         * Set to true if high contrast mode enabled
24935         */
24936        boolean mHighContrastText;
24937
24938        /**
24939         * Set to true if a pointer event is currently being handled.
24940         */
24941        boolean mHandlingPointerEvent;
24942
24943        /**
24944         * Global to the view hierarchy used as a temporary for dealing with
24945         * x/y points in the transparent region computations.
24946         */
24947        final int[] mTransparentLocation = new int[2];
24948
24949        /**
24950         * Global to the view hierarchy used as a temporary for dealing with
24951         * x/y points in the ViewGroup.invalidateChild implementation.
24952         */
24953        final int[] mInvalidateChildLocation = new int[2];
24954
24955        /**
24956         * Global to the view hierarchy used as a temporary for dealing with
24957         * computing absolute on-screen location.
24958         */
24959        final int[] mTmpLocation = new int[2];
24960
24961        /**
24962         * Global to the view hierarchy used as a temporary for dealing with
24963         * x/y location when view is transformed.
24964         */
24965        final float[] mTmpTransformLocation = new float[2];
24966
24967        /**
24968         * The view tree observer used to dispatch global events like
24969         * layout, pre-draw, touch mode change, etc.
24970         */
24971        final ViewTreeObserver mTreeObserver;
24972
24973        /**
24974         * A Canvas used by the view hierarchy to perform bitmap caching.
24975         */
24976        Canvas mCanvas;
24977
24978        /**
24979         * The view root impl.
24980         */
24981        final ViewRootImpl mViewRootImpl;
24982
24983        /**
24984         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24985         * handler can be used to pump events in the UI events queue.
24986         */
24987        final Handler mHandler;
24988
24989        /**
24990         * Temporary for use in computing invalidate rectangles while
24991         * calling up the hierarchy.
24992         */
24993        final Rect mTmpInvalRect = new Rect();
24994
24995        /**
24996         * Temporary for use in computing hit areas with transformed views
24997         */
24998        final RectF mTmpTransformRect = new RectF();
24999
25000        /**
25001         * Temporary for use in computing hit areas with transformed views
25002         */
25003        final RectF mTmpTransformRect1 = new RectF();
25004
25005        /**
25006         * Temporary list of rectanges.
25007         */
25008        final List<RectF> mTmpRectList = new ArrayList<>();
25009
25010        /**
25011         * Temporary for use in transforming invalidation rect
25012         */
25013        final Matrix mTmpMatrix = new Matrix();
25014
25015        /**
25016         * Temporary for use in transforming invalidation rect
25017         */
25018        final Transformation mTmpTransformation = new Transformation();
25019
25020        /**
25021         * Temporary for use in querying outlines from OutlineProviders
25022         */
25023        final Outline mTmpOutline = new Outline();
25024
25025        /**
25026         * Temporary list for use in collecting focusable descendents of a view.
25027         */
25028        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25029
25030        /**
25031         * The id of the window for accessibility purposes.
25032         */
25033        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25034
25035        /**
25036         * Flags related to accessibility processing.
25037         *
25038         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25039         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25040         */
25041        int mAccessibilityFetchFlags;
25042
25043        /**
25044         * The drawable for highlighting accessibility focus.
25045         */
25046        Drawable mAccessibilityFocusDrawable;
25047
25048        /**
25049         * The drawable for highlighting autofilled views.
25050         *
25051         * @see #isAutofilled()
25052         */
25053        Drawable mAutofilledDrawable;
25054
25055        /**
25056         * Show where the margins, bounds and layout bounds are for each view.
25057         */
25058        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25059
25060        /**
25061         * Point used to compute visible regions.
25062         */
25063        final Point mPoint = new Point();
25064
25065        /**
25066         * Used to track which View originated a requestLayout() call, used when
25067         * requestLayout() is called during layout.
25068         */
25069        View mViewRequestingLayout;
25070
25071        /**
25072         * Used to track views that need (at least) a partial relayout at their current size
25073         * during the next traversal.
25074         */
25075        List<View> mPartialLayoutViews = new ArrayList<>();
25076
25077        /**
25078         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25079         * modification. Lazily assigned during ViewRootImpl layout.
25080         */
25081        List<View> mEmptyPartialLayoutViews;
25082
25083        /**
25084         * Used to track the identity of the current drag operation.
25085         */
25086        IBinder mDragToken;
25087
25088        /**
25089         * The drag shadow surface for the current drag operation.
25090         */
25091        public Surface mDragSurface;
25092
25093
25094        /**
25095         * The view that currently has a tooltip displayed.
25096         */
25097        View mTooltipHost;
25098
25099        /**
25100         * Creates a new set of attachment information with the specified
25101         * events handler and thread.
25102         *
25103         * @param handler the events handler the view must use
25104         */
25105        AttachInfo(IWindowSession session, IWindow window, Display display,
25106                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25107                Context context) {
25108            mSession = session;
25109            mWindow = window;
25110            mWindowToken = window.asBinder();
25111            mDisplay = display;
25112            mViewRootImpl = viewRootImpl;
25113            mHandler = handler;
25114            mRootCallbacks = effectPlayer;
25115            mTreeObserver = new ViewTreeObserver(context);
25116        }
25117    }
25118
25119    /**
25120     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25121     * is supported. This avoids keeping too many unused fields in most
25122     * instances of View.</p>
25123     */
25124    private static class ScrollabilityCache implements Runnable {
25125
25126        /**
25127         * Scrollbars are not visible
25128         */
25129        public static final int OFF = 0;
25130
25131        /**
25132         * Scrollbars are visible
25133         */
25134        public static final int ON = 1;
25135
25136        /**
25137         * Scrollbars are fading away
25138         */
25139        public static final int FADING = 2;
25140
25141        public boolean fadeScrollBars;
25142
25143        public int fadingEdgeLength;
25144        public int scrollBarDefaultDelayBeforeFade;
25145        public int scrollBarFadeDuration;
25146
25147        public int scrollBarSize;
25148        public int scrollBarMinTouchTarget;
25149        public ScrollBarDrawable scrollBar;
25150        public float[] interpolatorValues;
25151        public View host;
25152
25153        public final Paint paint;
25154        public final Matrix matrix;
25155        public Shader shader;
25156
25157        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25158
25159        private static final float[] OPAQUE = { 255 };
25160        private static final float[] TRANSPARENT = { 0.0f };
25161
25162        /**
25163         * When fading should start. This time moves into the future every time
25164         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25165         */
25166        public long fadeStartTime;
25167
25168
25169        /**
25170         * The current state of the scrollbars: ON, OFF, or FADING
25171         */
25172        public int state = OFF;
25173
25174        private int mLastColor;
25175
25176        public final Rect mScrollBarBounds = new Rect();
25177        public final Rect mScrollBarTouchBounds = new Rect();
25178
25179        public static final int NOT_DRAGGING = 0;
25180        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25181        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25182        public int mScrollBarDraggingState = NOT_DRAGGING;
25183
25184        public float mScrollBarDraggingPos = 0;
25185
25186        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25187            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25188            scrollBarSize = configuration.getScaledScrollBarSize();
25189            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25190            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25191            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25192
25193            paint = new Paint();
25194            matrix = new Matrix();
25195            // use use a height of 1, and then wack the matrix each time we
25196            // actually use it.
25197            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25198            paint.setShader(shader);
25199            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25200
25201            this.host = host;
25202        }
25203
25204        public void setFadeColor(int color) {
25205            if (color != mLastColor) {
25206                mLastColor = color;
25207
25208                if (color != 0) {
25209                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25210                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25211                    paint.setShader(shader);
25212                    // Restore the default transfer mode (src_over)
25213                    paint.setXfermode(null);
25214                } else {
25215                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25216                    paint.setShader(shader);
25217                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25218                }
25219            }
25220        }
25221
25222        public void run() {
25223            long now = AnimationUtils.currentAnimationTimeMillis();
25224            if (now >= fadeStartTime) {
25225
25226                // the animation fades the scrollbars out by changing
25227                // the opacity (alpha) from fully opaque to fully
25228                // transparent
25229                int nextFrame = (int) now;
25230                int framesCount = 0;
25231
25232                Interpolator interpolator = scrollBarInterpolator;
25233
25234                // Start opaque
25235                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25236
25237                // End transparent
25238                nextFrame += scrollBarFadeDuration;
25239                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25240
25241                state = FADING;
25242
25243                // Kick off the fade animation
25244                host.invalidate(true);
25245            }
25246        }
25247    }
25248
25249    /**
25250     * Resuable callback for sending
25251     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25252     */
25253    private class SendViewScrolledAccessibilityEvent implements Runnable {
25254        public volatile boolean mIsPending;
25255
25256        public void run() {
25257            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25258            mIsPending = false;
25259        }
25260    }
25261
25262    /**
25263     * <p>
25264     * This class represents a delegate that can be registered in a {@link View}
25265     * to enhance accessibility support via composition rather via inheritance.
25266     * It is specifically targeted to widget developers that extend basic View
25267     * classes i.e. classes in package android.view, that would like their
25268     * applications to be backwards compatible.
25269     * </p>
25270     * <div class="special reference">
25271     * <h3>Developer Guides</h3>
25272     * <p>For more information about making applications accessible, read the
25273     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25274     * developer guide.</p>
25275     * </div>
25276     * <p>
25277     * A scenario in which a developer would like to use an accessibility delegate
25278     * is overriding a method introduced in a later API version than the minimal API
25279     * version supported by the application. For example, the method
25280     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25281     * in API version 4 when the accessibility APIs were first introduced. If a
25282     * developer would like his application to run on API version 4 devices (assuming
25283     * all other APIs used by the application are version 4 or lower) and take advantage
25284     * of this method, instead of overriding the method which would break the application's
25285     * backwards compatibility, he can override the corresponding method in this
25286     * delegate and register the delegate in the target View if the API version of
25287     * the system is high enough, i.e. the API version is the same as or higher than the API
25288     * version that introduced
25289     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25290     * </p>
25291     * <p>
25292     * Here is an example implementation:
25293     * </p>
25294     * <code><pre><p>
25295     * if (Build.VERSION.SDK_INT >= 14) {
25296     *     // If the API version is equal of higher than the version in
25297     *     // which onInitializeAccessibilityNodeInfo was introduced we
25298     *     // register a delegate with a customized implementation.
25299     *     View view = findViewById(R.id.view_id);
25300     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25301     *         public void onInitializeAccessibilityNodeInfo(View host,
25302     *                 AccessibilityNodeInfo info) {
25303     *             // Let the default implementation populate the info.
25304     *             super.onInitializeAccessibilityNodeInfo(host, info);
25305     *             // Set some other information.
25306     *             info.setEnabled(host.isEnabled());
25307     *         }
25308     *     });
25309     * }
25310     * </code></pre></p>
25311     * <p>
25312     * This delegate contains methods that correspond to the accessibility methods
25313     * in View. If a delegate has been specified the implementation in View hands
25314     * off handling to the corresponding method in this delegate. The default
25315     * implementation the delegate methods behaves exactly as the corresponding
25316     * method in View for the case of no accessibility delegate been set. Hence,
25317     * to customize the behavior of a View method, clients can override only the
25318     * corresponding delegate method without altering the behavior of the rest
25319     * accessibility related methods of the host view.
25320     * </p>
25321     * <p>
25322     * <strong>Note:</strong> On platform versions prior to
25323     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25324     * views in the {@code android.widget.*} package are called <i>before</i>
25325     * host methods. This prevents certain properties such as class name from
25326     * being modified by overriding
25327     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25328     * as any changes will be overwritten by the host class.
25329     * <p>
25330     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25331     * methods are called <i>after</i> host methods, which all properties to be
25332     * modified without being overwritten by the host class.
25333     */
25334    public static class AccessibilityDelegate {
25335
25336        /**
25337         * Sends an accessibility event of the given type. If accessibility is not
25338         * enabled this method has no effect.
25339         * <p>
25340         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25341         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25342         * been set.
25343         * </p>
25344         *
25345         * @param host The View hosting the delegate.
25346         * @param eventType The type of the event to send.
25347         *
25348         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25349         */
25350        public void sendAccessibilityEvent(View host, int eventType) {
25351            host.sendAccessibilityEventInternal(eventType);
25352        }
25353
25354        /**
25355         * Performs the specified accessibility action on the view. For
25356         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25357         * <p>
25358         * The default implementation behaves as
25359         * {@link View#performAccessibilityAction(int, Bundle)
25360         *  View#performAccessibilityAction(int, Bundle)} for the case of
25361         *  no accessibility delegate been set.
25362         * </p>
25363         *
25364         * @param action The action to perform.
25365         * @return Whether the action was performed.
25366         *
25367         * @see View#performAccessibilityAction(int, Bundle)
25368         *      View#performAccessibilityAction(int, Bundle)
25369         */
25370        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25371            return host.performAccessibilityActionInternal(action, args);
25372        }
25373
25374        /**
25375         * Sends an accessibility event. This method behaves exactly as
25376         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25377         * empty {@link AccessibilityEvent} and does not perform a check whether
25378         * accessibility is enabled.
25379         * <p>
25380         * The default implementation behaves as
25381         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25382         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25383         * the case of no accessibility delegate been set.
25384         * </p>
25385         *
25386         * @param host The View hosting the delegate.
25387         * @param event The event to send.
25388         *
25389         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25390         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25391         */
25392        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25393            host.sendAccessibilityEventUncheckedInternal(event);
25394        }
25395
25396        /**
25397         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25398         * to its children for adding their text content to the event.
25399         * <p>
25400         * The default implementation behaves as
25401         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25402         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25403         * the case of no accessibility delegate been set.
25404         * </p>
25405         *
25406         * @param host The View hosting the delegate.
25407         * @param event The event.
25408         * @return True if the event population was completed.
25409         *
25410         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25411         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25412         */
25413        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25414            return host.dispatchPopulateAccessibilityEventInternal(event);
25415        }
25416
25417        /**
25418         * Gives a chance to the host View to populate the accessibility event with its
25419         * text content.
25420         * <p>
25421         * The default implementation behaves as
25422         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25423         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25424         * the case of no accessibility delegate been set.
25425         * </p>
25426         *
25427         * @param host The View hosting the delegate.
25428         * @param event The accessibility event which to populate.
25429         *
25430         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25431         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25432         */
25433        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25434            host.onPopulateAccessibilityEventInternal(event);
25435        }
25436
25437        /**
25438         * Initializes an {@link AccessibilityEvent} with information about the
25439         * the host View which is the event source.
25440         * <p>
25441         * The default implementation behaves as
25442         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25443         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25444         * the case of no accessibility delegate been set.
25445         * </p>
25446         *
25447         * @param host The View hosting the delegate.
25448         * @param event The event to initialize.
25449         *
25450         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25451         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25452         */
25453        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25454            host.onInitializeAccessibilityEventInternal(event);
25455        }
25456
25457        /**
25458         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25459         * <p>
25460         * The default implementation behaves as
25461         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25462         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25463         * the case of no accessibility delegate been set.
25464         * </p>
25465         *
25466         * @param host The View hosting the delegate.
25467         * @param info The instance to initialize.
25468         *
25469         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25470         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25471         */
25472        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25473            host.onInitializeAccessibilityNodeInfoInternal(info);
25474        }
25475
25476        /**
25477         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25478         * additional data.
25479         * <p>
25480         * This method only needs to be implemented if the View offers to provide additional data.
25481         * </p>
25482         * <p>
25483         * The default implementation behaves as
25484         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25485         * the case where no accessibility delegate is set.
25486         * </p>
25487         *
25488         * @param host The View hosting the delegate. Never {@code null}.
25489         * @param info The info to which to add the extra data. Never {@code null}.
25490         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25491         *                     extra data should be added to the {@link Bundle} returned by
25492         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25493         *                     {@code null}.
25494         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25495         *                  May be {@code null} if the if the service provided no arguments.
25496         *
25497         * @see AccessibilityNodeInfo#setExtraAvailableData
25498         */
25499        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25500                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25501                @Nullable Bundle arguments) {
25502            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25503        }
25504
25505        /**
25506         * Called when a child of the host View has requested sending an
25507         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25508         * to augment the event.
25509         * <p>
25510         * The default implementation behaves as
25511         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25512         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25513         * the case of no accessibility delegate been set.
25514         * </p>
25515         *
25516         * @param host The View hosting the delegate.
25517         * @param child The child which requests sending the event.
25518         * @param event The event to be sent.
25519         * @return True if the event should be sent
25520         *
25521         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25522         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25523         */
25524        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25525                AccessibilityEvent event) {
25526            return host.onRequestSendAccessibilityEventInternal(child, event);
25527        }
25528
25529        /**
25530         * Gets the provider for managing a virtual view hierarchy rooted at this View
25531         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25532         * that explore the window content.
25533         * <p>
25534         * The default implementation behaves as
25535         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25536         * the case of no accessibility delegate been set.
25537         * </p>
25538         *
25539         * @return The provider.
25540         *
25541         * @see AccessibilityNodeProvider
25542         */
25543        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25544            return null;
25545        }
25546
25547        /**
25548         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25549         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25550         * This method is responsible for obtaining an accessibility node info from a
25551         * pool of reusable instances and calling
25552         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25553         * view to initialize the former.
25554         * <p>
25555         * <strong>Note:</strong> The client is responsible for recycling the obtained
25556         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25557         * creation.
25558         * </p>
25559         * <p>
25560         * The default implementation behaves as
25561         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25562         * the case of no accessibility delegate been set.
25563         * </p>
25564         * @return A populated {@link AccessibilityNodeInfo}.
25565         *
25566         * @see AccessibilityNodeInfo
25567         *
25568         * @hide
25569         */
25570        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25571            return host.createAccessibilityNodeInfoInternal();
25572        }
25573    }
25574
25575    private static class MatchIdPredicate implements Predicate<View> {
25576        public int mId;
25577
25578        @Override
25579        public boolean test(View view) {
25580            return (view.mID == mId);
25581        }
25582    }
25583
25584    private static class MatchLabelForPredicate implements Predicate<View> {
25585        private int mLabeledId;
25586
25587        @Override
25588        public boolean test(View view) {
25589            return (view.mLabelForId == mLabeledId);
25590        }
25591    }
25592
25593    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25594        private int mChangeTypes = 0;
25595        private boolean mPosted;
25596        private boolean mPostedWithDelay;
25597        private long mLastEventTimeMillis;
25598
25599        @Override
25600        public void run() {
25601            mPosted = false;
25602            mPostedWithDelay = false;
25603            mLastEventTimeMillis = SystemClock.uptimeMillis();
25604            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25605                final AccessibilityEvent event = AccessibilityEvent.obtain();
25606                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25607                event.setContentChangeTypes(mChangeTypes);
25608                sendAccessibilityEventUnchecked(event);
25609            }
25610            mChangeTypes = 0;
25611        }
25612
25613        public void runOrPost(int changeType) {
25614            mChangeTypes |= changeType;
25615
25616            // If this is a live region or the child of a live region, collect
25617            // all events from this frame and send them on the next frame.
25618            if (inLiveRegion()) {
25619                // If we're already posted with a delay, remove that.
25620                if (mPostedWithDelay) {
25621                    removeCallbacks(this);
25622                    mPostedWithDelay = false;
25623                }
25624                // Only post if we're not already posted.
25625                if (!mPosted) {
25626                    post(this);
25627                    mPosted = true;
25628                }
25629                return;
25630            }
25631
25632            if (mPosted) {
25633                return;
25634            }
25635
25636            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25637            final long minEventIntevalMillis =
25638                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25639            if (timeSinceLastMillis >= minEventIntevalMillis) {
25640                removeCallbacks(this);
25641                run();
25642            } else {
25643                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25644                mPostedWithDelay = true;
25645            }
25646        }
25647    }
25648
25649    private boolean inLiveRegion() {
25650        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25651            return true;
25652        }
25653
25654        ViewParent parent = getParent();
25655        while (parent instanceof View) {
25656            if (((View) parent).getAccessibilityLiveRegion()
25657                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25658                return true;
25659            }
25660            parent = parent.getParent();
25661        }
25662
25663        return false;
25664    }
25665
25666    /**
25667     * Dump all private flags in readable format, useful for documentation and
25668     * sanity checking.
25669     */
25670    private static void dumpFlags() {
25671        final HashMap<String, String> found = Maps.newHashMap();
25672        try {
25673            for (Field field : View.class.getDeclaredFields()) {
25674                final int modifiers = field.getModifiers();
25675                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25676                    if (field.getType().equals(int.class)) {
25677                        final int value = field.getInt(null);
25678                        dumpFlag(found, field.getName(), value);
25679                    } else if (field.getType().equals(int[].class)) {
25680                        final int[] values = (int[]) field.get(null);
25681                        for (int i = 0; i < values.length; i++) {
25682                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25683                        }
25684                    }
25685                }
25686            }
25687        } catch (IllegalAccessException e) {
25688            throw new RuntimeException(e);
25689        }
25690
25691        final ArrayList<String> keys = Lists.newArrayList();
25692        keys.addAll(found.keySet());
25693        Collections.sort(keys);
25694        for (String key : keys) {
25695            Log.d(VIEW_LOG_TAG, found.get(key));
25696        }
25697    }
25698
25699    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25700        // Sort flags by prefix, then by bits, always keeping unique keys
25701        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25702        final int prefix = name.indexOf('_');
25703        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25704        final String output = bits + " " + name;
25705        found.put(key, output);
25706    }
25707
25708    /** {@hide} */
25709    public void encode(@NonNull ViewHierarchyEncoder stream) {
25710        stream.beginObject(this);
25711        encodeProperties(stream);
25712        stream.endObject();
25713    }
25714
25715    /** {@hide} */
25716    @CallSuper
25717    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25718        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25719        if (resolveId instanceof String) {
25720            stream.addProperty("id", (String) resolveId);
25721        } else {
25722            stream.addProperty("id", mID);
25723        }
25724
25725        stream.addProperty("misc:transformation.alpha",
25726                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25727        stream.addProperty("misc:transitionName", getTransitionName());
25728
25729        // layout
25730        stream.addProperty("layout:left", mLeft);
25731        stream.addProperty("layout:right", mRight);
25732        stream.addProperty("layout:top", mTop);
25733        stream.addProperty("layout:bottom", mBottom);
25734        stream.addProperty("layout:width", getWidth());
25735        stream.addProperty("layout:height", getHeight());
25736        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25737        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25738        stream.addProperty("layout:hasTransientState", hasTransientState());
25739        stream.addProperty("layout:baseline", getBaseline());
25740
25741        // layout params
25742        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25743        if (layoutParams != null) {
25744            stream.addPropertyKey("layoutParams");
25745            layoutParams.encode(stream);
25746        }
25747
25748        // scrolling
25749        stream.addProperty("scrolling:scrollX", mScrollX);
25750        stream.addProperty("scrolling:scrollY", mScrollY);
25751
25752        // padding
25753        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25754        stream.addProperty("padding:paddingRight", mPaddingRight);
25755        stream.addProperty("padding:paddingTop", mPaddingTop);
25756        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25757        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25758        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25759        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25760        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25761        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25762
25763        // measurement
25764        stream.addProperty("measurement:minHeight", mMinHeight);
25765        stream.addProperty("measurement:minWidth", mMinWidth);
25766        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25767        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25768
25769        // drawing
25770        stream.addProperty("drawing:elevation", getElevation());
25771        stream.addProperty("drawing:translationX", getTranslationX());
25772        stream.addProperty("drawing:translationY", getTranslationY());
25773        stream.addProperty("drawing:translationZ", getTranslationZ());
25774        stream.addProperty("drawing:rotation", getRotation());
25775        stream.addProperty("drawing:rotationX", getRotationX());
25776        stream.addProperty("drawing:rotationY", getRotationY());
25777        stream.addProperty("drawing:scaleX", getScaleX());
25778        stream.addProperty("drawing:scaleY", getScaleY());
25779        stream.addProperty("drawing:pivotX", getPivotX());
25780        stream.addProperty("drawing:pivotY", getPivotY());
25781        stream.addProperty("drawing:opaque", isOpaque());
25782        stream.addProperty("drawing:alpha", getAlpha());
25783        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25784        stream.addProperty("drawing:shadow", hasShadow());
25785        stream.addProperty("drawing:solidColor", getSolidColor());
25786        stream.addProperty("drawing:layerType", mLayerType);
25787        stream.addProperty("drawing:willNotDraw", willNotDraw());
25788        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25789        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25790        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25791        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25792
25793        // focus
25794        stream.addProperty("focus:hasFocus", hasFocus());
25795        stream.addProperty("focus:isFocused", isFocused());
25796        stream.addProperty("focus:focusable", getFocusable());
25797        stream.addProperty("focus:isFocusable", isFocusable());
25798        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25799
25800        stream.addProperty("misc:clickable", isClickable());
25801        stream.addProperty("misc:pressed", isPressed());
25802        stream.addProperty("misc:selected", isSelected());
25803        stream.addProperty("misc:touchMode", isInTouchMode());
25804        stream.addProperty("misc:hovered", isHovered());
25805        stream.addProperty("misc:activated", isActivated());
25806
25807        stream.addProperty("misc:visibility", getVisibility());
25808        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25809        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25810
25811        stream.addProperty("misc:enabled", isEnabled());
25812        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25813        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25814
25815        // theme attributes
25816        Resources.Theme theme = getContext().getTheme();
25817        if (theme != null) {
25818            stream.addPropertyKey("theme");
25819            theme.encode(stream);
25820        }
25821
25822        // view attribute information
25823        int n = mAttributes != null ? mAttributes.length : 0;
25824        stream.addProperty("meta:__attrCount__", n/2);
25825        for (int i = 0; i < n; i += 2) {
25826            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25827        }
25828
25829        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25830
25831        // text
25832        stream.addProperty("text:textDirection", getTextDirection());
25833        stream.addProperty("text:textAlignment", getTextAlignment());
25834
25835        // accessibility
25836        CharSequence contentDescription = getContentDescription();
25837        stream.addProperty("accessibility:contentDescription",
25838                contentDescription == null ? "" : contentDescription.toString());
25839        stream.addProperty("accessibility:labelFor", getLabelFor());
25840        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25841    }
25842
25843    /**
25844     * Determine if this view is rendered on a round wearable device and is the main view
25845     * on the screen.
25846     */
25847    boolean shouldDrawRoundScrollbar() {
25848        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25849            return false;
25850        }
25851
25852        final View rootView = getRootView();
25853        final WindowInsets insets = getRootWindowInsets();
25854
25855        int height = getHeight();
25856        int width = getWidth();
25857        int displayHeight = rootView.getHeight();
25858        int displayWidth = rootView.getWidth();
25859
25860        if (height != displayHeight || width != displayWidth) {
25861            return false;
25862        }
25863
25864        getLocationInWindow(mAttachInfo.mTmpLocation);
25865        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25866                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25867    }
25868
25869    /**
25870     * Sets the tooltip text which will be displayed in a small popup next to the view.
25871     * <p>
25872     * The tooltip will be displayed:
25873     * <ul>
25874     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
25875     * menu). </li>
25876     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25877     * </ul>
25878     * <p>
25879     * <strong>Note:</strong> Do not override this method, as it will have no
25880     * effect on the text displayed in the tooltip.
25881     *
25882     * @param tooltipText the tooltip text, or null if no tooltip is required
25883     * @see #getTooltipText()
25884     * @attr ref android.R.styleable#View_tooltipText
25885     */
25886    public void setTooltipText(@Nullable CharSequence tooltipText) {
25887        if (TextUtils.isEmpty(tooltipText)) {
25888            setFlags(0, TOOLTIP);
25889            hideTooltip();
25890            mTooltipInfo = null;
25891        } else {
25892            setFlags(TOOLTIP, TOOLTIP);
25893            if (mTooltipInfo == null) {
25894                mTooltipInfo = new TooltipInfo();
25895                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25896                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25897            }
25898            mTooltipInfo.mTooltipText = tooltipText;
25899            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25900                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25901            }
25902        }
25903    }
25904
25905    /**
25906     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25907     */
25908    public void setTooltip(@Nullable CharSequence tooltipText) {
25909        setTooltipText(tooltipText);
25910    }
25911
25912    /**
25913     * Returns the view's tooltip text.
25914     *
25915     * <strong>Note:</strong> Do not override this method, as it will have no
25916     * effect on the text displayed in the tooltip. You must call
25917     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25918     *
25919     * @return the tooltip text
25920     * @see #setTooltipText(CharSequence)
25921     * @attr ref android.R.styleable#View_tooltipText
25922     */
25923    @Nullable
25924    public CharSequence getTooltipText() {
25925        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25926    }
25927
25928    /**
25929     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25930     */
25931    @Nullable
25932    public CharSequence getTooltip() {
25933        return getTooltipText();
25934    }
25935
25936    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25937        if (mAttachInfo == null || mTooltipInfo == null) {
25938            return false;
25939        }
25940        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25941            return false;
25942        }
25943        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25944            return false;
25945        }
25946        hideTooltip();
25947        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25948        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25949        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25950        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25951        mAttachInfo.mTooltipHost = this;
25952        return true;
25953    }
25954
25955    void hideTooltip() {
25956        if (mTooltipInfo == null) {
25957            return;
25958        }
25959        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25960        if (mTooltipInfo.mTooltipPopup == null) {
25961            return;
25962        }
25963        mTooltipInfo.mTooltipPopup.hide();
25964        mTooltipInfo.mTooltipPopup = null;
25965        mTooltipInfo.mTooltipFromLongClick = false;
25966        if (mAttachInfo != null) {
25967            mAttachInfo.mTooltipHost = null;
25968        }
25969    }
25970
25971    private boolean showLongClickTooltip(int x, int y) {
25972        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25973        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25974        return showTooltip(x, y, true);
25975    }
25976
25977    private void showHoverTooltip() {
25978        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25979    }
25980
25981    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25982        if (mTooltipInfo == null) {
25983            return false;
25984        }
25985        switch(event.getAction()) {
25986            case MotionEvent.ACTION_HOVER_MOVE:
25987                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25988                    break;
25989                }
25990                if (!mTooltipInfo.mTooltipFromLongClick) {
25991                    if (mTooltipInfo.mTooltipPopup == null) {
25992                        // Schedule showing the tooltip after a timeout.
25993                        mTooltipInfo.mAnchorX = (int) event.getX();
25994                        mTooltipInfo.mAnchorY = (int) event.getY();
25995                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25996                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25997                                ViewConfiguration.getHoverTooltipShowTimeout());
25998                    }
25999
26000                    // Hide hover-triggered tooltip after a period of inactivity.
26001                    // Match the timeout used by NativeInputManager to hide the mouse pointer
26002                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26003                    final int timeout;
26004                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26005                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
26006                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26007                    } else {
26008                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26009                    }
26010                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26011                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26012                }
26013                return true;
26014
26015            case MotionEvent.ACTION_HOVER_EXIT:
26016                if (!mTooltipInfo.mTooltipFromLongClick) {
26017                    hideTooltip();
26018                }
26019                break;
26020        }
26021        return false;
26022    }
26023
26024    void handleTooltipKey(KeyEvent event) {
26025        switch (event.getAction()) {
26026            case KeyEvent.ACTION_DOWN:
26027                if (event.getRepeatCount() == 0) {
26028                    hideTooltip();
26029                }
26030                break;
26031
26032            case KeyEvent.ACTION_UP:
26033                handleTooltipUp();
26034                break;
26035        }
26036    }
26037
26038    private void handleTooltipUp() {
26039        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26040            return;
26041        }
26042        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26043        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26044                ViewConfiguration.getLongPressTooltipHideTimeout());
26045    }
26046
26047    private int getFocusableAttribute(TypedArray attributes) {
26048        TypedValue val = new TypedValue();
26049        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26050            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26051                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26052            } else {
26053                return val.data;
26054            }
26055        } else {
26056            return FOCUSABLE_AUTO;
26057        }
26058    }
26059
26060    /**
26061     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26062     * is not showing.
26063     * @hide
26064     */
26065    @TestApi
26066    public View getTooltipView() {
26067        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26068            return null;
26069        }
26070        return mTooltipInfo.mTooltipPopup.getContentView();
26071    }
26072}
26073