View.java revision 85d1c2d2905362b984563d9b5e8332010c272fc5
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        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7385        if (provider != null) {
7386            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7387            structure.setChildCount(1);
7388            ViewStructure root = structure.newChild(0);
7389            populateVirtualStructure(root, provider, info);
7390            info.recycle();
7391        }
7392    }
7393
7394    /**
7395     * Called when assist structure is being retrieved from a view as part of an autofill request
7396     * to generate additional virtual structure under this view.
7397     *
7398     * <p>When implementing this method, subclasses must follow the rules below:
7399     *
7400     * <ol>
7401     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7402     * children.
7403     * <li>Call
7404     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7405     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7406     * when the focus inside the view changed.
7407     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7408     * AutofillValue)} when the value of a child changed.
7409     * <li>Call {@link AutofillManager#commit()} when the autofill context
7410     * of the view structure changed and you want the current autofill interaction if such
7411     * to be commited.
7412     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7413     * of the view structure changed and you want the current autofill interaction if such
7414     * to be cancelled.
7415     * </ol>
7416     *
7417     * @param structure Fill in with structured view data.
7418     * @param flags optional flags (currently {@code 0}).
7419     */
7420    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7421        // TODO(b/36171235): need a way to let apps set the ViewStructure without forcing them
7422        // to call super() (in case they override both this method and dispatchProvide....
7423        // Perhaps the best solution would simply make setAutofillId(ViewStructure) public.
7424        setAutofillId(structure);
7425    }
7426
7427    /**
7428     * Automatically fills the content of this view with the {@code value}.
7429     *
7430     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7431     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7432     * to support the Autofill Framework.
7433     *
7434     * <p>Typically, it is implemented by:
7435     *
7436     * <ol>
7437     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7438     * <li>Passing the actual value to the equivalent setter in the view.
7439     * </ol>
7440     *
7441     * <p>For example, a text-field view would call:
7442     * <pre class="prettyprint">
7443     * CharSequence text = value.getTextValue();
7444     * if (text != null) {
7445     *     setText(text);
7446     * }
7447     * </pre>
7448     *
7449     * <p>If the value is updated asyncronously the next call to
7450     * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
7451     * changed to the autofilled value. If not, the view will not be considered autofilled.
7452     *
7453     * @param value value to be autofilled.
7454     */
7455    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7456    }
7457
7458    /**
7459     * Automatically fills the content of a virtual views.
7460     *
7461     * <p>See {@link #autofill(AutofillValue)} and
7462     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7463     * <p>To indicate that a virtual view was autofilled
7464     * <code>@android:drawable/autofilled_highlight</code> should be drawn over it until the data
7465     * changes.
7466     *
7467     * @param values map of values to be autofilled, keyed by virtual child id.
7468     */
7469    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7470    }
7471
7472    /**
7473     * Describes the autofill type that should be used on calls to
7474     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7475     *
7476     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7477     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7478     */
7479    public @AutofillType int getAutofillType() {
7480        return AUTOFILL_TYPE_NONE;
7481    }
7482
7483    /**
7484     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7485     *
7486     * @return The hints set via the attribute or {@code null} if no hint it set.
7487     *
7488     * @attr ref android.R.styleable#View_autofillHints
7489     */
7490    @ViewDebug.ExportedProperty()
7491    @Nullable public String[] getAutofillHints() {
7492        return mAutofillHints;
7493    }
7494
7495    /**
7496     * @hide
7497     */
7498    public boolean isAutofilled() {
7499        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7500    }
7501
7502    /**
7503     * Gets the {@link View}'s current autofill value.
7504     *
7505     * <p>By default returns {@code null}, but views should override it (and
7506     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7507     * Framework.
7508     */
7509    @Nullable
7510    public AutofillValue getAutofillValue() {
7511        return null;
7512    }
7513
7514    /**
7515     * Gets the mode for determining whether this View is important for autofill.
7516     *
7517     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7518     *
7519     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7520     * {@link #setImportantForAutofill(int)}.
7521     *
7522     * @attr ref android.R.styleable#View_importantForAutofill
7523     */
7524    @ViewDebug.ExportedProperty(mapping = {
7525            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7526            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7527            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7528            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7529                to = "yesExcludeDescendants"),
7530            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7531                to = "noExcludeDescendants")})
7532    public @AutofillImportance int getImportantForAutofill() {
7533        return (mPrivateFlags3
7534                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7535    }
7536
7537    /**
7538     * Sets the mode for determining whether this View is important for autofill.
7539     *
7540     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7541     *
7542     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7543     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7544     * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7545     *
7546     * @attr ref android.R.styleable#View_importantForAutofill
7547     */
7548    public void setImportantForAutofill(@AutofillImportance int mode) {
7549        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7550        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7551                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7552    }
7553
7554    /**
7555     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7556     * associated with this View should be included in a {@link ViewStructure} used for
7557     * autofill purposes.
7558     *
7559     * <p>Generally speaking, a view is important for autofill if:
7560     * <ol>
7561     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7562     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7563     * autofill other views.
7564     * <ol>
7565     *
7566     * <p>For example, view containers should typically return {@code false} for performance reasons
7567     * (since the important info is provided by their children), but if the container is actually
7568     * whose children are part of a compound view, it should return {@code true} (and then override
7569     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7570     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7571     * the structure). On the other hand, views representing labels or editable fields should
7572     * typically return {@code true}, but in some cases they could return {@code false} (for
7573     * example, if they're part of a "Captcha" mechanism).
7574     *
7575     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7576     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7577     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7578     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7579     * should use {@link #setImportantForAutofill(int)} instead.
7580     *
7581     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7582     * excluded from the structure; for example, if the user explicitly requested autofill, the
7583     * View might be always included.
7584     *
7585     * <p>This decision applies just for the view, not its children - if the view children are not
7586     * important for autofill, the view should override
7587     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7588     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7589     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7590     *
7591     * @return whether the view is considered important for autofill.
7592     *
7593     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7594     * @see #IMPORTANT_FOR_AUTOFILL_YES
7595     * @see #IMPORTANT_FOR_AUTOFILL_NO
7596     */
7597    public final boolean isImportantForAutofill() {
7598        final int flag = getImportantForAutofill();
7599
7600        // First, check if view explicity set it to YES or NO
7601        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
7602            return true;
7603        }
7604        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
7605            return false;
7606        }
7607
7608        // Then use some heuristics to handle AUTO.
7609
7610        // Always include views that have a explicity resource id.
7611        final int id = mID;
7612        if (id != NO_ID && !isViewIdGenerated(id)) {
7613            final Resources res = getResources();
7614            String entry = null;
7615            String pkg = null;
7616            try {
7617                entry = res.getResourceEntryName(id);
7618                pkg = res.getResourcePackageName(id);
7619            } catch (Resources.NotFoundException e) {
7620                // ignore
7621            }
7622            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7623                return true;
7624            }
7625        }
7626
7627        // Otherwise, assume it's not important...
7628        return false;
7629    }
7630
7631    @Nullable
7632    private AutofillManager getAutofillManager() {
7633        return mContext.getSystemService(AutofillManager.class);
7634    }
7635
7636    private boolean isAutofillable() {
7637        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
7638    }
7639
7640    private void populateVirtualStructure(ViewStructure structure,
7641            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
7642        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7643                null, null, null);
7644        Rect rect = structure.getTempRect();
7645        info.getBoundsInParent(rect);
7646        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7647        structure.setVisibility(VISIBLE);
7648        structure.setEnabled(info.isEnabled());
7649        if (info.isClickable()) {
7650            structure.setClickable(true);
7651        }
7652        if (info.isFocusable()) {
7653            structure.setFocusable(true);
7654        }
7655        if (info.isFocused()) {
7656            structure.setFocused(true);
7657        }
7658        if (info.isAccessibilityFocused()) {
7659            structure.setAccessibilityFocused(true);
7660        }
7661        if (info.isSelected()) {
7662            structure.setSelected(true);
7663        }
7664        if (info.isLongClickable()) {
7665            structure.setLongClickable(true);
7666        }
7667        if (info.isCheckable()) {
7668            structure.setCheckable(true);
7669            if (info.isChecked()) {
7670                structure.setChecked(true);
7671            }
7672        }
7673        if (info.isContextClickable()) {
7674            structure.setContextClickable(true);
7675        }
7676        CharSequence cname = info.getClassName();
7677        structure.setClassName(cname != null ? cname.toString() : null);
7678        structure.setContentDescription(info.getContentDescription());
7679        if ((info.getText() != null || info.getError() != null)) {
7680            structure.setText(info.getText(), info.getTextSelectionStart(),
7681                    info.getTextSelectionEnd());
7682        }
7683        final int NCHILDREN = info.getChildCount();
7684        if (NCHILDREN > 0) {
7685            structure.setChildCount(NCHILDREN);
7686            for (int i=0; i<NCHILDREN; i++) {
7687                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7688                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7689                ViewStructure child = structure.newChild(i);
7690                populateVirtualStructure(child, provider, cinfo);
7691                cinfo.recycle();
7692            }
7693        }
7694    }
7695
7696    /**
7697     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7698     * implementation calls {@link #onProvideStructure} and
7699     * {@link #onProvideVirtualStructure}.
7700     */
7701    public void dispatchProvideStructure(ViewStructure structure) {
7702        dispatchProvideStructureForAssistOrAutofill(structure, false);
7703    }
7704
7705    /**
7706     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7707     *
7708     * <p>The structure must be filled according to the request type, which is set in the
7709     * {@code flags} parameter - see the documentation on each flag for more details.
7710     *
7711     * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
7712     * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7713     *
7714     * @param structure Fill in with structured view data.
7715     * @param flags optional flags (currently {@code 0}).
7716     */
7717    public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
7718        dispatchProvideStructureForAssistOrAutofill(structure, true);
7719    }
7720
7721    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7722            boolean forAutofill) {
7723        boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
7724        if (!blocked) {
7725            if (forAutofill) {
7726                setAutofillId(structure);
7727                // NOTE: flags are not currently supported, hence 0
7728                onProvideAutofillStructure(structure, 0);
7729                onProvideAutofillVirtualStructure(structure, 0);
7730            } else {
7731                onProvideStructure(structure);
7732                onProvideVirtualStructure(structure);
7733            }
7734        } else {
7735            structure.setClassName(getAccessibilityClassName().toString());
7736            structure.setAssistBlocked(true);
7737        }
7738    }
7739
7740    /**
7741     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7742     *
7743     * Note: Called from the default {@link AccessibilityDelegate}.
7744     *
7745     * @hide
7746     */
7747    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7748        if (mAttachInfo == null) {
7749            return;
7750        }
7751
7752        Rect bounds = mAttachInfo.mTmpInvalRect;
7753
7754        getDrawingRect(bounds);
7755        info.setBoundsInParent(bounds);
7756
7757        getBoundsOnScreen(bounds, true);
7758        info.setBoundsInScreen(bounds);
7759
7760        ViewParent parent = getParentForAccessibility();
7761        if (parent instanceof View) {
7762            info.setParent((View) parent);
7763        }
7764
7765        if (mID != View.NO_ID) {
7766            View rootView = getRootView();
7767            if (rootView == null) {
7768                rootView = this;
7769            }
7770
7771            View label = rootView.findLabelForView(this, mID);
7772            if (label != null) {
7773                info.setLabeledBy(label);
7774            }
7775
7776            if ((mAttachInfo.mAccessibilityFetchFlags
7777                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7778                    && Resources.resourceHasPackage(mID)) {
7779                try {
7780                    String viewId = getResources().getResourceName(mID);
7781                    info.setViewIdResourceName(viewId);
7782                } catch (Resources.NotFoundException nfe) {
7783                    /* ignore */
7784                }
7785            }
7786        }
7787
7788        if (mLabelForId != View.NO_ID) {
7789            View rootView = getRootView();
7790            if (rootView == null) {
7791                rootView = this;
7792            }
7793            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7794            if (labeled != null) {
7795                info.setLabelFor(labeled);
7796            }
7797        }
7798
7799        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7800            View rootView = getRootView();
7801            if (rootView == null) {
7802                rootView = this;
7803            }
7804            View next = rootView.findViewInsideOutShouldExist(this,
7805                    mAccessibilityTraversalBeforeId);
7806            if (next != null && next.includeForAccessibility()) {
7807                info.setTraversalBefore(next);
7808            }
7809        }
7810
7811        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7812            View rootView = getRootView();
7813            if (rootView == null) {
7814                rootView = this;
7815            }
7816            View next = rootView.findViewInsideOutShouldExist(this,
7817                    mAccessibilityTraversalAfterId);
7818            if (next != null && next.includeForAccessibility()) {
7819                info.setTraversalAfter(next);
7820            }
7821        }
7822
7823        info.setVisibleToUser(isVisibleToUser());
7824
7825        info.setImportantForAccessibility(isImportantForAccessibility());
7826        info.setPackageName(mContext.getPackageName());
7827        info.setClassName(getAccessibilityClassName());
7828        info.setContentDescription(getContentDescription());
7829
7830        info.setEnabled(isEnabled());
7831        info.setClickable(isClickable());
7832        info.setFocusable(isFocusable());
7833        info.setFocused(isFocused());
7834        info.setAccessibilityFocused(isAccessibilityFocused());
7835        info.setSelected(isSelected());
7836        info.setLongClickable(isLongClickable());
7837        info.setContextClickable(isContextClickable());
7838        info.setLiveRegion(getAccessibilityLiveRegion());
7839
7840        // TODO: These make sense only if we are in an AdapterView but all
7841        // views can be selected. Maybe from accessibility perspective
7842        // we should report as selectable view in an AdapterView.
7843        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7844        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7845
7846        if (isFocusable()) {
7847            if (isFocused()) {
7848                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7849            } else {
7850                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7851            }
7852        }
7853
7854        if (!isAccessibilityFocused()) {
7855            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7856        } else {
7857            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7858        }
7859
7860        if (isClickable() && isEnabled()) {
7861            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7862        }
7863
7864        if (isLongClickable() && isEnabled()) {
7865            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7866        }
7867
7868        if (isContextClickable() && isEnabled()) {
7869            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7870        }
7871
7872        CharSequence text = getIterableTextForAccessibility();
7873        if (text != null && text.length() > 0) {
7874            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7875
7876            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7877            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7878            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7879            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7880                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7881                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7882        }
7883
7884        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7885        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7886    }
7887
7888    /**
7889     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7890     * additional data.
7891     * <p>
7892     * This method only needs overloading if the node is marked as having extra data available.
7893     * </p>
7894     *
7895     * @param info The info to which to add the extra data. Never {@code null}.
7896     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7897     *                     extra data should be added to the {@link Bundle} returned by
7898     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7899     *                     {@code null}.
7900     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7901     *                  {@code null} if the service provided no arguments.
7902     *
7903     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
7904     */
7905    public void addExtraDataToAccessibilityNodeInfo(
7906            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7907            @Nullable Bundle arguments) {
7908    }
7909
7910    /**
7911     * Determine the order in which this view will be drawn relative to its siblings for a11y
7912     *
7913     * @param info The info whose drawing order should be populated
7914     */
7915    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7916        /*
7917         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7918         * drawing order may not be well-defined, and some Views with custom drawing order may
7919         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7920         */
7921        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7922            info.setDrawingOrder(0);
7923            return;
7924        }
7925        int drawingOrderInParent = 1;
7926        // Iterate up the hierarchy if parents are not important for a11y
7927        View viewAtDrawingLevel = this;
7928        final ViewParent parent = getParentForAccessibility();
7929        while (viewAtDrawingLevel != parent) {
7930            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7931            if (!(currentParent instanceof ViewGroup)) {
7932                // Should only happen for the Decor
7933                drawingOrderInParent = 0;
7934                break;
7935            } else {
7936                final ViewGroup parentGroup = (ViewGroup) currentParent;
7937                final int childCount = parentGroup.getChildCount();
7938                if (childCount > 1) {
7939                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7940                    if (preorderedList != null) {
7941                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7942                        for (int i = 0; i < childDrawIndex; i++) {
7943                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7944                        }
7945                    } else {
7946                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7947                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7948                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7949                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7950                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7951                        if (childDrawIndex != 0) {
7952                            for (int i = 0; i < numChildrenToIterate; i++) {
7953                                final int otherDrawIndex = (customOrder ?
7954                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7955                                if (otherDrawIndex < childDrawIndex) {
7956                                    drawingOrderInParent +=
7957                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7958                                }
7959                            }
7960                        }
7961                    }
7962                }
7963            }
7964            viewAtDrawingLevel = (View) currentParent;
7965        }
7966        info.setDrawingOrder(drawingOrderInParent);
7967    }
7968
7969    private static int numViewsForAccessibility(View view) {
7970        if (view != null) {
7971            if (view.includeForAccessibility()) {
7972                return 1;
7973            } else if (view instanceof ViewGroup) {
7974                return ((ViewGroup) view).getNumChildrenForAccessibility();
7975            }
7976        }
7977        return 0;
7978    }
7979
7980    private View findLabelForView(View view, int labeledId) {
7981        if (mMatchLabelForPredicate == null) {
7982            mMatchLabelForPredicate = new MatchLabelForPredicate();
7983        }
7984        mMatchLabelForPredicate.mLabeledId = labeledId;
7985        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7986    }
7987
7988    /**
7989     * Computes whether this view is visible to the user. Such a view is
7990     * attached, visible, all its predecessors are visible, it is not clipped
7991     * entirely by its predecessors, and has an alpha greater than zero.
7992     *
7993     * @return Whether the view is visible on the screen.
7994     *
7995     * @hide
7996     */
7997    protected boolean isVisibleToUser() {
7998        return isVisibleToUser(null);
7999    }
8000
8001    /**
8002     * Computes whether the given portion of this view is visible to the user.
8003     * Such a view is attached, visible, all its predecessors are visible,
8004     * has an alpha greater than zero, and the specified portion is not
8005     * clipped entirely by its predecessors.
8006     *
8007     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8008     *                    <code>null</code>, and the entire view will be tested in this case.
8009     *                    When <code>true</code> is returned by the function, the actual visible
8010     *                    region will be stored in this parameter; that is, if boundInView is fully
8011     *                    contained within the view, no modification will be made, otherwise regions
8012     *                    outside of the visible area of the view will be clipped.
8013     *
8014     * @return Whether the specified portion of the view is visible on the screen.
8015     *
8016     * @hide
8017     */
8018    protected boolean isVisibleToUser(Rect boundInView) {
8019        if (mAttachInfo != null) {
8020            // Attached to invisible window means this view is not visible.
8021            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8022                return false;
8023            }
8024            // An invisible predecessor or one with alpha zero means
8025            // that this view is not visible to the user.
8026            Object current = this;
8027            while (current instanceof View) {
8028                View view = (View) current;
8029                // We have attach info so this view is attached and there is no
8030                // need to check whether we reach to ViewRootImpl on the way up.
8031                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8032                        view.getVisibility() != VISIBLE) {
8033                    return false;
8034                }
8035                current = view.mParent;
8036            }
8037            // Check if the view is entirely covered by its predecessors.
8038            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8039            Point offset = mAttachInfo.mPoint;
8040            if (!getGlobalVisibleRect(visibleRect, offset)) {
8041                return false;
8042            }
8043            // Check if the visible portion intersects the rectangle of interest.
8044            if (boundInView != null) {
8045                visibleRect.offset(-offset.x, -offset.y);
8046                return boundInView.intersect(visibleRect);
8047            }
8048            return true;
8049        }
8050        return false;
8051    }
8052
8053    /**
8054     * Returns the delegate for implementing accessibility support via
8055     * composition. For more details see {@link AccessibilityDelegate}.
8056     *
8057     * @return The delegate, or null if none set.
8058     *
8059     * @hide
8060     */
8061    public AccessibilityDelegate getAccessibilityDelegate() {
8062        return mAccessibilityDelegate;
8063    }
8064
8065    /**
8066     * Sets a delegate for implementing accessibility support via composition
8067     * (as opposed to inheritance). For more details, see
8068     * {@link AccessibilityDelegate}.
8069     * <p>
8070     * <strong>Note:</strong> On platform versions prior to
8071     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8072     * views in the {@code android.widget.*} package are called <i>before</i>
8073     * host methods. This prevents certain properties such as class name from
8074     * being modified by overriding
8075     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8076     * as any changes will be overwritten by the host class.
8077     * <p>
8078     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8079     * methods are called <i>after</i> host methods, which all properties to be
8080     * modified without being overwritten by the host class.
8081     *
8082     * @param delegate the object to which accessibility method calls should be
8083     *                 delegated
8084     * @see AccessibilityDelegate
8085     */
8086    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8087        mAccessibilityDelegate = delegate;
8088    }
8089
8090    /**
8091     * Gets the provider for managing a virtual view hierarchy rooted at this View
8092     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8093     * that explore the window content.
8094     * <p>
8095     * If this method returns an instance, this instance is responsible for managing
8096     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8097     * View including the one representing the View itself. Similarly the returned
8098     * instance is responsible for performing accessibility actions on any virtual
8099     * view or the root view itself.
8100     * </p>
8101     * <p>
8102     * If an {@link AccessibilityDelegate} has been specified via calling
8103     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8104     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8105     * is responsible for handling this call.
8106     * </p>
8107     *
8108     * @return The provider.
8109     *
8110     * @see AccessibilityNodeProvider
8111     */
8112    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8113        if (mAccessibilityDelegate != null) {
8114            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8115        } else {
8116            return null;
8117        }
8118    }
8119
8120    /**
8121     * Gets the unique identifier of this view on the screen for accessibility purposes.
8122     *
8123     * @return The view accessibility id.
8124     *
8125     * @hide
8126     */
8127    public int getAccessibilityViewId() {
8128        if (mAccessibilityViewId == NO_ID) {
8129            mAccessibilityViewId = mContext.getNextAccessibilityId();
8130        }
8131        return mAccessibilityViewId;
8132    }
8133
8134    /**
8135     * Gets the unique identifier of the window in which this View reseides.
8136     *
8137     * @return The window accessibility id.
8138     *
8139     * @hide
8140     */
8141    public int getAccessibilityWindowId() {
8142        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8143                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8144    }
8145
8146    /**
8147     * Returns the {@link View}'s content description.
8148     * <p>
8149     * <strong>Note:</strong> Do not override this method, as it will have no
8150     * effect on the content description presented to accessibility services.
8151     * You must call {@link #setContentDescription(CharSequence)} to modify the
8152     * content description.
8153     *
8154     * @return the content description
8155     * @see #setContentDescription(CharSequence)
8156     * @attr ref android.R.styleable#View_contentDescription
8157     */
8158    @ViewDebug.ExportedProperty(category = "accessibility")
8159    public CharSequence getContentDescription() {
8160        return mContentDescription;
8161    }
8162
8163    /**
8164     * Sets the {@link View}'s content description.
8165     * <p>
8166     * A content description briefly describes the view and is primarily used
8167     * for accessibility support to determine how a view should be presented to
8168     * the user. In the case of a view with no textual representation, such as
8169     * {@link android.widget.ImageButton}, a useful content description
8170     * explains what the view does. For example, an image button with a phone
8171     * icon that is used to place a call may use "Call" as its content
8172     * description. An image of a floppy disk that is used to save a file may
8173     * use "Save".
8174     *
8175     * @param contentDescription The content description.
8176     * @see #getContentDescription()
8177     * @attr ref android.R.styleable#View_contentDescription
8178     */
8179    @RemotableViewMethod
8180    public void setContentDescription(CharSequence contentDescription) {
8181        if (mContentDescription == null) {
8182            if (contentDescription == null) {
8183                return;
8184            }
8185        } else if (mContentDescription.equals(contentDescription)) {
8186            return;
8187        }
8188        mContentDescription = contentDescription;
8189        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8190        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8191            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8192            notifySubtreeAccessibilityStateChangedIfNeeded();
8193        } else {
8194            notifyViewAccessibilityStateChangedIfNeeded(
8195                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8196        }
8197    }
8198
8199    /**
8200     * Sets the id of a view before which this one is visited in accessibility traversal.
8201     * A screen-reader must visit the content of this view before the content of the one
8202     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8203     * will traverse the entire content of B before traversing the entire content of A,
8204     * regardles of what traversal strategy it is using.
8205     * <p>
8206     * Views that do not have specified before/after relationships are traversed in order
8207     * determined by the screen-reader.
8208     * </p>
8209     * <p>
8210     * Setting that this view is before a view that is not important for accessibility
8211     * or if this view is not important for accessibility will have no effect as the
8212     * screen-reader is not aware of unimportant views.
8213     * </p>
8214     *
8215     * @param beforeId The id of a view this one precedes in accessibility traversal.
8216     *
8217     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8218     *
8219     * @see #setImportantForAccessibility(int)
8220     */
8221    @RemotableViewMethod
8222    public void setAccessibilityTraversalBefore(int beforeId) {
8223        if (mAccessibilityTraversalBeforeId == beforeId) {
8224            return;
8225        }
8226        mAccessibilityTraversalBeforeId = beforeId;
8227        notifyViewAccessibilityStateChangedIfNeeded(
8228                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8229    }
8230
8231    /**
8232     * Gets the id of a view before which this one is visited in accessibility traversal.
8233     *
8234     * @return The id of a view this one precedes in accessibility traversal if
8235     *         specified, otherwise {@link #NO_ID}.
8236     *
8237     * @see #setAccessibilityTraversalBefore(int)
8238     */
8239    public int getAccessibilityTraversalBefore() {
8240        return mAccessibilityTraversalBeforeId;
8241    }
8242
8243    /**
8244     * Sets the id of a view after which this one is visited in accessibility traversal.
8245     * A screen-reader must visit the content of the other view before the content of this
8246     * one. For example, if view B is set to be after view A, then a screen-reader
8247     * will traverse the entire content of A before traversing the entire content of B,
8248     * regardles of what traversal strategy it is using.
8249     * <p>
8250     * Views that do not have specified before/after relationships are traversed in order
8251     * determined by the screen-reader.
8252     * </p>
8253     * <p>
8254     * Setting that this view is after a view that is not important for accessibility
8255     * or if this view is not important for accessibility will have no effect as the
8256     * screen-reader is not aware of unimportant views.
8257     * </p>
8258     *
8259     * @param afterId The id of a view this one succedees in accessibility traversal.
8260     *
8261     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8262     *
8263     * @see #setImportantForAccessibility(int)
8264     */
8265    @RemotableViewMethod
8266    public void setAccessibilityTraversalAfter(int afterId) {
8267        if (mAccessibilityTraversalAfterId == afterId) {
8268            return;
8269        }
8270        mAccessibilityTraversalAfterId = afterId;
8271        notifyViewAccessibilityStateChangedIfNeeded(
8272                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8273    }
8274
8275    /**
8276     * Gets the id of a view after which this one is visited in accessibility traversal.
8277     *
8278     * @return The id of a view this one succeedes in accessibility traversal if
8279     *         specified, otherwise {@link #NO_ID}.
8280     *
8281     * @see #setAccessibilityTraversalAfter(int)
8282     */
8283    public int getAccessibilityTraversalAfter() {
8284        return mAccessibilityTraversalAfterId;
8285    }
8286
8287    /**
8288     * Gets the id of a view for which this view serves as a label for
8289     * accessibility purposes.
8290     *
8291     * @return The labeled view id.
8292     */
8293    @ViewDebug.ExportedProperty(category = "accessibility")
8294    public int getLabelFor() {
8295        return mLabelForId;
8296    }
8297
8298    /**
8299     * Sets the id of a view for which this view serves as a label for
8300     * accessibility purposes.
8301     *
8302     * @param id The labeled view id.
8303     */
8304    @RemotableViewMethod
8305    public void setLabelFor(@IdRes int id) {
8306        if (mLabelForId == id) {
8307            return;
8308        }
8309        mLabelForId = id;
8310        if (mLabelForId != View.NO_ID
8311                && mID == View.NO_ID) {
8312            mID = generateViewId();
8313        }
8314        notifyViewAccessibilityStateChangedIfNeeded(
8315                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8316    }
8317
8318    /**
8319     * Invoked whenever this view loses focus, either by losing window focus or by losing
8320     * focus within its window. This method can be used to clear any state tied to the
8321     * focus. For instance, if a button is held pressed with the trackball and the window
8322     * loses focus, this method can be used to cancel the press.
8323     *
8324     * Subclasses of View overriding this method should always call super.onFocusLost().
8325     *
8326     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8327     * @see #onWindowFocusChanged(boolean)
8328     *
8329     * @hide pending API council approval
8330     */
8331    @CallSuper
8332    protected void onFocusLost() {
8333        resetPressedState();
8334    }
8335
8336    private void resetPressedState() {
8337        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8338            return;
8339        }
8340
8341        if (isPressed()) {
8342            setPressed(false);
8343
8344            if (!mHasPerformedLongPress) {
8345                removeLongPressCallback();
8346            }
8347        }
8348    }
8349
8350    /**
8351     * Returns true if this view has focus
8352     *
8353     * @return True if this view has focus, false otherwise.
8354     */
8355    @ViewDebug.ExportedProperty(category = "focus")
8356    public boolean isFocused() {
8357        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8358    }
8359
8360    /**
8361     * Find the view in the hierarchy rooted at this view that currently has
8362     * focus.
8363     *
8364     * @return The view that currently has focus, or null if no focused view can
8365     *         be found.
8366     */
8367    public View findFocus() {
8368        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8369    }
8370
8371    /**
8372     * Indicates whether this view is one of the set of scrollable containers in
8373     * its window.
8374     *
8375     * @return whether this view is one of the set of scrollable containers in
8376     * its window
8377     *
8378     * @attr ref android.R.styleable#View_isScrollContainer
8379     */
8380    public boolean isScrollContainer() {
8381        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8382    }
8383
8384    /**
8385     * Change whether this view is one of the set of scrollable containers in
8386     * its window.  This will be used to determine whether the window can
8387     * resize or must pan when a soft input area is open -- scrollable
8388     * containers allow the window to use resize mode since the container
8389     * will appropriately shrink.
8390     *
8391     * @attr ref android.R.styleable#View_isScrollContainer
8392     */
8393    public void setScrollContainer(boolean isScrollContainer) {
8394        if (isScrollContainer) {
8395            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8396                mAttachInfo.mScrollContainers.add(this);
8397                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8398            }
8399            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8400        } else {
8401            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8402                mAttachInfo.mScrollContainers.remove(this);
8403            }
8404            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8405        }
8406    }
8407
8408    /**
8409     * Returns the quality of the drawing cache.
8410     *
8411     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8412     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8413     *
8414     * @see #setDrawingCacheQuality(int)
8415     * @see #setDrawingCacheEnabled(boolean)
8416     * @see #isDrawingCacheEnabled()
8417     *
8418     * @attr ref android.R.styleable#View_drawingCacheQuality
8419     */
8420    @DrawingCacheQuality
8421    public int getDrawingCacheQuality() {
8422        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8423    }
8424
8425    /**
8426     * Set the drawing cache quality of this view. This value is used only when the
8427     * drawing cache is enabled
8428     *
8429     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8430     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8431     *
8432     * @see #getDrawingCacheQuality()
8433     * @see #setDrawingCacheEnabled(boolean)
8434     * @see #isDrawingCacheEnabled()
8435     *
8436     * @attr ref android.R.styleable#View_drawingCacheQuality
8437     */
8438    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8439        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8440    }
8441
8442    /**
8443     * Returns whether the screen should remain on, corresponding to the current
8444     * value of {@link #KEEP_SCREEN_ON}.
8445     *
8446     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8447     *
8448     * @see #setKeepScreenOn(boolean)
8449     *
8450     * @attr ref android.R.styleable#View_keepScreenOn
8451     */
8452    public boolean getKeepScreenOn() {
8453        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8454    }
8455
8456    /**
8457     * Controls whether the screen should remain on, modifying the
8458     * value of {@link #KEEP_SCREEN_ON}.
8459     *
8460     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8461     *
8462     * @see #getKeepScreenOn()
8463     *
8464     * @attr ref android.R.styleable#View_keepScreenOn
8465     */
8466    public void setKeepScreenOn(boolean keepScreenOn) {
8467        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8468    }
8469
8470    /**
8471     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8472     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8473     *
8474     * @attr ref android.R.styleable#View_nextFocusLeft
8475     */
8476    public int getNextFocusLeftId() {
8477        return mNextFocusLeftId;
8478    }
8479
8480    /**
8481     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8482     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8483     * decide automatically.
8484     *
8485     * @attr ref android.R.styleable#View_nextFocusLeft
8486     */
8487    public void setNextFocusLeftId(int nextFocusLeftId) {
8488        mNextFocusLeftId = nextFocusLeftId;
8489    }
8490
8491    /**
8492     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8493     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8494     *
8495     * @attr ref android.R.styleable#View_nextFocusRight
8496     */
8497    public int getNextFocusRightId() {
8498        return mNextFocusRightId;
8499    }
8500
8501    /**
8502     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8503     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8504     * decide automatically.
8505     *
8506     * @attr ref android.R.styleable#View_nextFocusRight
8507     */
8508    public void setNextFocusRightId(int nextFocusRightId) {
8509        mNextFocusRightId = nextFocusRightId;
8510    }
8511
8512    /**
8513     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8514     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8515     *
8516     * @attr ref android.R.styleable#View_nextFocusUp
8517     */
8518    public int getNextFocusUpId() {
8519        return mNextFocusUpId;
8520    }
8521
8522    /**
8523     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8524     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8525     * decide automatically.
8526     *
8527     * @attr ref android.R.styleable#View_nextFocusUp
8528     */
8529    public void setNextFocusUpId(int nextFocusUpId) {
8530        mNextFocusUpId = nextFocusUpId;
8531    }
8532
8533    /**
8534     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8535     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8536     *
8537     * @attr ref android.R.styleable#View_nextFocusDown
8538     */
8539    public int getNextFocusDownId() {
8540        return mNextFocusDownId;
8541    }
8542
8543    /**
8544     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8545     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8546     * decide automatically.
8547     *
8548     * @attr ref android.R.styleable#View_nextFocusDown
8549     */
8550    public void setNextFocusDownId(int nextFocusDownId) {
8551        mNextFocusDownId = nextFocusDownId;
8552    }
8553
8554    /**
8555     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8556     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8557     *
8558     * @attr ref android.R.styleable#View_nextFocusForward
8559     */
8560    public int getNextFocusForwardId() {
8561        return mNextFocusForwardId;
8562    }
8563
8564    /**
8565     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8566     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8567     * decide automatically.
8568     *
8569     * @attr ref android.R.styleable#View_nextFocusForward
8570     */
8571    public void setNextFocusForwardId(int nextFocusForwardId) {
8572        mNextFocusForwardId = nextFocusForwardId;
8573    }
8574
8575    /**
8576     * Gets the id of the root of the next keyboard navigation cluster.
8577     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8578     * decide automatically.
8579     *
8580     * @attr ref android.R.styleable#View_nextClusterForward
8581     */
8582    public int getNextClusterForwardId() {
8583        return mNextClusterForwardId;
8584    }
8585
8586    /**
8587     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8588     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8589     * decide automatically.
8590     *
8591     * @attr ref android.R.styleable#View_nextClusterForward
8592     */
8593    public void setNextClusterForwardId(int nextClusterForwardId) {
8594        mNextClusterForwardId = nextClusterForwardId;
8595    }
8596
8597    /**
8598     * Returns the visibility of this view and all of its ancestors
8599     *
8600     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8601     */
8602    public boolean isShown() {
8603        View current = this;
8604        //noinspection ConstantConditions
8605        do {
8606            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8607                return false;
8608            }
8609            ViewParent parent = current.mParent;
8610            if (parent == null) {
8611                return false; // We are not attached to the view root
8612            }
8613            if (!(parent instanceof View)) {
8614                return true;
8615            }
8616            current = (View) parent;
8617        } while (current != null);
8618
8619        return false;
8620    }
8621
8622    /**
8623     * Called by the view hierarchy when the content insets for a window have
8624     * changed, to allow it to adjust its content to fit within those windows.
8625     * The content insets tell you the space that the status bar, input method,
8626     * and other system windows infringe on the application's window.
8627     *
8628     * <p>You do not normally need to deal with this function, since the default
8629     * window decoration given to applications takes care of applying it to the
8630     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8631     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8632     * and your content can be placed under those system elements.  You can then
8633     * use this method within your view hierarchy if you have parts of your UI
8634     * which you would like to ensure are not being covered.
8635     *
8636     * <p>The default implementation of this method simply applies the content
8637     * insets to the view's padding, consuming that content (modifying the
8638     * insets to be 0), and returning true.  This behavior is off by default, but can
8639     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8640     *
8641     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8642     * insets object is propagated down the hierarchy, so any changes made to it will
8643     * be seen by all following views (including potentially ones above in
8644     * the hierarchy since this is a depth-first traversal).  The first view
8645     * that returns true will abort the entire traversal.
8646     *
8647     * <p>The default implementation works well for a situation where it is
8648     * used with a container that covers the entire window, allowing it to
8649     * apply the appropriate insets to its content on all edges.  If you need
8650     * a more complicated layout (such as two different views fitting system
8651     * windows, one on the top of the window, and one on the bottom),
8652     * you can override the method and handle the insets however you would like.
8653     * Note that the insets provided by the framework are always relative to the
8654     * far edges of the window, not accounting for the location of the called view
8655     * within that window.  (In fact when this method is called you do not yet know
8656     * where the layout will place the view, as it is done before layout happens.)
8657     *
8658     * <p>Note: unlike many View methods, there is no dispatch phase to this
8659     * call.  If you are overriding it in a ViewGroup and want to allow the
8660     * call to continue to your children, you must be sure to call the super
8661     * implementation.
8662     *
8663     * <p>Here is a sample layout that makes use of fitting system windows
8664     * to have controls for a video view placed inside of the window decorations
8665     * that it hides and shows.  This can be used with code like the second
8666     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8667     *
8668     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8669     *
8670     * @param insets Current content insets of the window.  Prior to
8671     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8672     * the insets or else you and Android will be unhappy.
8673     *
8674     * @return {@code true} if this view applied the insets and it should not
8675     * continue propagating further down the hierarchy, {@code false} otherwise.
8676     * @see #getFitsSystemWindows()
8677     * @see #setFitsSystemWindows(boolean)
8678     * @see #setSystemUiVisibility(int)
8679     *
8680     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8681     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8682     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8683     * to implement handling their own insets.
8684     */
8685    @Deprecated
8686    protected boolean fitSystemWindows(Rect insets) {
8687        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8688            if (insets == null) {
8689                // Null insets by definition have already been consumed.
8690                // This call cannot apply insets since there are none to apply,
8691                // so return false.
8692                return false;
8693            }
8694            // If we're not in the process of dispatching the newer apply insets call,
8695            // that means we're not in the compatibility path. Dispatch into the newer
8696            // apply insets path and take things from there.
8697            try {
8698                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8699                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8700            } finally {
8701                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8702            }
8703        } else {
8704            // We're being called from the newer apply insets path.
8705            // Perform the standard fallback behavior.
8706            return fitSystemWindowsInt(insets);
8707        }
8708    }
8709
8710    private boolean fitSystemWindowsInt(Rect insets) {
8711        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8712            mUserPaddingStart = UNDEFINED_PADDING;
8713            mUserPaddingEnd = UNDEFINED_PADDING;
8714            Rect localInsets = sThreadLocal.get();
8715            if (localInsets == null) {
8716                localInsets = new Rect();
8717                sThreadLocal.set(localInsets);
8718            }
8719            boolean res = computeFitSystemWindows(insets, localInsets);
8720            mUserPaddingLeftInitial = localInsets.left;
8721            mUserPaddingRightInitial = localInsets.right;
8722            internalSetPadding(localInsets.left, localInsets.top,
8723                    localInsets.right, localInsets.bottom);
8724            return res;
8725        }
8726        return false;
8727    }
8728
8729    /**
8730     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8731     *
8732     * <p>This method should be overridden by views that wish to apply a policy different from or
8733     * in addition to the default behavior. Clients that wish to force a view subtree
8734     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8735     *
8736     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8737     * it will be called during dispatch instead of this method. The listener may optionally
8738     * call this method from its own implementation if it wishes to apply the view's default
8739     * insets policy in addition to its own.</p>
8740     *
8741     * <p>Implementations of this method should either return the insets parameter unchanged
8742     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8743     * that this view applied itself. This allows new inset types added in future platform
8744     * versions to pass through existing implementations unchanged without being erroneously
8745     * consumed.</p>
8746     *
8747     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8748     * property is set then the view will consume the system window insets and apply them
8749     * as padding for the view.</p>
8750     *
8751     * @param insets Insets to apply
8752     * @return The supplied insets with any applied insets consumed
8753     */
8754    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8755        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8756            // We weren't called from within a direct call to fitSystemWindows,
8757            // call into it as a fallback in case we're in a class that overrides it
8758            // and has logic to perform.
8759            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8760                return insets.consumeSystemWindowInsets();
8761            }
8762        } else {
8763            // We were called from within a direct call to fitSystemWindows.
8764            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8765                return insets.consumeSystemWindowInsets();
8766            }
8767        }
8768        return insets;
8769    }
8770
8771    /**
8772     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8773     * window insets to this view. The listener's
8774     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8775     * method will be called instead of the view's
8776     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8777     *
8778     * @param listener Listener to set
8779     *
8780     * @see #onApplyWindowInsets(WindowInsets)
8781     */
8782    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8783        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8784    }
8785
8786    /**
8787     * Request to apply the given window insets to this view or another view in its subtree.
8788     *
8789     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8790     * obscured by window decorations or overlays. This can include the status and navigation bars,
8791     * action bars, input methods and more. New inset categories may be added in the future.
8792     * The method returns the insets provided minus any that were applied by this view or its
8793     * children.</p>
8794     *
8795     * <p>Clients wishing to provide custom behavior should override the
8796     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8797     * {@link OnApplyWindowInsetsListener} via the
8798     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8799     * method.</p>
8800     *
8801     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8802     * </p>
8803     *
8804     * @param insets Insets to apply
8805     * @return The provided insets minus the insets that were consumed
8806     */
8807    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8808        try {
8809            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8810            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8811                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8812            } else {
8813                return onApplyWindowInsets(insets);
8814            }
8815        } finally {
8816            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8817        }
8818    }
8819
8820    /**
8821     * Compute the view's coordinate within the surface.
8822     *
8823     * <p>Computes the coordinates of this view in its surface. The argument
8824     * must be an array of two integers. After the method returns, the array
8825     * contains the x and y location in that order.</p>
8826     * @hide
8827     * @param location an array of two integers in which to hold the coordinates
8828     */
8829    public void getLocationInSurface(@Size(2) int[] location) {
8830        getLocationInWindow(location);
8831        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8832            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8833            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8834        }
8835    }
8836
8837    /**
8838     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8839     * only available if the view is attached.
8840     *
8841     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8842     */
8843    public WindowInsets getRootWindowInsets() {
8844        if (mAttachInfo != null) {
8845            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8846        }
8847        return null;
8848    }
8849
8850    /**
8851     * @hide Compute the insets that should be consumed by this view and the ones
8852     * that should propagate to those under it.
8853     */
8854    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8855        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8856                || mAttachInfo == null
8857                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8858                        && !mAttachInfo.mOverscanRequested)) {
8859            outLocalInsets.set(inoutInsets);
8860            inoutInsets.set(0, 0, 0, 0);
8861            return true;
8862        } else {
8863            // The application wants to take care of fitting system window for
8864            // the content...  however we still need to take care of any overscan here.
8865            final Rect overscan = mAttachInfo.mOverscanInsets;
8866            outLocalInsets.set(overscan);
8867            inoutInsets.left -= overscan.left;
8868            inoutInsets.top -= overscan.top;
8869            inoutInsets.right -= overscan.right;
8870            inoutInsets.bottom -= overscan.bottom;
8871            return false;
8872        }
8873    }
8874
8875    /**
8876     * Compute insets that should be consumed by this view and the ones that should propagate
8877     * to those under it.
8878     *
8879     * @param in Insets currently being processed by this View, likely received as a parameter
8880     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8881     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8882     *                       by this view
8883     * @return Insets that should be passed along to views under this one
8884     */
8885    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8886        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8887                || mAttachInfo == null
8888                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8889            outLocalInsets.set(in.getSystemWindowInsets());
8890            return in.consumeSystemWindowInsets();
8891        } else {
8892            outLocalInsets.set(0, 0, 0, 0);
8893            return in;
8894        }
8895    }
8896
8897    /**
8898     * Sets whether or not this view should account for system screen decorations
8899     * such as the status bar and inset its content; that is, controlling whether
8900     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8901     * executed.  See that method for more details.
8902     *
8903     * <p>Note that if you are providing your own implementation of
8904     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8905     * flag to true -- your implementation will be overriding the default
8906     * implementation that checks this flag.
8907     *
8908     * @param fitSystemWindows If true, then the default implementation of
8909     * {@link #fitSystemWindows(Rect)} will be executed.
8910     *
8911     * @attr ref android.R.styleable#View_fitsSystemWindows
8912     * @see #getFitsSystemWindows()
8913     * @see #fitSystemWindows(Rect)
8914     * @see #setSystemUiVisibility(int)
8915     */
8916    public void setFitsSystemWindows(boolean fitSystemWindows) {
8917        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8918    }
8919
8920    /**
8921     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8922     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8923     * will be executed.
8924     *
8925     * @return {@code true} if the default implementation of
8926     * {@link #fitSystemWindows(Rect)} will be executed.
8927     *
8928     * @attr ref android.R.styleable#View_fitsSystemWindows
8929     * @see #setFitsSystemWindows(boolean)
8930     * @see #fitSystemWindows(Rect)
8931     * @see #setSystemUiVisibility(int)
8932     */
8933    @ViewDebug.ExportedProperty
8934    public boolean getFitsSystemWindows() {
8935        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8936    }
8937
8938    /** @hide */
8939    public boolean fitsSystemWindows() {
8940        return getFitsSystemWindows();
8941    }
8942
8943    /**
8944     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8945     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8946     */
8947    @Deprecated
8948    public void requestFitSystemWindows() {
8949        if (mParent != null) {
8950            mParent.requestFitSystemWindows();
8951        }
8952    }
8953
8954    /**
8955     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8956     */
8957    public void requestApplyInsets() {
8958        requestFitSystemWindows();
8959    }
8960
8961    /**
8962     * For use by PhoneWindow to make its own system window fitting optional.
8963     * @hide
8964     */
8965    public void makeOptionalFitsSystemWindows() {
8966        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8967    }
8968
8969    /**
8970     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8971     * treat them as such.
8972     * @hide
8973     */
8974    public void getOutsets(Rect outOutsetRect) {
8975        if (mAttachInfo != null) {
8976            outOutsetRect.set(mAttachInfo.mOutsets);
8977        } else {
8978            outOutsetRect.setEmpty();
8979        }
8980    }
8981
8982    /**
8983     * Returns the visibility status for this view.
8984     *
8985     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8986     * @attr ref android.R.styleable#View_visibility
8987     */
8988    @ViewDebug.ExportedProperty(mapping = {
8989        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8990        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8991        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8992    })
8993    @Visibility
8994    public int getVisibility() {
8995        return mViewFlags & VISIBILITY_MASK;
8996    }
8997
8998    /**
8999     * Set the visibility state of this view.
9000     *
9001     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9002     * @attr ref android.R.styleable#View_visibility
9003     */
9004    @RemotableViewMethod
9005    public void setVisibility(@Visibility int visibility) {
9006        setFlags(visibility, VISIBILITY_MASK);
9007    }
9008
9009    /**
9010     * Returns the enabled status for this view. The interpretation of the
9011     * enabled state varies by subclass.
9012     *
9013     * @return True if this view is enabled, false otherwise.
9014     */
9015    @ViewDebug.ExportedProperty
9016    public boolean isEnabled() {
9017        return (mViewFlags & ENABLED_MASK) == ENABLED;
9018    }
9019
9020    /**
9021     * Set the enabled state of this view. The interpretation of the enabled
9022     * state varies by subclass.
9023     *
9024     * @param enabled True if this view is enabled, false otherwise.
9025     */
9026    @RemotableViewMethod
9027    public void setEnabled(boolean enabled) {
9028        if (enabled == isEnabled()) return;
9029
9030        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9031
9032        /*
9033         * The View most likely has to change its appearance, so refresh
9034         * the drawable state.
9035         */
9036        refreshDrawableState();
9037
9038        // Invalidate too, since the default behavior for views is to be
9039        // be drawn at 50% alpha rather than to change the drawable.
9040        invalidate(true);
9041
9042        if (!enabled) {
9043            cancelPendingInputEvents();
9044        }
9045    }
9046
9047    /**
9048     * Set whether this view can receive the focus.
9049     * <p>
9050     * Setting this to false will also ensure that this view is not focusable
9051     * in touch mode.
9052     *
9053     * @param focusable If true, this view can receive the focus.
9054     *
9055     * @see #setFocusableInTouchMode(boolean)
9056     * @see #setFocusable(int)
9057     * @attr ref android.R.styleable#View_focusable
9058     */
9059    public void setFocusable(boolean focusable) {
9060        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9061    }
9062
9063    /**
9064     * Sets whether this view can receive focus.
9065     * <p>
9066     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9067     * automatically based on the view's interactivity. This is the default.
9068     * <p>
9069     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9070     * in touch mode.
9071     *
9072     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9073     *                  or {@link #FOCUSABLE_AUTO}.
9074     * @see #setFocusableInTouchMode(boolean)
9075     * @attr ref android.R.styleable#View_focusable
9076     */
9077    public void setFocusable(@Focusable int focusable) {
9078        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9079            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9080        }
9081        setFlags(focusable, FOCUSABLE_MASK);
9082    }
9083
9084    /**
9085     * Set whether this view can receive focus while in touch mode.
9086     *
9087     * Setting this to true will also ensure that this view is focusable.
9088     *
9089     * @param focusableInTouchMode If true, this view can receive the focus while
9090     *   in touch mode.
9091     *
9092     * @see #setFocusable(boolean)
9093     * @attr ref android.R.styleable#View_focusableInTouchMode
9094     */
9095    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9096        // Focusable in touch mode should always be set before the focusable flag
9097        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9098        // which, in touch mode, will not successfully request focus on this view
9099        // because the focusable in touch mode flag is not set
9100        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9101
9102        // Clear FOCUSABLE_AUTO if set.
9103        if (focusableInTouchMode) {
9104            // Clears FOCUSABLE_AUTO if set.
9105            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9106        }
9107    }
9108
9109    /**
9110     * Sets the hints that helps the autofill service to select the appropriate data to fill the
9111     * view.
9112     *
9113     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9114     * @attr ref android.R.styleable#View_autofillHints
9115     */
9116    public void setAutofillHints(@Nullable String... autofillHints) {
9117        if (autofillHints == null || autofillHints.length == 0) {
9118            mAutofillHints = null;
9119        } else {
9120            mAutofillHints = autofillHints;
9121        }
9122    }
9123
9124    /**
9125     * @hide
9126     */
9127    @TestApi
9128    public void setAutofilled(boolean isAutofilled) {
9129        boolean wasChanged = isAutofilled != isAutofilled();
9130
9131        if (wasChanged) {
9132            if (isAutofilled) {
9133                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9134            } else {
9135                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9136            }
9137
9138            invalidate();
9139        }
9140    }
9141
9142    /**
9143     * Set whether this view should have sound effects enabled for events such as
9144     * clicking and touching.
9145     *
9146     * <p>You may wish to disable sound effects for a view if you already play sounds,
9147     * for instance, a dial key that plays dtmf tones.
9148     *
9149     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9150     * @see #isSoundEffectsEnabled()
9151     * @see #playSoundEffect(int)
9152     * @attr ref android.R.styleable#View_soundEffectsEnabled
9153     */
9154    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9155        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9156    }
9157
9158    /**
9159     * @return whether this view should have sound effects enabled for events such as
9160     *     clicking and touching.
9161     *
9162     * @see #setSoundEffectsEnabled(boolean)
9163     * @see #playSoundEffect(int)
9164     * @attr ref android.R.styleable#View_soundEffectsEnabled
9165     */
9166    @ViewDebug.ExportedProperty
9167    public boolean isSoundEffectsEnabled() {
9168        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9169    }
9170
9171    /**
9172     * Set whether this view should have haptic feedback for events such as
9173     * long presses.
9174     *
9175     * <p>You may wish to disable haptic feedback if your view already controls
9176     * its own haptic feedback.
9177     *
9178     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9179     * @see #isHapticFeedbackEnabled()
9180     * @see #performHapticFeedback(int)
9181     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9182     */
9183    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9184        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9185    }
9186
9187    /**
9188     * @return whether this view should have haptic feedback enabled for events
9189     * long presses.
9190     *
9191     * @see #setHapticFeedbackEnabled(boolean)
9192     * @see #performHapticFeedback(int)
9193     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9194     */
9195    @ViewDebug.ExportedProperty
9196    public boolean isHapticFeedbackEnabled() {
9197        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9198    }
9199
9200    /**
9201     * Returns the layout direction for this view.
9202     *
9203     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9204     *   {@link #LAYOUT_DIRECTION_RTL},
9205     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9206     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9207     *
9208     * @attr ref android.R.styleable#View_layoutDirection
9209     *
9210     * @hide
9211     */
9212    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9213        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9214        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9215        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9216        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9217    })
9218    @LayoutDir
9219    public int getRawLayoutDirection() {
9220        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9221    }
9222
9223    /**
9224     * Set the layout direction for this view. This will propagate a reset of layout direction
9225     * resolution to the view's children and resolve layout direction for this view.
9226     *
9227     * @param layoutDirection the layout direction to set. Should be one of:
9228     *
9229     * {@link #LAYOUT_DIRECTION_LTR},
9230     * {@link #LAYOUT_DIRECTION_RTL},
9231     * {@link #LAYOUT_DIRECTION_INHERIT},
9232     * {@link #LAYOUT_DIRECTION_LOCALE}.
9233     *
9234     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9235     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9236     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9237     *
9238     * @attr ref android.R.styleable#View_layoutDirection
9239     */
9240    @RemotableViewMethod
9241    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9242        if (getRawLayoutDirection() != layoutDirection) {
9243            // Reset the current layout direction and the resolved one
9244            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9245            resetRtlProperties();
9246            // Set the new layout direction (filtered)
9247            mPrivateFlags2 |=
9248                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9249            // We need to resolve all RTL properties as they all depend on layout direction
9250            resolveRtlPropertiesIfNeeded();
9251            requestLayout();
9252            invalidate(true);
9253        }
9254    }
9255
9256    /**
9257     * Returns the resolved layout direction for this view.
9258     *
9259     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9260     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9261     *
9262     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9263     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9264     *
9265     * @attr ref android.R.styleable#View_layoutDirection
9266     */
9267    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9268        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9269        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9270    })
9271    @ResolvedLayoutDir
9272    public int getLayoutDirection() {
9273        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9274        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9275            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9276            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9277        }
9278        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9279                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9280    }
9281
9282    /**
9283     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9284     * layout attribute and/or the inherited value from the parent
9285     *
9286     * @return true if the layout is right-to-left.
9287     *
9288     * @hide
9289     */
9290    @ViewDebug.ExportedProperty(category = "layout")
9291    public boolean isLayoutRtl() {
9292        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9293    }
9294
9295    /**
9296     * Indicates whether the view is currently tracking transient state that the
9297     * app should not need to concern itself with saving and restoring, but that
9298     * the framework should take special note to preserve when possible.
9299     *
9300     * <p>A view with transient state cannot be trivially rebound from an external
9301     * data source, such as an adapter binding item views in a list. This may be
9302     * because the view is performing an animation, tracking user selection
9303     * of content, or similar.</p>
9304     *
9305     * @return true if the view has transient state
9306     */
9307    @ViewDebug.ExportedProperty(category = "layout")
9308    public boolean hasTransientState() {
9309        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9310    }
9311
9312    /**
9313     * Set whether this view is currently tracking transient state that the
9314     * framework should attempt to preserve when possible. This flag is reference counted,
9315     * so every call to setHasTransientState(true) should be paired with a later call
9316     * to setHasTransientState(false).
9317     *
9318     * <p>A view with transient state cannot be trivially rebound from an external
9319     * data source, such as an adapter binding item views in a list. This may be
9320     * because the view is performing an animation, tracking user selection
9321     * of content, or similar.</p>
9322     *
9323     * @param hasTransientState true if this view has transient state
9324     */
9325    public void setHasTransientState(boolean hasTransientState) {
9326        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9327                mTransientStateCount - 1;
9328        if (mTransientStateCount < 0) {
9329            mTransientStateCount = 0;
9330            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9331                    "unmatched pair of setHasTransientState calls");
9332        } else if ((hasTransientState && mTransientStateCount == 1) ||
9333                (!hasTransientState && mTransientStateCount == 0)) {
9334            // update flag if we've just incremented up from 0 or decremented down to 0
9335            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9336                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9337            if (mParent != null) {
9338                try {
9339                    mParent.childHasTransientStateChanged(this, hasTransientState);
9340                } catch (AbstractMethodError e) {
9341                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9342                            " does not fully implement ViewParent", e);
9343                }
9344            }
9345        }
9346    }
9347
9348    /**
9349     * Returns true if this view is currently attached to a window.
9350     */
9351    public boolean isAttachedToWindow() {
9352        return mAttachInfo != null;
9353    }
9354
9355    /**
9356     * Returns true if this view has been through at least one layout since it
9357     * was last attached to or detached from a window.
9358     */
9359    public boolean isLaidOut() {
9360        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9361    }
9362
9363    /**
9364     * If this view doesn't do any drawing on its own, set this flag to
9365     * allow further optimizations. By default, this flag is not set on
9366     * View, but could be set on some View subclasses such as ViewGroup.
9367     *
9368     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9369     * you should clear this flag.
9370     *
9371     * @param willNotDraw whether or not this View draw on its own
9372     */
9373    public void setWillNotDraw(boolean willNotDraw) {
9374        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9375    }
9376
9377    /**
9378     * Returns whether or not this View draws on its own.
9379     *
9380     * @return true if this view has nothing to draw, false otherwise
9381     */
9382    @ViewDebug.ExportedProperty(category = "drawing")
9383    public boolean willNotDraw() {
9384        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9385    }
9386
9387    /**
9388     * When a View's drawing cache is enabled, drawing is redirected to an
9389     * offscreen bitmap. Some views, like an ImageView, must be able to
9390     * bypass this mechanism if they already draw a single bitmap, to avoid
9391     * unnecessary usage of the memory.
9392     *
9393     * @param willNotCacheDrawing true if this view does not cache its
9394     *        drawing, false otherwise
9395     */
9396    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9397        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9398    }
9399
9400    /**
9401     * Returns whether or not this View can cache its drawing or not.
9402     *
9403     * @return true if this view does not cache its drawing, false otherwise
9404     */
9405    @ViewDebug.ExportedProperty(category = "drawing")
9406    public boolean willNotCacheDrawing() {
9407        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9408    }
9409
9410    /**
9411     * Indicates whether this view reacts to click events or not.
9412     *
9413     * @return true if the view is clickable, false otherwise
9414     *
9415     * @see #setClickable(boolean)
9416     * @attr ref android.R.styleable#View_clickable
9417     */
9418    @ViewDebug.ExportedProperty
9419    public boolean isClickable() {
9420        return (mViewFlags & CLICKABLE) == CLICKABLE;
9421    }
9422
9423    /**
9424     * Enables or disables click events for this view. When a view
9425     * is clickable it will change its state to "pressed" on every click.
9426     * Subclasses should set the view clickable to visually react to
9427     * user's clicks.
9428     *
9429     * @param clickable true to make the view clickable, false otherwise
9430     *
9431     * @see #isClickable()
9432     * @attr ref android.R.styleable#View_clickable
9433     */
9434    public void setClickable(boolean clickable) {
9435        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9436    }
9437
9438    /**
9439     * Indicates whether this view reacts to long click events or not.
9440     *
9441     * @return true if the view is long clickable, false otherwise
9442     *
9443     * @see #setLongClickable(boolean)
9444     * @attr ref android.R.styleable#View_longClickable
9445     */
9446    public boolean isLongClickable() {
9447        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9448    }
9449
9450    /**
9451     * Enables or disables long click events for this view. When a view is long
9452     * clickable it reacts to the user holding down the button for a longer
9453     * duration than a tap. This event can either launch the listener or a
9454     * context menu.
9455     *
9456     * @param longClickable true to make the view long clickable, false otherwise
9457     * @see #isLongClickable()
9458     * @attr ref android.R.styleable#View_longClickable
9459     */
9460    public void setLongClickable(boolean longClickable) {
9461        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9462    }
9463
9464    /**
9465     * Indicates whether this view reacts to context clicks or not.
9466     *
9467     * @return true if the view is context clickable, false otherwise
9468     * @see #setContextClickable(boolean)
9469     * @attr ref android.R.styleable#View_contextClickable
9470     */
9471    public boolean isContextClickable() {
9472        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9473    }
9474
9475    /**
9476     * Enables or disables context clicking for this view. This event can launch the listener.
9477     *
9478     * @param contextClickable true to make the view react to a context click, false otherwise
9479     * @see #isContextClickable()
9480     * @attr ref android.R.styleable#View_contextClickable
9481     */
9482    public void setContextClickable(boolean contextClickable) {
9483        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9484    }
9485
9486    /**
9487     * Sets the pressed state for this view and provides a touch coordinate for
9488     * animation hinting.
9489     *
9490     * @param pressed Pass true to set the View's internal state to "pressed",
9491     *            or false to reverts the View's internal state from a
9492     *            previously set "pressed" state.
9493     * @param x The x coordinate of the touch that caused the press
9494     * @param y The y coordinate of the touch that caused the press
9495     */
9496    private void setPressed(boolean pressed, float x, float y) {
9497        if (pressed) {
9498            drawableHotspotChanged(x, y);
9499        }
9500
9501        setPressed(pressed);
9502    }
9503
9504    /**
9505     * Sets the pressed state for this view.
9506     *
9507     * @see #isClickable()
9508     * @see #setClickable(boolean)
9509     *
9510     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9511     *        the View's internal state from a previously set "pressed" state.
9512     */
9513    public void setPressed(boolean pressed) {
9514        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9515
9516        if (pressed) {
9517            mPrivateFlags |= PFLAG_PRESSED;
9518        } else {
9519            mPrivateFlags &= ~PFLAG_PRESSED;
9520        }
9521
9522        if (needsRefresh) {
9523            refreshDrawableState();
9524        }
9525        dispatchSetPressed(pressed);
9526    }
9527
9528    /**
9529     * Dispatch setPressed to all of this View's children.
9530     *
9531     * @see #setPressed(boolean)
9532     *
9533     * @param pressed The new pressed state
9534     */
9535    protected void dispatchSetPressed(boolean pressed) {
9536    }
9537
9538    /**
9539     * Indicates whether the view is currently in pressed state. Unless
9540     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9541     * the pressed state.
9542     *
9543     * @see #setPressed(boolean)
9544     * @see #isClickable()
9545     * @see #setClickable(boolean)
9546     *
9547     * @return true if the view is currently pressed, false otherwise
9548     */
9549    @ViewDebug.ExportedProperty
9550    public boolean isPressed() {
9551        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9552    }
9553
9554    /**
9555     * @hide
9556     * Indicates whether this view will participate in data collection through
9557     * {@link ViewStructure}.  If true, it will not provide any data
9558     * for itself or its children.  If false, the normal data collection will be allowed.
9559     *
9560     * @return Returns false if assist data collection is not blocked, else true.
9561     *
9562     * @see #setAssistBlocked(boolean)
9563     * @attr ref android.R.styleable#View_assistBlocked
9564     */
9565    public boolean isAssistBlocked() {
9566        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9567    }
9568
9569    /**
9570     * @hide
9571     * Indicates whether this view will participate in data collection through
9572     * {@link ViewStructure} for autofill purposes.
9573     *
9574     * <p>If {@code true}, it will not provide any data for itself or its children.
9575     * <p>If {@code false}, the normal data collection will be allowed.
9576     *
9577     * @return Returns {@code false} if assist data collection for autofill is not blocked,
9578     * else {@code true}.
9579     */
9580    public boolean isAutofillBlocked() {
9581        // TODO(b/36171235): properly implement it using isImportantForAutofill()
9582        return false;
9583    }
9584
9585    /**
9586     * @hide
9587     * Controls whether assist data collection from this view and its children is enabled
9588     * (that is, whether {@link #onProvideStructure} and
9589     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9590     * allowing normal assist collection.  Setting this to false will disable assist collection.
9591     *
9592     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9593     * (the default) to allow it.
9594     *
9595     * @see #isAssistBlocked()
9596     * @see #onProvideStructure
9597     * @see #onProvideVirtualStructure
9598     * @attr ref android.R.styleable#View_assistBlocked
9599     */
9600    public void setAssistBlocked(boolean enabled) {
9601        if (enabled) {
9602            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9603        } else {
9604            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9605        }
9606    }
9607
9608    /**
9609     * Indicates whether this view will save its state (that is,
9610     * whether its {@link #onSaveInstanceState} method will be called).
9611     *
9612     * @return Returns true if the view state saving is enabled, else false.
9613     *
9614     * @see #setSaveEnabled(boolean)
9615     * @attr ref android.R.styleable#View_saveEnabled
9616     */
9617    public boolean isSaveEnabled() {
9618        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9619    }
9620
9621    /**
9622     * Controls whether the saving of this view's state is
9623     * enabled (that is, whether its {@link #onSaveInstanceState} method
9624     * will be called).  Note that even if freezing is enabled, the
9625     * view still must have an id assigned to it (via {@link #setId(int)})
9626     * for its state to be saved.  This flag can only disable the
9627     * saving of this view; any child views may still have their state saved.
9628     *
9629     * @param enabled Set to false to <em>disable</em> state saving, or true
9630     * (the default) to allow it.
9631     *
9632     * @see #isSaveEnabled()
9633     * @see #setId(int)
9634     * @see #onSaveInstanceState()
9635     * @attr ref android.R.styleable#View_saveEnabled
9636     */
9637    public void setSaveEnabled(boolean enabled) {
9638        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9639    }
9640
9641    /**
9642     * Gets whether the framework should discard touches when the view's
9643     * window is obscured by another visible window.
9644     * Refer to the {@link View} security documentation for more details.
9645     *
9646     * @return True if touch filtering is enabled.
9647     *
9648     * @see #setFilterTouchesWhenObscured(boolean)
9649     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9650     */
9651    @ViewDebug.ExportedProperty
9652    public boolean getFilterTouchesWhenObscured() {
9653        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9654    }
9655
9656    /**
9657     * Sets whether the framework should discard touches when the view's
9658     * window is obscured by another visible window.
9659     * Refer to the {@link View} security documentation for more details.
9660     *
9661     * @param enabled True if touch filtering should be enabled.
9662     *
9663     * @see #getFilterTouchesWhenObscured
9664     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9665     */
9666    public void setFilterTouchesWhenObscured(boolean enabled) {
9667        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9668                FILTER_TOUCHES_WHEN_OBSCURED);
9669    }
9670
9671    /**
9672     * Indicates whether the entire hierarchy under this view will save its
9673     * state when a state saving traversal occurs from its parent.  The default
9674     * is true; if false, these views will not be saved unless
9675     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9676     *
9677     * @return Returns true if the view state saving from parent is enabled, else false.
9678     *
9679     * @see #setSaveFromParentEnabled(boolean)
9680     */
9681    public boolean isSaveFromParentEnabled() {
9682        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9683    }
9684
9685    /**
9686     * Controls whether the entire hierarchy under this view will save its
9687     * state when a state saving traversal occurs from its parent.  The default
9688     * is true; if false, these views will not be saved unless
9689     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9690     *
9691     * @param enabled Set to false to <em>disable</em> state saving, or true
9692     * (the default) to allow it.
9693     *
9694     * @see #isSaveFromParentEnabled()
9695     * @see #setId(int)
9696     * @see #onSaveInstanceState()
9697     */
9698    public void setSaveFromParentEnabled(boolean enabled) {
9699        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9700    }
9701
9702
9703    /**
9704     * Returns whether this View is currently able to take focus.
9705     *
9706     * @return True if this view can take focus, or false otherwise.
9707     */
9708    @ViewDebug.ExportedProperty(category = "focus")
9709    public final boolean isFocusable() {
9710        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9711    }
9712
9713    /**
9714     * Returns the focusable setting for this view.
9715     *
9716     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9717     * @attr ref android.R.styleable#View_focusable
9718     */
9719    @ViewDebug.ExportedProperty(mapping = {
9720            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9721            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9722            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9723            }, category = "focus")
9724    @Focusable
9725    public int getFocusable() {
9726        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9727    }
9728
9729    /**
9730     * When a view is focusable, it may not want to take focus when in touch mode.
9731     * For example, a button would like focus when the user is navigating via a D-pad
9732     * so that the user can click on it, but once the user starts touching the screen,
9733     * the button shouldn't take focus
9734     * @return Whether the view is focusable in touch mode.
9735     * @attr ref android.R.styleable#View_focusableInTouchMode
9736     */
9737    @ViewDebug.ExportedProperty(category = "focus")
9738    public final boolean isFocusableInTouchMode() {
9739        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9740    }
9741
9742    /**
9743     * Find the nearest view in the specified direction that can take focus.
9744     * This does not actually give focus to that view.
9745     *
9746     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9747     *
9748     * @return The nearest focusable in the specified direction, or null if none
9749     *         can be found.
9750     */
9751    public View focusSearch(@FocusRealDirection int direction) {
9752        if (mParent != null) {
9753            return mParent.focusSearch(this, direction);
9754        } else {
9755            return null;
9756        }
9757    }
9758
9759    /**
9760     * Returns whether this View is a root of a keyboard navigation cluster.
9761     *
9762     * @return True if this view is a root of a cluster, or false otherwise.
9763     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9764     */
9765    @ViewDebug.ExportedProperty(category = "focus")
9766    public final boolean isKeyboardNavigationCluster() {
9767        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9768    }
9769
9770    /**
9771     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
9772     * will be ignored.
9773     *
9774     * @return the keyboard navigation cluster that this view is in (can be this view)
9775     *         or {@code null} if not in one
9776     */
9777    View findKeyboardNavigationCluster() {
9778        if (mParent instanceof View) {
9779            View cluster = ((View) mParent).findKeyboardNavigationCluster();
9780            if (cluster != null) {
9781                return cluster;
9782            } else if (isKeyboardNavigationCluster()) {
9783                return this;
9784            }
9785        }
9786        return null;
9787    }
9788
9789    /**
9790     * Set whether this view is a root of a keyboard navigation cluster.
9791     *
9792     * @param isCluster If true, this view is a root of a cluster.
9793     *
9794     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9795     */
9796    public void setKeyboardNavigationCluster(boolean isCluster) {
9797        if (isCluster) {
9798            mPrivateFlags3 |= PFLAG3_CLUSTER;
9799        } else {
9800            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9801        }
9802    }
9803
9804    /**
9805     * Sets this View as the one which receives focus the next time cluster navigation jumps
9806     * to the cluster containing this View. This does NOT change focus even if the cluster
9807     * containing this view is current.
9808     *
9809     * @hide
9810     */
9811    public final void setFocusedInCluster() {
9812        View top = findKeyboardNavigationCluster();
9813        if (top == this) {
9814            return;
9815        }
9816        ViewParent parent = mParent;
9817        View child = this;
9818        while (parent instanceof ViewGroup) {
9819            ((ViewGroup) parent).setFocusedInCluster(child);
9820            if (parent == top) {
9821                return;
9822            }
9823            child = (View) parent;
9824            parent = parent.getParent();
9825        }
9826    }
9827
9828    /**
9829     * Returns whether this View should receive focus when the focus is restored for the view
9830     * hierarchy containing this view.
9831     * <p>
9832     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9833     * window or serves as a target of cluster navigation.
9834     *
9835     * @see #restoreDefaultFocus()
9836     *
9837     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9838     * @attr ref android.R.styleable#View_focusedByDefault
9839     */
9840    @ViewDebug.ExportedProperty(category = "focus")
9841    public final boolean isFocusedByDefault() {
9842        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9843    }
9844
9845    /**
9846     * Sets whether this View should receive focus when the focus is restored for the view
9847     * hierarchy containing this view.
9848     * <p>
9849     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9850     * window or serves as a target of cluster navigation.
9851     *
9852     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9853     *                           {@code false} otherwise.
9854     *
9855     * @see #restoreDefaultFocus()
9856     *
9857     * @attr ref android.R.styleable#View_focusedByDefault
9858     */
9859    public void setFocusedByDefault(boolean isFocusedByDefault) {
9860        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9861            return;
9862        }
9863
9864        if (isFocusedByDefault) {
9865            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9866        } else {
9867            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9868        }
9869
9870        if (mParent instanceof ViewGroup) {
9871            if (isFocusedByDefault) {
9872                ((ViewGroup) mParent).setDefaultFocus(this);
9873            } else {
9874                ((ViewGroup) mParent).clearDefaultFocus(this);
9875            }
9876        }
9877    }
9878
9879    /**
9880     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9881     *
9882     * @return {@code true} if this view has default focus, {@code false} otherwise
9883     */
9884    boolean hasDefaultFocus() {
9885        return isFocusedByDefault();
9886    }
9887
9888    /**
9889     * Find the nearest keyboard navigation cluster in the specified direction.
9890     * This does not actually give focus to that cluster.
9891     *
9892     * @param currentCluster The starting point of the search. Null means the current cluster is not
9893     *                       found yet
9894     * @param direction Direction to look
9895     *
9896     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9897     *         can be found
9898     */
9899    public View keyboardNavigationClusterSearch(View currentCluster,
9900            @FocusDirection int direction) {
9901        if (isKeyboardNavigationCluster()) {
9902            currentCluster = this;
9903        }
9904        if (isRootNamespace()) {
9905            // Root namespace means we should consider ourselves the top of the
9906            // tree for group searching; otherwise we could be group searching
9907            // into other tabs.  see LocalActivityManager and TabHost for more info.
9908            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9909                    this, currentCluster, direction);
9910        } else if (mParent != null) {
9911            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9912        }
9913        return null;
9914    }
9915
9916    /**
9917     * This method is the last chance for the focused view and its ancestors to
9918     * respond to an arrow key. This is called when the focused view did not
9919     * consume the key internally, nor could the view system find a new view in
9920     * the requested direction to give focus to.
9921     *
9922     * @param focused The currently focused view.
9923     * @param direction The direction focus wants to move. One of FOCUS_UP,
9924     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9925     * @return True if the this view consumed this unhandled move.
9926     */
9927    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9928        return false;
9929    }
9930
9931    /**
9932     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
9933     * have {@link android.R.attr#state_focused} defined in its background.
9934     *
9935     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
9936     *                                      highlight, {@code false} otherwise.
9937     *
9938     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
9939     */
9940    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
9941        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
9942    }
9943
9944    /**
9945
9946    /**
9947     * Returns whether this View should use a default focus highlight when it gets focused but
9948     * doesn't have {@link android.R.attr#state_focused} defined in its background.
9949     *
9950     * @return True if this View should use a default focus highlight.
9951     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
9952     */
9953    @ViewDebug.ExportedProperty(category = "focus")
9954    public final boolean getDefaultFocusHighlightEnabled() {
9955        return mDefaultFocusHighlightEnabled;
9956    }
9957
9958    /**
9959     * If a user manually specified the next view id for a particular direction,
9960     * use the root to look up the view.
9961     * @param root The root view of the hierarchy containing this view.
9962     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9963     * or FOCUS_BACKWARD.
9964     * @return The user specified next view, or null if there is none.
9965     */
9966    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9967        switch (direction) {
9968            case FOCUS_LEFT:
9969                if (mNextFocusLeftId == View.NO_ID) return null;
9970                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9971            case FOCUS_RIGHT:
9972                if (mNextFocusRightId == View.NO_ID) return null;
9973                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9974            case FOCUS_UP:
9975                if (mNextFocusUpId == View.NO_ID) return null;
9976                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9977            case FOCUS_DOWN:
9978                if (mNextFocusDownId == View.NO_ID) return null;
9979                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9980            case FOCUS_FORWARD:
9981                if (mNextFocusForwardId == View.NO_ID) return null;
9982                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9983            case FOCUS_BACKWARD: {
9984                if (mID == View.NO_ID) return null;
9985                final int id = mID;
9986                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9987                    @Override
9988                    public boolean test(View t) {
9989                        return t.mNextFocusForwardId == id;
9990                    }
9991                });
9992            }
9993        }
9994        return null;
9995    }
9996
9997    /**
9998     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
9999     * use the root to look up the view.
10000     *
10001     * @param root the root view of the hierarchy containing this view
10002     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10003     * @return the user-specified next cluster, or {@code null} if there is none
10004     */
10005    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10006        switch (direction) {
10007            case FOCUS_FORWARD:
10008                if (mNextClusterForwardId == View.NO_ID) return null;
10009                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10010            case FOCUS_BACKWARD: {
10011                if (mID == View.NO_ID) return null;
10012                final int id = mID;
10013                return root.findViewByPredicateInsideOut(this,
10014                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10015            }
10016        }
10017        return null;
10018    }
10019
10020    private View findViewInsideOutShouldExist(View root, int id) {
10021        if (mMatchIdPredicate == null) {
10022            mMatchIdPredicate = new MatchIdPredicate();
10023        }
10024        mMatchIdPredicate.mId = id;
10025        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10026        if (result == null) {
10027            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10028        }
10029        return result;
10030    }
10031
10032    /**
10033     * Find and return all focusable views that are descendants of this view,
10034     * possibly including this view if it is focusable itself.
10035     *
10036     * @param direction The direction of the focus
10037     * @return A list of focusable views
10038     */
10039    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10040        ArrayList<View> result = new ArrayList<View>(24);
10041        addFocusables(result, direction);
10042        return result;
10043    }
10044
10045    /**
10046     * Add any focusable views that are descendants of this view (possibly
10047     * including this view if it is focusable itself) to views.  If we are in touch mode,
10048     * only add views that are also focusable in touch mode.
10049     *
10050     * @param views Focusable views found so far
10051     * @param direction The direction of the focus
10052     */
10053    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10054        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10055    }
10056
10057    /**
10058     * Adds any focusable views that are descendants of this view (possibly
10059     * including this view if it is focusable itself) to views. This method
10060     * adds all focusable views regardless if we are in touch mode or
10061     * only views focusable in touch mode if we are in touch mode or
10062     * only views that can take accessibility focus if accessibility is enabled
10063     * depending on the focusable mode parameter.
10064     *
10065     * @param views Focusable views found so far or null if all we are interested is
10066     *        the number of focusables.
10067     * @param direction The direction of the focus.
10068     * @param focusableMode The type of focusables to be added.
10069     *
10070     * @see #FOCUSABLES_ALL
10071     * @see #FOCUSABLES_TOUCH_MODE
10072     */
10073    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10074            @FocusableMode int focusableMode) {
10075        if (views == null) {
10076            return;
10077        }
10078        if (!isFocusable()) {
10079            return;
10080        }
10081        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10082                && !isFocusableInTouchMode()) {
10083            return;
10084        }
10085        views.add(this);
10086    }
10087
10088    /**
10089     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10090     * including this view if it is a cluster root itself) to views.
10091     *
10092     * @param views Keyboard navigation cluster roots found so far
10093     * @param direction Direction to look
10094     */
10095    public void addKeyboardNavigationClusters(
10096            @NonNull Collection<View> views,
10097            int direction) {
10098        if (!isKeyboardNavigationCluster()) {
10099            return;
10100        }
10101        if (!hasFocusable()) {
10102            return;
10103        }
10104        views.add(this);
10105    }
10106
10107    /**
10108     * Finds the Views that contain given text. The containment is case insensitive.
10109     * The search is performed by either the text that the View renders or the content
10110     * description that describes the view for accessibility purposes and the view does
10111     * not render or both. Clients can specify how the search is to be performed via
10112     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10113     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10114     *
10115     * @param outViews The output list of matching Views.
10116     * @param searched The text to match against.
10117     *
10118     * @see #FIND_VIEWS_WITH_TEXT
10119     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10120     * @see #setContentDescription(CharSequence)
10121     */
10122    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10123            @FindViewFlags int flags) {
10124        if (getAccessibilityNodeProvider() != null) {
10125            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10126                outViews.add(this);
10127            }
10128        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10129                && (searched != null && searched.length() > 0)
10130                && (mContentDescription != null && mContentDescription.length() > 0)) {
10131            String searchedLowerCase = searched.toString().toLowerCase();
10132            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10133            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10134                outViews.add(this);
10135            }
10136        }
10137    }
10138
10139    /**
10140     * Find and return all touchable views that are descendants of this view,
10141     * possibly including this view if it is touchable itself.
10142     *
10143     * @return A list of touchable views
10144     */
10145    public ArrayList<View> getTouchables() {
10146        ArrayList<View> result = new ArrayList<View>();
10147        addTouchables(result);
10148        return result;
10149    }
10150
10151    /**
10152     * Add any touchable views that are descendants of this view (possibly
10153     * including this view if it is touchable itself) to views.
10154     *
10155     * @param views Touchable views found so far
10156     */
10157    public void addTouchables(ArrayList<View> views) {
10158        final int viewFlags = mViewFlags;
10159
10160        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10161                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10162                && (viewFlags & ENABLED_MASK) == ENABLED) {
10163            views.add(this);
10164        }
10165    }
10166
10167    /**
10168     * Returns whether this View is accessibility focused.
10169     *
10170     * @return True if this View is accessibility focused.
10171     */
10172    public boolean isAccessibilityFocused() {
10173        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10174    }
10175
10176    /**
10177     * Call this to try to give accessibility focus to this view.
10178     *
10179     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10180     * returns false or the view is no visible or the view already has accessibility
10181     * focus.
10182     *
10183     * See also {@link #focusSearch(int)}, which is what you call to say that you
10184     * have focus, and you want your parent to look for the next one.
10185     *
10186     * @return Whether this view actually took accessibility focus.
10187     *
10188     * @hide
10189     */
10190    public boolean requestAccessibilityFocus() {
10191        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10192        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10193            return false;
10194        }
10195        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10196            return false;
10197        }
10198        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10199            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10200            ViewRootImpl viewRootImpl = getViewRootImpl();
10201            if (viewRootImpl != null) {
10202                viewRootImpl.setAccessibilityFocus(this, null);
10203            }
10204            invalidate();
10205            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10206            return true;
10207        }
10208        return false;
10209    }
10210
10211    /**
10212     * Call this to try to clear accessibility focus of this view.
10213     *
10214     * See also {@link #focusSearch(int)}, which is what you call to say that you
10215     * have focus, and you want your parent to look for the next one.
10216     *
10217     * @hide
10218     */
10219    public void clearAccessibilityFocus() {
10220        clearAccessibilityFocusNoCallbacks(0);
10221
10222        // Clear the global reference of accessibility focus if this view or
10223        // any of its descendants had accessibility focus. This will NOT send
10224        // an event or update internal state if focus is cleared from a
10225        // descendant view, which may leave views in inconsistent states.
10226        final ViewRootImpl viewRootImpl = getViewRootImpl();
10227        if (viewRootImpl != null) {
10228            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10229            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10230                viewRootImpl.setAccessibilityFocus(null, null);
10231            }
10232        }
10233    }
10234
10235    private void sendAccessibilityHoverEvent(int eventType) {
10236        // Since we are not delivering to a client accessibility events from not
10237        // important views (unless the clinet request that) we need to fire the
10238        // event from the deepest view exposed to the client. As a consequence if
10239        // the user crosses a not exposed view the client will see enter and exit
10240        // of the exposed predecessor followed by and enter and exit of that same
10241        // predecessor when entering and exiting the not exposed descendant. This
10242        // is fine since the client has a clear idea which view is hovered at the
10243        // price of a couple more events being sent. This is a simple and
10244        // working solution.
10245        View source = this;
10246        while (true) {
10247            if (source.includeForAccessibility()) {
10248                source.sendAccessibilityEvent(eventType);
10249                return;
10250            }
10251            ViewParent parent = source.getParent();
10252            if (parent instanceof View) {
10253                source = (View) parent;
10254            } else {
10255                return;
10256            }
10257        }
10258    }
10259
10260    /**
10261     * Clears accessibility focus without calling any callback methods
10262     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10263     * is used separately from that one for clearing accessibility focus when
10264     * giving this focus to another view.
10265     *
10266     * @param action The action, if any, that led to focus being cleared. Set to
10267     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10268     * the window.
10269     */
10270    void clearAccessibilityFocusNoCallbacks(int action) {
10271        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10272            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10273            invalidate();
10274            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10275                AccessibilityEvent event = AccessibilityEvent.obtain(
10276                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10277                event.setAction(action);
10278                if (mAccessibilityDelegate != null) {
10279                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10280                } else {
10281                    sendAccessibilityEventUnchecked(event);
10282                }
10283            }
10284        }
10285    }
10286
10287    /**
10288     * Call this to try to give focus to a specific view or to one of its
10289     * descendants.
10290     *
10291     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10292     * false), or if it is focusable and it is not focusable in touch mode
10293     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10294     *
10295     * See also {@link #focusSearch(int)}, which is what you call to say that you
10296     * have focus, and you want your parent to look for the next one.
10297     *
10298     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10299     * {@link #FOCUS_DOWN} and <code>null</code>.
10300     *
10301     * @return Whether this view or one of its descendants actually took focus.
10302     */
10303    public final boolean requestFocus() {
10304        return requestFocus(View.FOCUS_DOWN);
10305    }
10306
10307    /**
10308     * This will request focus for whichever View was last focused within this
10309     * cluster before a focus-jump out of it.
10310     *
10311     * @hide
10312     */
10313    @TestApi
10314    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10315        // Prioritize focusableByDefault over algorithmic focus selection.
10316        if (restoreDefaultFocus()) {
10317            return true;
10318        }
10319        return requestFocus(direction);
10320    }
10321
10322    /**
10323     * This will request focus for whichever View not in a cluster was last focused before a
10324     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10325     * the "first" focusable view it finds.
10326     *
10327     * @hide
10328     */
10329    @TestApi
10330    public boolean restoreFocusNotInCluster() {
10331        return requestFocus(View.FOCUS_DOWN);
10332    }
10333
10334    /**
10335     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10336     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10337     *
10338     * @return Whether this view or one of its descendants actually took focus
10339     */
10340    public boolean restoreDefaultFocus() {
10341        return requestFocus(View.FOCUS_DOWN);
10342    }
10343
10344    /**
10345     * Call this to try to give focus to a specific view or to one of its
10346     * descendants and give it a hint about what direction focus is heading.
10347     *
10348     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10349     * false), or if it is focusable and it is not focusable in touch mode
10350     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10351     *
10352     * See also {@link #focusSearch(int)}, which is what you call to say that you
10353     * have focus, and you want your parent to look for the next one.
10354     *
10355     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10356     * <code>null</code> set for the previously focused rectangle.
10357     *
10358     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10359     * @return Whether this view or one of its descendants actually took focus.
10360     */
10361    public final boolean requestFocus(int direction) {
10362        return requestFocus(direction, null);
10363    }
10364
10365    /**
10366     * Call this to try to give focus to a specific view or to one of its descendants
10367     * and give it hints about the direction and a specific rectangle that the focus
10368     * is coming from.  The rectangle can help give larger views a finer grained hint
10369     * about where focus is coming from, and therefore, where to show selection, or
10370     * forward focus change internally.
10371     *
10372     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10373     * false), or if it is focusable and it is not focusable in touch mode
10374     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10375     *
10376     * A View will not take focus if it is not visible.
10377     *
10378     * A View will not take focus if one of its parents has
10379     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10380     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10381     *
10382     * See also {@link #focusSearch(int)}, which is what you call to say that you
10383     * have focus, and you want your parent to look for the next one.
10384     *
10385     * You may wish to override this method if your custom {@link View} has an internal
10386     * {@link View} that it wishes to forward the request to.
10387     *
10388     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10389     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10390     *        to give a finer grained hint about where focus is coming from.  May be null
10391     *        if there is no hint.
10392     * @return Whether this view or one of its descendants actually took focus.
10393     */
10394    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10395        return requestFocusNoSearch(direction, previouslyFocusedRect);
10396    }
10397
10398    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10399        // need to be focusable
10400        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10401                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10402            return false;
10403        }
10404
10405        // need to be focusable in touch mode if in touch mode
10406        if (isInTouchMode() &&
10407            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10408               return false;
10409        }
10410
10411        // need to not have any parents blocking us
10412        if (hasAncestorThatBlocksDescendantFocus()) {
10413            return false;
10414        }
10415
10416        handleFocusGainInternal(direction, previouslyFocusedRect);
10417        return true;
10418    }
10419
10420    /**
10421     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10422     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10423     * touch mode to request focus when they are touched.
10424     *
10425     * @return Whether this view or one of its descendants actually took focus.
10426     *
10427     * @see #isInTouchMode()
10428     *
10429     */
10430    public final boolean requestFocusFromTouch() {
10431        // Leave touch mode if we need to
10432        if (isInTouchMode()) {
10433            ViewRootImpl viewRoot = getViewRootImpl();
10434            if (viewRoot != null) {
10435                viewRoot.ensureTouchMode(false);
10436            }
10437        }
10438        return requestFocus(View.FOCUS_DOWN);
10439    }
10440
10441    /**
10442     * @return Whether any ancestor of this view blocks descendant focus.
10443     */
10444    private boolean hasAncestorThatBlocksDescendantFocus() {
10445        final boolean focusableInTouchMode = isFocusableInTouchMode();
10446        ViewParent ancestor = mParent;
10447        while (ancestor instanceof ViewGroup) {
10448            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10449            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10450                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10451                return true;
10452            } else {
10453                ancestor = vgAncestor.getParent();
10454            }
10455        }
10456        return false;
10457    }
10458
10459    /**
10460     * Gets the mode for determining whether this View is important for accessibility.
10461     * A view is important for accessibility if it fires accessibility events and if it
10462     * is reported to accessibility services that query the screen.
10463     *
10464     * @return The mode for determining whether a view is important for accessibility, one
10465     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10466     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10467     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10468     *
10469     * @attr ref android.R.styleable#View_importantForAccessibility
10470     *
10471     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10472     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10473     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10474     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10475     */
10476    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10477            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10478            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10479            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10480            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10481                    to = "noHideDescendants")
10482        })
10483    public int getImportantForAccessibility() {
10484        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10485                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10486    }
10487
10488    /**
10489     * Sets the live region mode for this view. This indicates to accessibility
10490     * services whether they should automatically notify the user about changes
10491     * to the view's content description or text, or to the content descriptions
10492     * or text of the view's children (where applicable).
10493     * <p>
10494     * For example, in a login screen with a TextView that displays an "incorrect
10495     * password" notification, that view should be marked as a live region with
10496     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10497     * <p>
10498     * To disable change notifications for this view, use
10499     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10500     * mode for most views.
10501     * <p>
10502     * To indicate that the user should be notified of changes, use
10503     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10504     * <p>
10505     * If the view's changes should interrupt ongoing speech and notify the user
10506     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10507     *
10508     * @param mode The live region mode for this view, one of:
10509     *        <ul>
10510     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10511     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10512     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10513     *        </ul>
10514     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10515     */
10516    public void setAccessibilityLiveRegion(int mode) {
10517        if (mode != getAccessibilityLiveRegion()) {
10518            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10519            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10520                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10521            notifyViewAccessibilityStateChangedIfNeeded(
10522                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10523        }
10524    }
10525
10526    /**
10527     * Gets the live region mode for this View.
10528     *
10529     * @return The live region mode for the view.
10530     *
10531     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10532     *
10533     * @see #setAccessibilityLiveRegion(int)
10534     */
10535    public int getAccessibilityLiveRegion() {
10536        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10537                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10538    }
10539
10540    /**
10541     * Sets how to determine whether this view is important for accessibility
10542     * which is if it fires accessibility events and if it is reported to
10543     * accessibility services that query the screen.
10544     *
10545     * @param mode How to determine whether this view is important for accessibility.
10546     *
10547     * @attr ref android.R.styleable#View_importantForAccessibility
10548     *
10549     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10550     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10551     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10552     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10553     */
10554    public void setImportantForAccessibility(int mode) {
10555        final int oldMode = getImportantForAccessibility();
10556        if (mode != oldMode) {
10557            final boolean hideDescendants =
10558                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10559
10560            // If this node or its descendants are no longer important, try to
10561            // clear accessibility focus.
10562            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10563                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10564                if (focusHost != null) {
10565                    focusHost.clearAccessibilityFocus();
10566                }
10567            }
10568
10569            // If we're moving between AUTO and another state, we might not need
10570            // to send a subtree changed notification. We'll store the computed
10571            // importance, since we'll need to check it later to make sure.
10572            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10573                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10574            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10575            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10576            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10577                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10578            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10579                notifySubtreeAccessibilityStateChangedIfNeeded();
10580            } else {
10581                notifyViewAccessibilityStateChangedIfNeeded(
10582                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10583            }
10584        }
10585    }
10586
10587    /**
10588     * Returns the view within this view's hierarchy that is hosting
10589     * accessibility focus.
10590     *
10591     * @param searchDescendants whether to search for focus in descendant views
10592     * @return the view hosting accessibility focus, or {@code null}
10593     */
10594    private View findAccessibilityFocusHost(boolean searchDescendants) {
10595        if (isAccessibilityFocusedViewOrHost()) {
10596            return this;
10597        }
10598
10599        if (searchDescendants) {
10600            final ViewRootImpl viewRoot = getViewRootImpl();
10601            if (viewRoot != null) {
10602                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10603                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10604                    return focusHost;
10605                }
10606            }
10607        }
10608
10609        return null;
10610    }
10611
10612    /**
10613     * Computes whether this view should be exposed for accessibility. In
10614     * general, views that are interactive or provide information are exposed
10615     * while views that serve only as containers are hidden.
10616     * <p>
10617     * If an ancestor of this view has importance
10618     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10619     * returns <code>false</code>.
10620     * <p>
10621     * Otherwise, the value is computed according to the view's
10622     * {@link #getImportantForAccessibility()} value:
10623     * <ol>
10624     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10625     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10626     * </code>
10627     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10628     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10629     * view satisfies any of the following:
10630     * <ul>
10631     * <li>Is actionable, e.g. {@link #isClickable()},
10632     * {@link #isLongClickable()}, or {@link #isFocusable()}
10633     * <li>Has an {@link AccessibilityDelegate}
10634     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10635     * {@link OnKeyListener}, etc.
10636     * <li>Is an accessibility live region, e.g.
10637     * {@link #getAccessibilityLiveRegion()} is not
10638     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10639     * </ul>
10640     * </ol>
10641     *
10642     * @return Whether the view is exposed for accessibility.
10643     * @see #setImportantForAccessibility(int)
10644     * @see #getImportantForAccessibility()
10645     */
10646    public boolean isImportantForAccessibility() {
10647        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10648                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10649        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10650                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10651            return false;
10652        }
10653
10654        // Check parent mode to ensure we're not hidden.
10655        ViewParent parent = mParent;
10656        while (parent instanceof View) {
10657            if (((View) parent).getImportantForAccessibility()
10658                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10659                return false;
10660            }
10661            parent = parent.getParent();
10662        }
10663
10664        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10665                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10666                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10667    }
10668
10669    /**
10670     * Gets the parent for accessibility purposes. Note that the parent for
10671     * accessibility is not necessary the immediate parent. It is the first
10672     * predecessor that is important for accessibility.
10673     *
10674     * @return The parent for accessibility purposes.
10675     */
10676    public ViewParent getParentForAccessibility() {
10677        if (mParent instanceof View) {
10678            View parentView = (View) mParent;
10679            if (parentView.includeForAccessibility()) {
10680                return mParent;
10681            } else {
10682                return mParent.getParentForAccessibility();
10683            }
10684        }
10685        return null;
10686    }
10687
10688    /**
10689     * Adds the children of this View relevant for accessibility to the given list
10690     * as output. Since some Views are not important for accessibility the added
10691     * child views are not necessarily direct children of this view, rather they are
10692     * the first level of descendants important for accessibility.
10693     *
10694     * @param outChildren The output list that will receive children for accessibility.
10695     */
10696    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10697
10698    }
10699
10700    /**
10701     * Whether to regard this view for accessibility. A view is regarded for
10702     * accessibility if it is important for accessibility or the querying
10703     * accessibility service has explicitly requested that view not
10704     * important for accessibility are regarded.
10705     *
10706     * @return Whether to regard the view for accessibility.
10707     *
10708     * @hide
10709     */
10710    public boolean includeForAccessibility() {
10711        if (mAttachInfo != null) {
10712            return (mAttachInfo.mAccessibilityFetchFlags
10713                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10714                    || isImportantForAccessibility();
10715        }
10716        return false;
10717    }
10718
10719    /**
10720     * Returns whether the View is considered actionable from
10721     * accessibility perspective. Such view are important for
10722     * accessibility.
10723     *
10724     * @return True if the view is actionable for accessibility.
10725     *
10726     * @hide
10727     */
10728    public boolean isActionableForAccessibility() {
10729        return (isClickable() || isLongClickable() || isFocusable());
10730    }
10731
10732    /**
10733     * Returns whether the View has registered callbacks which makes it
10734     * important for accessibility.
10735     *
10736     * @return True if the view is actionable for accessibility.
10737     */
10738    private boolean hasListenersForAccessibility() {
10739        ListenerInfo info = getListenerInfo();
10740        return mTouchDelegate != null || info.mOnKeyListener != null
10741                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10742                || info.mOnHoverListener != null || info.mOnDragListener != null;
10743    }
10744
10745    /**
10746     * Notifies that the accessibility state of this view changed. The change
10747     * is local to this view and does not represent structural changes such
10748     * as children and parent. For example, the view became focusable. The
10749     * notification is at at most once every
10750     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10751     * to avoid unnecessary load to the system. Also once a view has a pending
10752     * notification this method is a NOP until the notification has been sent.
10753     *
10754     * @hide
10755     */
10756    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10757        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10758            return;
10759        }
10760        if (mSendViewStateChangedAccessibilityEvent == null) {
10761            mSendViewStateChangedAccessibilityEvent =
10762                    new SendViewStateChangedAccessibilityEvent();
10763        }
10764        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10765    }
10766
10767    /**
10768     * Notifies that the accessibility state of this view changed. The change
10769     * is *not* local to this view and does represent structural changes such
10770     * as children and parent. For example, the view size changed. The
10771     * notification is at at most once every
10772     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10773     * to avoid unnecessary load to the system. Also once a view has a pending
10774     * notification this method is a NOP until the notification has been sent.
10775     *
10776     * @hide
10777     */
10778    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10779        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10780            return;
10781        }
10782        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10783            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10784            if (mParent != null) {
10785                try {
10786                    mParent.notifySubtreeAccessibilityStateChanged(
10787                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10788                } catch (AbstractMethodError e) {
10789                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10790                            " does not fully implement ViewParent", e);
10791                }
10792            }
10793        }
10794    }
10795
10796    /**
10797     * Change the visibility of the View without triggering any other changes. This is
10798     * important for transitions, where visibility changes should not adjust focus or
10799     * trigger a new layout. This is only used when the visibility has already been changed
10800     * and we need a transient value during an animation. When the animation completes,
10801     * the original visibility value is always restored.
10802     *
10803     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10804     * @hide
10805     */
10806    public void setTransitionVisibility(@Visibility int visibility) {
10807        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10808    }
10809
10810    /**
10811     * Reset the flag indicating the accessibility state of the subtree rooted
10812     * at this view changed.
10813     */
10814    void resetSubtreeAccessibilityStateChanged() {
10815        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10816    }
10817
10818    /**
10819     * Report an accessibility action to this view's parents for delegated processing.
10820     *
10821     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10822     * call this method to delegate an accessibility action to a supporting parent. If the parent
10823     * returns true from its
10824     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10825     * method this method will return true to signify that the action was consumed.</p>
10826     *
10827     * <p>This method is useful for implementing nested scrolling child views. If
10828     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10829     * a custom view implementation may invoke this method to allow a parent to consume the
10830     * scroll first. If this method returns true the custom view should skip its own scrolling
10831     * behavior.</p>
10832     *
10833     * @param action Accessibility action to delegate
10834     * @param arguments Optional action arguments
10835     * @return true if the action was consumed by a parent
10836     */
10837    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10838        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10839            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10840                return true;
10841            }
10842        }
10843        return false;
10844    }
10845
10846    /**
10847     * Performs the specified accessibility action on the view. For
10848     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10849     * <p>
10850     * If an {@link AccessibilityDelegate} has been specified via calling
10851     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10852     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10853     * is responsible for handling this call.
10854     * </p>
10855     *
10856     * <p>The default implementation will delegate
10857     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10858     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10859     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10860     *
10861     * @param action The action to perform.
10862     * @param arguments Optional action arguments.
10863     * @return Whether the action was performed.
10864     */
10865    public boolean performAccessibilityAction(int action, Bundle arguments) {
10866      if (mAccessibilityDelegate != null) {
10867          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10868      } else {
10869          return performAccessibilityActionInternal(action, arguments);
10870      }
10871    }
10872
10873   /**
10874    * @see #performAccessibilityAction(int, Bundle)
10875    *
10876    * Note: Called from the default {@link AccessibilityDelegate}.
10877    *
10878    * @hide
10879    */
10880    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10881        if (isNestedScrollingEnabled()
10882                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10883                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10884                || action == R.id.accessibilityActionScrollUp
10885                || action == R.id.accessibilityActionScrollLeft
10886                || action == R.id.accessibilityActionScrollDown
10887                || action == R.id.accessibilityActionScrollRight)) {
10888            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10889                return true;
10890            }
10891        }
10892
10893        switch (action) {
10894            case AccessibilityNodeInfo.ACTION_CLICK: {
10895                if (isClickable()) {
10896                    performClick();
10897                    return true;
10898                }
10899            } break;
10900            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10901                if (isLongClickable()) {
10902                    performLongClick();
10903                    return true;
10904                }
10905            } break;
10906            case AccessibilityNodeInfo.ACTION_FOCUS: {
10907                if (!hasFocus()) {
10908                    // Get out of touch mode since accessibility
10909                    // wants to move focus around.
10910                    getViewRootImpl().ensureTouchMode(false);
10911                    return requestFocus();
10912                }
10913            } break;
10914            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10915                if (hasFocus()) {
10916                    clearFocus();
10917                    return !isFocused();
10918                }
10919            } break;
10920            case AccessibilityNodeInfo.ACTION_SELECT: {
10921                if (!isSelected()) {
10922                    setSelected(true);
10923                    return isSelected();
10924                }
10925            } break;
10926            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10927                if (isSelected()) {
10928                    setSelected(false);
10929                    return !isSelected();
10930                }
10931            } break;
10932            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10933                if (!isAccessibilityFocused()) {
10934                    return requestAccessibilityFocus();
10935                }
10936            } break;
10937            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10938                if (isAccessibilityFocused()) {
10939                    clearAccessibilityFocus();
10940                    return true;
10941                }
10942            } break;
10943            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10944                if (arguments != null) {
10945                    final int granularity = arguments.getInt(
10946                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10947                    final boolean extendSelection = arguments.getBoolean(
10948                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10949                    return traverseAtGranularity(granularity, true, extendSelection);
10950                }
10951            } break;
10952            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10953                if (arguments != null) {
10954                    final int granularity = arguments.getInt(
10955                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10956                    final boolean extendSelection = arguments.getBoolean(
10957                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10958                    return traverseAtGranularity(granularity, false, extendSelection);
10959                }
10960            } break;
10961            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10962                CharSequence text = getIterableTextForAccessibility();
10963                if (text == null) {
10964                    return false;
10965                }
10966                final int start = (arguments != null) ? arguments.getInt(
10967                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10968                final int end = (arguments != null) ? arguments.getInt(
10969                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10970                // Only cursor position can be specified (selection length == 0)
10971                if ((getAccessibilitySelectionStart() != start
10972                        || getAccessibilitySelectionEnd() != end)
10973                        && (start == end)) {
10974                    setAccessibilitySelection(start, end);
10975                    notifyViewAccessibilityStateChangedIfNeeded(
10976                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10977                    return true;
10978                }
10979            } break;
10980            case R.id.accessibilityActionShowOnScreen: {
10981                if (mAttachInfo != null) {
10982                    final Rect r = mAttachInfo.mTmpInvalRect;
10983                    getDrawingRect(r);
10984                    return requestRectangleOnScreen(r, true);
10985                }
10986            } break;
10987            case R.id.accessibilityActionContextClick: {
10988                if (isContextClickable()) {
10989                    performContextClick();
10990                    return true;
10991                }
10992            } break;
10993        }
10994        return false;
10995    }
10996
10997    private boolean traverseAtGranularity(int granularity, boolean forward,
10998            boolean extendSelection) {
10999        CharSequence text = getIterableTextForAccessibility();
11000        if (text == null || text.length() == 0) {
11001            return false;
11002        }
11003        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11004        if (iterator == null) {
11005            return false;
11006        }
11007        int current = getAccessibilitySelectionEnd();
11008        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11009            current = forward ? 0 : text.length();
11010        }
11011        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11012        if (range == null) {
11013            return false;
11014        }
11015        final int segmentStart = range[0];
11016        final int segmentEnd = range[1];
11017        int selectionStart;
11018        int selectionEnd;
11019        if (extendSelection && isAccessibilitySelectionExtendable()) {
11020            selectionStart = getAccessibilitySelectionStart();
11021            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11022                selectionStart = forward ? segmentStart : segmentEnd;
11023            }
11024            selectionEnd = forward ? segmentEnd : segmentStart;
11025        } else {
11026            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11027        }
11028        setAccessibilitySelection(selectionStart, selectionEnd);
11029        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11030                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11031        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11032        return true;
11033    }
11034
11035    /**
11036     * Gets the text reported for accessibility purposes.
11037     *
11038     * @return The accessibility text.
11039     *
11040     * @hide
11041     */
11042    public CharSequence getIterableTextForAccessibility() {
11043        return getContentDescription();
11044    }
11045
11046    /**
11047     * Gets whether accessibility selection can be extended.
11048     *
11049     * @return If selection is extensible.
11050     *
11051     * @hide
11052     */
11053    public boolean isAccessibilitySelectionExtendable() {
11054        return false;
11055    }
11056
11057    /**
11058     * @hide
11059     */
11060    public int getAccessibilitySelectionStart() {
11061        return mAccessibilityCursorPosition;
11062    }
11063
11064    /**
11065     * @hide
11066     */
11067    public int getAccessibilitySelectionEnd() {
11068        return getAccessibilitySelectionStart();
11069    }
11070
11071    /**
11072     * @hide
11073     */
11074    public void setAccessibilitySelection(int start, int end) {
11075        if (start ==  end && end == mAccessibilityCursorPosition) {
11076            return;
11077        }
11078        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11079            mAccessibilityCursorPosition = start;
11080        } else {
11081            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11082        }
11083        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11084    }
11085
11086    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11087            int fromIndex, int toIndex) {
11088        if (mParent == null) {
11089            return;
11090        }
11091        AccessibilityEvent event = AccessibilityEvent.obtain(
11092                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11093        onInitializeAccessibilityEvent(event);
11094        onPopulateAccessibilityEvent(event);
11095        event.setFromIndex(fromIndex);
11096        event.setToIndex(toIndex);
11097        event.setAction(action);
11098        event.setMovementGranularity(granularity);
11099        mParent.requestSendAccessibilityEvent(this, event);
11100    }
11101
11102    /**
11103     * @hide
11104     */
11105    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11106        switch (granularity) {
11107            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11108                CharSequence text = getIterableTextForAccessibility();
11109                if (text != null && text.length() > 0) {
11110                    CharacterTextSegmentIterator iterator =
11111                        CharacterTextSegmentIterator.getInstance(
11112                                mContext.getResources().getConfiguration().locale);
11113                    iterator.initialize(text.toString());
11114                    return iterator;
11115                }
11116            } break;
11117            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11118                CharSequence text = getIterableTextForAccessibility();
11119                if (text != null && text.length() > 0) {
11120                    WordTextSegmentIterator iterator =
11121                        WordTextSegmentIterator.getInstance(
11122                                mContext.getResources().getConfiguration().locale);
11123                    iterator.initialize(text.toString());
11124                    return iterator;
11125                }
11126            } break;
11127            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11128                CharSequence text = getIterableTextForAccessibility();
11129                if (text != null && text.length() > 0) {
11130                    ParagraphTextSegmentIterator iterator =
11131                        ParagraphTextSegmentIterator.getInstance();
11132                    iterator.initialize(text.toString());
11133                    return iterator;
11134                }
11135            } break;
11136        }
11137        return null;
11138    }
11139
11140    /**
11141     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11142     * and {@link #onFinishTemporaryDetach()}.
11143     *
11144     * <p>This method always returns {@code true} when called directly or indirectly from
11145     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11146     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11147     * <ul>
11148     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11149     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11150     * </ul>
11151     * </p>
11152     *
11153     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11154     * and {@link #onFinishTemporaryDetach()}.
11155     */
11156    public final boolean isTemporarilyDetached() {
11157        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11158    }
11159
11160    /**
11161     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11162     * a container View.
11163     */
11164    @CallSuper
11165    public void dispatchStartTemporaryDetach() {
11166        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11167        notifyEnterOrExitForAutoFillIfNeeded(false);
11168        onStartTemporaryDetach();
11169    }
11170
11171    /**
11172     * This is called when a container is going to temporarily detach a child, with
11173     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11174     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11175     * {@link #onDetachedFromWindow()} when the container is done.
11176     */
11177    public void onStartTemporaryDetach() {
11178        removeUnsetPressCallback();
11179        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11180    }
11181
11182    /**
11183     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11184     * a container View.
11185     */
11186    @CallSuper
11187    public void dispatchFinishTemporaryDetach() {
11188        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11189        onFinishTemporaryDetach();
11190        if (hasWindowFocus() && hasFocus()) {
11191            InputMethodManager.getInstance().focusIn(this);
11192        }
11193        notifyEnterOrExitForAutoFillIfNeeded(true);
11194    }
11195
11196    /**
11197     * Called after {@link #onStartTemporaryDetach} when the container is done
11198     * changing the view.
11199     */
11200    public void onFinishTemporaryDetach() {
11201    }
11202
11203    /**
11204     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11205     * for this view's window.  Returns null if the view is not currently attached
11206     * to the window.  Normally you will not need to use this directly, but
11207     * just use the standard high-level event callbacks like
11208     * {@link #onKeyDown(int, KeyEvent)}.
11209     */
11210    public KeyEvent.DispatcherState getKeyDispatcherState() {
11211        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11212    }
11213
11214    /**
11215     * Dispatch a key event before it is processed by any input method
11216     * associated with the view hierarchy.  This can be used to intercept
11217     * key events in special situations before the IME consumes them; a
11218     * typical example would be handling the BACK key to update the application's
11219     * UI instead of allowing the IME to see it and close itself.
11220     *
11221     * @param event The key event to be dispatched.
11222     * @return True if the event was handled, false otherwise.
11223     */
11224    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11225        return onKeyPreIme(event.getKeyCode(), event);
11226    }
11227
11228    /**
11229     * Dispatch a key event to the next view on the focus path. This path runs
11230     * from the top of the view tree down to the currently focused view. If this
11231     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11232     * the next node down the focus path. This method also fires any key
11233     * listeners.
11234     *
11235     * @param event The key event to be dispatched.
11236     * @return True if the event was handled, false otherwise.
11237     */
11238    public boolean dispatchKeyEvent(KeyEvent event) {
11239        if (mInputEventConsistencyVerifier != null) {
11240            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11241        }
11242
11243        // Give any attached key listener a first crack at the event.
11244        //noinspection SimplifiableIfStatement
11245        ListenerInfo li = mListenerInfo;
11246        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11247                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11248            return true;
11249        }
11250
11251        if (event.dispatch(this, mAttachInfo != null
11252                ? mAttachInfo.mKeyDispatchState : null, this)) {
11253            return true;
11254        }
11255
11256        if (mInputEventConsistencyVerifier != null) {
11257            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11258        }
11259        return false;
11260    }
11261
11262    /**
11263     * Dispatches a key shortcut event.
11264     *
11265     * @param event The key event to be dispatched.
11266     * @return True if the event was handled by the view, false otherwise.
11267     */
11268    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11269        return onKeyShortcut(event.getKeyCode(), event);
11270    }
11271
11272    /**
11273     * Pass the touch screen motion event down to the target view, or this
11274     * view if it is the target.
11275     *
11276     * @param event The motion event to be dispatched.
11277     * @return True if the event was handled by the view, false otherwise.
11278     */
11279    public boolean dispatchTouchEvent(MotionEvent event) {
11280        // If the event should be handled by accessibility focus first.
11281        if (event.isTargetAccessibilityFocus()) {
11282            // We don't have focus or no virtual descendant has it, do not handle the event.
11283            if (!isAccessibilityFocusedViewOrHost()) {
11284                return false;
11285            }
11286            // We have focus and got the event, then use normal event dispatch.
11287            event.setTargetAccessibilityFocus(false);
11288        }
11289
11290        boolean result = false;
11291
11292        if (mInputEventConsistencyVerifier != null) {
11293            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11294        }
11295
11296        final int actionMasked = event.getActionMasked();
11297        if (actionMasked == MotionEvent.ACTION_DOWN) {
11298            // Defensive cleanup for new gesture
11299            stopNestedScroll();
11300        }
11301
11302        if (onFilterTouchEventForSecurity(event)) {
11303            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11304                result = true;
11305            }
11306            //noinspection SimplifiableIfStatement
11307            ListenerInfo li = mListenerInfo;
11308            if (li != null && li.mOnTouchListener != null
11309                    && (mViewFlags & ENABLED_MASK) == ENABLED
11310                    && li.mOnTouchListener.onTouch(this, event)) {
11311                result = true;
11312            }
11313
11314            if (!result && onTouchEvent(event)) {
11315                result = true;
11316            }
11317        }
11318
11319        if (!result && mInputEventConsistencyVerifier != null) {
11320            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11321        }
11322
11323        // Clean up after nested scrolls if this is the end of a gesture;
11324        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11325        // of the gesture.
11326        if (actionMasked == MotionEvent.ACTION_UP ||
11327                actionMasked == MotionEvent.ACTION_CANCEL ||
11328                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11329            stopNestedScroll();
11330        }
11331
11332        return result;
11333    }
11334
11335    boolean isAccessibilityFocusedViewOrHost() {
11336        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11337                .getAccessibilityFocusedHost() == this);
11338    }
11339
11340    /**
11341     * Filter the touch event to apply security policies.
11342     *
11343     * @param event The motion event to be filtered.
11344     * @return True if the event should be dispatched, false if the event should be dropped.
11345     *
11346     * @see #getFilterTouchesWhenObscured
11347     */
11348    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11349        //noinspection RedundantIfStatement
11350        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11351                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11352            // Window is obscured, drop this touch.
11353            return false;
11354        }
11355        return true;
11356    }
11357
11358    /**
11359     * Pass a trackball motion event down to the focused view.
11360     *
11361     * @param event The motion event to be dispatched.
11362     * @return True if the event was handled by the view, false otherwise.
11363     */
11364    public boolean dispatchTrackballEvent(MotionEvent event) {
11365        if (mInputEventConsistencyVerifier != null) {
11366            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11367        }
11368
11369        return onTrackballEvent(event);
11370    }
11371
11372    /**
11373     * Pass a captured pointer event down to the focused view.
11374     *
11375     * @param event The motion event to be dispatched.
11376     * @return True if the event was handled by the view, false otherwise.
11377     */
11378    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11379        if (!hasPointerCapture()) {
11380            return false;
11381        }
11382        //noinspection SimplifiableIfStatement
11383        ListenerInfo li = mListenerInfo;
11384        if (li != null && li.mOnCapturedPointerListener != null
11385                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11386            return true;
11387        }
11388        return onCapturedPointerEvent(event);
11389    }
11390
11391    /**
11392     * Dispatch a generic motion event.
11393     * <p>
11394     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11395     * are delivered to the view under the pointer.  All other generic motion events are
11396     * delivered to the focused view.  Hover events are handled specially and are delivered
11397     * to {@link #onHoverEvent(MotionEvent)}.
11398     * </p>
11399     *
11400     * @param event The motion event to be dispatched.
11401     * @return True if the event was handled by the view, false otherwise.
11402     */
11403    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11404        if (mInputEventConsistencyVerifier != null) {
11405            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11406        }
11407
11408        final int source = event.getSource();
11409        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11410            final int action = event.getAction();
11411            if (action == MotionEvent.ACTION_HOVER_ENTER
11412                    || action == MotionEvent.ACTION_HOVER_MOVE
11413                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11414                if (dispatchHoverEvent(event)) {
11415                    return true;
11416                }
11417            } else if (dispatchGenericPointerEvent(event)) {
11418                return true;
11419            }
11420        } else if (dispatchGenericFocusedEvent(event)) {
11421            return true;
11422        }
11423
11424        if (dispatchGenericMotionEventInternal(event)) {
11425            return true;
11426        }
11427
11428        if (mInputEventConsistencyVerifier != null) {
11429            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11430        }
11431        return false;
11432    }
11433
11434    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11435        //noinspection SimplifiableIfStatement
11436        ListenerInfo li = mListenerInfo;
11437        if (li != null && li.mOnGenericMotionListener != null
11438                && (mViewFlags & ENABLED_MASK) == ENABLED
11439                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11440            return true;
11441        }
11442
11443        if (onGenericMotionEvent(event)) {
11444            return true;
11445        }
11446
11447        final int actionButton = event.getActionButton();
11448        switch (event.getActionMasked()) {
11449            case MotionEvent.ACTION_BUTTON_PRESS:
11450                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11451                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11452                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11453                    if (performContextClick(event.getX(), event.getY())) {
11454                        mInContextButtonPress = true;
11455                        setPressed(true, event.getX(), event.getY());
11456                        removeTapCallback();
11457                        removeLongPressCallback();
11458                        return true;
11459                    }
11460                }
11461                break;
11462
11463            case MotionEvent.ACTION_BUTTON_RELEASE:
11464                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11465                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11466                    mInContextButtonPress = false;
11467                    mIgnoreNextUpEvent = true;
11468                }
11469                break;
11470        }
11471
11472        if (mInputEventConsistencyVerifier != null) {
11473            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11474        }
11475        return false;
11476    }
11477
11478    /**
11479     * Dispatch a hover event.
11480     * <p>
11481     * Do not call this method directly.
11482     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11483     * </p>
11484     *
11485     * @param event The motion event to be dispatched.
11486     * @return True if the event was handled by the view, false otherwise.
11487     */
11488    protected boolean dispatchHoverEvent(MotionEvent event) {
11489        ListenerInfo li = mListenerInfo;
11490        //noinspection SimplifiableIfStatement
11491        if (li != null && li.mOnHoverListener != null
11492                && (mViewFlags & ENABLED_MASK) == ENABLED
11493                && li.mOnHoverListener.onHover(this, event)) {
11494            return true;
11495        }
11496
11497        return onHoverEvent(event);
11498    }
11499
11500    /**
11501     * Returns true if the view has a child to which it has recently sent
11502     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11503     * it does not have a hovered child, then it must be the innermost hovered view.
11504     * @hide
11505     */
11506    protected boolean hasHoveredChild() {
11507        return false;
11508    }
11509
11510    /**
11511     * Dispatch a generic motion event to the view under the first pointer.
11512     * <p>
11513     * Do not call this method directly.
11514     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11515     * </p>
11516     *
11517     * @param event The motion event to be dispatched.
11518     * @return True if the event was handled by the view, false otherwise.
11519     */
11520    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11521        return false;
11522    }
11523
11524    /**
11525     * Dispatch a generic motion event to the currently focused view.
11526     * <p>
11527     * Do not call this method directly.
11528     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11529     * </p>
11530     *
11531     * @param event The motion event to be dispatched.
11532     * @return True if the event was handled by the view, false otherwise.
11533     */
11534    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11535        return false;
11536    }
11537
11538    /**
11539     * Dispatch a pointer event.
11540     * <p>
11541     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11542     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11543     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11544     * and should not be expected to handle other pointing device features.
11545     * </p>
11546     *
11547     * @param event The motion event to be dispatched.
11548     * @return True if the event was handled by the view, false otherwise.
11549     * @hide
11550     */
11551    public final boolean dispatchPointerEvent(MotionEvent event) {
11552        if (event.isTouchEvent()) {
11553            return dispatchTouchEvent(event);
11554        } else {
11555            return dispatchGenericMotionEvent(event);
11556        }
11557    }
11558
11559    /**
11560     * Called when the window containing this view gains or loses window focus.
11561     * ViewGroups should override to route to their children.
11562     *
11563     * @param hasFocus True if the window containing this view now has focus,
11564     *        false otherwise.
11565     */
11566    public void dispatchWindowFocusChanged(boolean hasFocus) {
11567        onWindowFocusChanged(hasFocus);
11568    }
11569
11570    /**
11571     * Called when the window containing this view gains or loses focus.  Note
11572     * that this is separate from view focus: to receive key events, both
11573     * your view and its window must have focus.  If a window is displayed
11574     * on top of yours that takes input focus, then your own window will lose
11575     * focus but the view focus will remain unchanged.
11576     *
11577     * @param hasWindowFocus True if the window containing this view now has
11578     *        focus, false otherwise.
11579     */
11580    public void onWindowFocusChanged(boolean hasWindowFocus) {
11581        InputMethodManager imm = InputMethodManager.peekInstance();
11582        if (!hasWindowFocus) {
11583            if (isPressed()) {
11584                setPressed(false);
11585            }
11586            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11587            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11588                imm.focusOut(this);
11589            }
11590            removeLongPressCallback();
11591            removeTapCallback();
11592            onFocusLost();
11593        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11594            imm.focusIn(this);
11595        }
11596
11597        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11598
11599        refreshDrawableState();
11600    }
11601
11602    /**
11603     * Returns true if this view is in a window that currently has window focus.
11604     * Note that this is not the same as the view itself having focus.
11605     *
11606     * @return True if this view is in a window that currently has window focus.
11607     */
11608    public boolean hasWindowFocus() {
11609        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11610    }
11611
11612    /**
11613     * Dispatch a view visibility change down the view hierarchy.
11614     * ViewGroups should override to route to their children.
11615     * @param changedView The view whose visibility changed. Could be 'this' or
11616     * an ancestor view.
11617     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11618     * {@link #INVISIBLE} or {@link #GONE}.
11619     */
11620    protected void dispatchVisibilityChanged(@NonNull View changedView,
11621            @Visibility int visibility) {
11622        onVisibilityChanged(changedView, visibility);
11623    }
11624
11625    /**
11626     * Called when the visibility of the view or an ancestor of the view has
11627     * changed.
11628     *
11629     * @param changedView The view whose visibility changed. May be
11630     *                    {@code this} or an ancestor view.
11631     * @param visibility The new visibility, one of {@link #VISIBLE},
11632     *                   {@link #INVISIBLE} or {@link #GONE}.
11633     */
11634    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11635    }
11636
11637    /**
11638     * Dispatch a hint about whether this view is displayed. For instance, when
11639     * a View moves out of the screen, it might receives a display hint indicating
11640     * the view is not displayed. Applications should not <em>rely</em> on this hint
11641     * as there is no guarantee that they will receive one.
11642     *
11643     * @param hint A hint about whether or not this view is displayed:
11644     * {@link #VISIBLE} or {@link #INVISIBLE}.
11645     */
11646    public void dispatchDisplayHint(@Visibility int hint) {
11647        onDisplayHint(hint);
11648    }
11649
11650    /**
11651     * Gives this view a hint about whether is displayed or not. For instance, when
11652     * a View moves out of the screen, it might receives a display hint indicating
11653     * the view is not displayed. Applications should not <em>rely</em> on this hint
11654     * as there is no guarantee that they will receive one.
11655     *
11656     * @param hint A hint about whether or not this view is displayed:
11657     * {@link #VISIBLE} or {@link #INVISIBLE}.
11658     */
11659    protected void onDisplayHint(@Visibility int hint) {
11660    }
11661
11662    /**
11663     * Dispatch a window visibility change down the view hierarchy.
11664     * ViewGroups should override to route to their children.
11665     *
11666     * @param visibility The new visibility of the window.
11667     *
11668     * @see #onWindowVisibilityChanged(int)
11669     */
11670    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11671        onWindowVisibilityChanged(visibility);
11672    }
11673
11674    /**
11675     * Called when the window containing has change its visibility
11676     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11677     * that this tells you whether or not your window is being made visible
11678     * to the window manager; this does <em>not</em> tell you whether or not
11679     * your window is obscured by other windows on the screen, even if it
11680     * is itself visible.
11681     *
11682     * @param visibility The new visibility of the window.
11683     */
11684    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11685        if (visibility == VISIBLE) {
11686            initialAwakenScrollBars();
11687        }
11688    }
11689
11690    /**
11691     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11692     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11693     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11694     *
11695     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11696     *                  ancestors or by window visibility
11697     * @return true if this view is visible to the user, not counting clipping or overlapping
11698     */
11699    boolean dispatchVisibilityAggregated(boolean isVisible) {
11700        final boolean thisVisible = getVisibility() == VISIBLE;
11701        // If we're not visible but something is telling us we are, ignore it.
11702        if (thisVisible || !isVisible) {
11703            onVisibilityAggregated(isVisible);
11704        }
11705        return thisVisible && isVisible;
11706    }
11707
11708    /**
11709     * Called when the user-visibility of this View is potentially affected by a change
11710     * to this view itself, an ancestor view or the window this view is attached to.
11711     *
11712     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11713     *                  and this view's window is also visible
11714     */
11715    @CallSuper
11716    public void onVisibilityAggregated(boolean isVisible) {
11717        if (isVisible && mAttachInfo != null) {
11718            initialAwakenScrollBars();
11719        }
11720
11721        final Drawable dr = mBackground;
11722        if (dr != null && isVisible != dr.isVisible()) {
11723            dr.setVisible(isVisible, false);
11724        }
11725        final Drawable hl = mDefaultFocusHighlight;
11726        if (hl != null && isVisible != hl.isVisible()) {
11727            hl.setVisible(isVisible, false);
11728        }
11729        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11730        if (fg != null && isVisible != fg.isVisible()) {
11731            fg.setVisible(isVisible, false);
11732        }
11733
11734        if (isAutofillable()) {
11735            AutofillManager afm = getAutofillManager();
11736
11737            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
11738                if (mVisibilityChangeForAutofillHandler != null) {
11739                    mVisibilityChangeForAutofillHandler.removeMessages(0);
11740                }
11741
11742                // If the view is in the background but still part of the hierarchy this is called
11743                // with isVisible=false. Hence visibility==false requires further checks
11744                if (isVisible) {
11745                    afm.notifyViewVisibilityChange(this, true);
11746                } else {
11747                    if (mVisibilityChangeForAutofillHandler == null) {
11748                        mVisibilityChangeForAutofillHandler =
11749                                new VisibilityChangeForAutofillHandler(afm, this);
11750                    }
11751                    // Let current operation (e.g. removal of the view from the hierarchy)
11752                    // finish before checking state
11753                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
11754                }
11755            }
11756        }
11757    }
11758
11759    /**
11760     * Returns the current visibility of the window this view is attached to
11761     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11762     *
11763     * @return Returns the current visibility of the view's window.
11764     */
11765    @Visibility
11766    public int getWindowVisibility() {
11767        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11768    }
11769
11770    /**
11771     * Retrieve the overall visible display size in which the window this view is
11772     * attached to has been positioned in.  This takes into account screen
11773     * decorations above the window, for both cases where the window itself
11774     * is being position inside of them or the window is being placed under
11775     * then and covered insets are used for the window to position its content
11776     * inside.  In effect, this tells you the available area where content can
11777     * be placed and remain visible to users.
11778     *
11779     * <p>This function requires an IPC back to the window manager to retrieve
11780     * the requested information, so should not be used in performance critical
11781     * code like drawing.
11782     *
11783     * @param outRect Filled in with the visible display frame.  If the view
11784     * is not attached to a window, this is simply the raw display size.
11785     */
11786    public void getWindowVisibleDisplayFrame(Rect outRect) {
11787        if (mAttachInfo != null) {
11788            try {
11789                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11790            } catch (RemoteException e) {
11791                return;
11792            }
11793            // XXX This is really broken, and probably all needs to be done
11794            // in the window manager, and we need to know more about whether
11795            // we want the area behind or in front of the IME.
11796            final Rect insets = mAttachInfo.mVisibleInsets;
11797            outRect.left += insets.left;
11798            outRect.top += insets.top;
11799            outRect.right -= insets.right;
11800            outRect.bottom -= insets.bottom;
11801            return;
11802        }
11803        // The view is not attached to a display so we don't have a context.
11804        // Make a best guess about the display size.
11805        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11806        d.getRectSize(outRect);
11807    }
11808
11809    /**
11810     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11811     * is currently in without any insets.
11812     *
11813     * @hide
11814     */
11815    public void getWindowDisplayFrame(Rect outRect) {
11816        if (mAttachInfo != null) {
11817            try {
11818                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11819            } catch (RemoteException e) {
11820                return;
11821            }
11822            return;
11823        }
11824        // The view is not attached to a display so we don't have a context.
11825        // Make a best guess about the display size.
11826        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11827        d.getRectSize(outRect);
11828    }
11829
11830    /**
11831     * Dispatch a notification about a resource configuration change down
11832     * the view hierarchy.
11833     * ViewGroups should override to route to their children.
11834     *
11835     * @param newConfig The new resource configuration.
11836     *
11837     * @see #onConfigurationChanged(android.content.res.Configuration)
11838     */
11839    public void dispatchConfigurationChanged(Configuration newConfig) {
11840        onConfigurationChanged(newConfig);
11841    }
11842
11843    /**
11844     * Called when the current configuration of the resources being used
11845     * by the application have changed.  You can use this to decide when
11846     * to reload resources that can changed based on orientation and other
11847     * configuration characteristics.  You only need to use this if you are
11848     * not relying on the normal {@link android.app.Activity} mechanism of
11849     * recreating the activity instance upon a configuration change.
11850     *
11851     * @param newConfig The new resource configuration.
11852     */
11853    protected void onConfigurationChanged(Configuration newConfig) {
11854    }
11855
11856    /**
11857     * Private function to aggregate all per-view attributes in to the view
11858     * root.
11859     */
11860    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11861        performCollectViewAttributes(attachInfo, visibility);
11862    }
11863
11864    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11865        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11866            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11867                attachInfo.mKeepScreenOn = true;
11868            }
11869            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11870            ListenerInfo li = mListenerInfo;
11871            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11872                attachInfo.mHasSystemUiListeners = true;
11873            }
11874        }
11875    }
11876
11877    void needGlobalAttributesUpdate(boolean force) {
11878        final AttachInfo ai = mAttachInfo;
11879        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11880            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11881                    || ai.mHasSystemUiListeners) {
11882                ai.mRecomputeGlobalAttributes = true;
11883            }
11884        }
11885    }
11886
11887    /**
11888     * Returns whether the device is currently in touch mode.  Touch mode is entered
11889     * once the user begins interacting with the device by touch, and affects various
11890     * things like whether focus is always visible to the user.
11891     *
11892     * @return Whether the device is in touch mode.
11893     */
11894    @ViewDebug.ExportedProperty
11895    public boolean isInTouchMode() {
11896        if (mAttachInfo != null) {
11897            return mAttachInfo.mInTouchMode;
11898        } else {
11899            return ViewRootImpl.isInTouchMode();
11900        }
11901    }
11902
11903    /**
11904     * Returns the context the view is running in, through which it can
11905     * access the current theme, resources, etc.
11906     *
11907     * @return The view's Context.
11908     */
11909    @ViewDebug.CapturedViewProperty
11910    public final Context getContext() {
11911        return mContext;
11912    }
11913
11914    /**
11915     * Handle a key event before it is processed by any input method
11916     * associated with the view hierarchy.  This can be used to intercept
11917     * key events in special situations before the IME consumes them; a
11918     * typical example would be handling the BACK key to update the application's
11919     * UI instead of allowing the IME to see it and close itself.
11920     *
11921     * @param keyCode The value in event.getKeyCode().
11922     * @param event Description of the key event.
11923     * @return If you handled the event, return true. If you want to allow the
11924     *         event to be handled by the next receiver, return false.
11925     */
11926    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11927        return false;
11928    }
11929
11930    /**
11931     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11932     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11933     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11934     * is released, if the view is enabled and clickable.
11935     * <p>
11936     * Key presses in software keyboards will generally NOT trigger this
11937     * listener, although some may elect to do so in some situations. Do not
11938     * rely on this to catch software key presses.
11939     *
11940     * @param keyCode a key code that represents the button pressed, from
11941     *                {@link android.view.KeyEvent}
11942     * @param event the KeyEvent object that defines the button action
11943     */
11944    public boolean onKeyDown(int keyCode, KeyEvent event) {
11945        if (KeyEvent.isConfirmKey(keyCode)) {
11946            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11947                return true;
11948            }
11949
11950            if (event.getRepeatCount() == 0) {
11951                // Long clickable items don't necessarily have to be clickable.
11952                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11953                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11954                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11955                    // For the purposes of menu anchoring and drawable hotspots,
11956                    // key events are considered to be at the center of the view.
11957                    final float x = getWidth() / 2f;
11958                    final float y = getHeight() / 2f;
11959                    if (clickable) {
11960                        setPressed(true, x, y);
11961                    }
11962                    checkForLongClick(0, x, y);
11963                    return true;
11964                }
11965            }
11966        }
11967
11968        return false;
11969    }
11970
11971    /**
11972     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11973     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11974     * the event).
11975     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11976     * although some may elect to do so in some situations. Do not rely on this to
11977     * catch software key presses.
11978     */
11979    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11980        return false;
11981    }
11982
11983    /**
11984     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11985     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11986     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11987     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11988     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11989     * although some may elect to do so in some situations. Do not rely on this to
11990     * catch software key presses.
11991     *
11992     * @param keyCode A key code that represents the button pressed, from
11993     *                {@link android.view.KeyEvent}.
11994     * @param event   The KeyEvent object that defines the button action.
11995     */
11996    public boolean onKeyUp(int keyCode, KeyEvent event) {
11997        if (KeyEvent.isConfirmKey(keyCode)) {
11998            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11999                return true;
12000            }
12001            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12002                setPressed(false);
12003
12004                if (!mHasPerformedLongPress) {
12005                    // This is a tap, so remove the longpress check
12006                    removeLongPressCallback();
12007                    if (!event.isCanceled()) {
12008                        return performClick();
12009                    }
12010                }
12011            }
12012        }
12013        return false;
12014    }
12015
12016    /**
12017     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12018     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12019     * the event).
12020     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12021     * although some may elect to do so in some situations. Do not rely on this to
12022     * catch software key presses.
12023     *
12024     * @param keyCode     A key code that represents the button pressed, from
12025     *                    {@link android.view.KeyEvent}.
12026     * @param repeatCount The number of times the action was made.
12027     * @param event       The KeyEvent object that defines the button action.
12028     */
12029    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12030        return false;
12031    }
12032
12033    /**
12034     * Called on the focused view when a key shortcut event is not handled.
12035     * Override this method to implement local key shortcuts for the View.
12036     * Key shortcuts can also be implemented by setting the
12037     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12038     *
12039     * @param keyCode The value in event.getKeyCode().
12040     * @param event Description of the key event.
12041     * @return If you handled the event, return true. If you want to allow the
12042     *         event to be handled by the next receiver, return false.
12043     */
12044    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12045        return false;
12046    }
12047
12048    /**
12049     * Check whether the called view is a text editor, in which case it
12050     * would make sense to automatically display a soft input window for
12051     * it.  Subclasses should override this if they implement
12052     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12053     * a call on that method would return a non-null InputConnection, and
12054     * they are really a first-class editor that the user would normally
12055     * start typing on when the go into a window containing your view.
12056     *
12057     * <p>The default implementation always returns false.  This does
12058     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12059     * will not be called or the user can not otherwise perform edits on your
12060     * view; it is just a hint to the system that this is not the primary
12061     * purpose of this view.
12062     *
12063     * @return Returns true if this view is a text editor, else false.
12064     */
12065    public boolean onCheckIsTextEditor() {
12066        return false;
12067    }
12068
12069    /**
12070     * Create a new InputConnection for an InputMethod to interact
12071     * with the view.  The default implementation returns null, since it doesn't
12072     * support input methods.  You can override this to implement such support.
12073     * This is only needed for views that take focus and text input.
12074     *
12075     * <p>When implementing this, you probably also want to implement
12076     * {@link #onCheckIsTextEditor()} to indicate you will return a
12077     * non-null InputConnection.</p>
12078     *
12079     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12080     * object correctly and in its entirety, so that the connected IME can rely
12081     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12082     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12083     * must be filled in with the correct cursor position for IMEs to work correctly
12084     * with your application.</p>
12085     *
12086     * @param outAttrs Fill in with attribute information about the connection.
12087     */
12088    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12089        return null;
12090    }
12091
12092    /**
12093     * Called by the {@link android.view.inputmethod.InputMethodManager}
12094     * when a view who is not the current
12095     * input connection target is trying to make a call on the manager.  The
12096     * default implementation returns false; you can override this to return
12097     * true for certain views if you are performing InputConnection proxying
12098     * to them.
12099     * @param view The View that is making the InputMethodManager call.
12100     * @return Return true to allow the call, false to reject.
12101     */
12102    public boolean checkInputConnectionProxy(View view) {
12103        return false;
12104    }
12105
12106    /**
12107     * Show the context menu for this view. It is not safe to hold on to the
12108     * menu after returning from this method.
12109     *
12110     * You should normally not overload this method. Overload
12111     * {@link #onCreateContextMenu(ContextMenu)} or define an
12112     * {@link OnCreateContextMenuListener} to add items to the context menu.
12113     *
12114     * @param menu The context menu to populate
12115     */
12116    public void createContextMenu(ContextMenu menu) {
12117        ContextMenuInfo menuInfo = getContextMenuInfo();
12118
12119        // Sets the current menu info so all items added to menu will have
12120        // my extra info set.
12121        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12122
12123        onCreateContextMenu(menu);
12124        ListenerInfo li = mListenerInfo;
12125        if (li != null && li.mOnCreateContextMenuListener != null) {
12126            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12127        }
12128
12129        // Clear the extra information so subsequent items that aren't mine don't
12130        // have my extra info.
12131        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12132
12133        if (mParent != null) {
12134            mParent.createContextMenu(menu);
12135        }
12136    }
12137
12138    /**
12139     * Views should implement this if they have extra information to associate
12140     * with the context menu. The return result is supplied as a parameter to
12141     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12142     * callback.
12143     *
12144     * @return Extra information about the item for which the context menu
12145     *         should be shown. This information will vary across different
12146     *         subclasses of View.
12147     */
12148    protected ContextMenuInfo getContextMenuInfo() {
12149        return null;
12150    }
12151
12152    /**
12153     * Views should implement this if the view itself is going to add items to
12154     * the context menu.
12155     *
12156     * @param menu the context menu to populate
12157     */
12158    protected void onCreateContextMenu(ContextMenu menu) {
12159    }
12160
12161    /**
12162     * Implement this method to handle trackball motion events.  The
12163     * <em>relative</em> movement of the trackball since the last event
12164     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12165     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12166     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12167     * they will often be fractional values, representing the more fine-grained
12168     * movement information available from a trackball).
12169     *
12170     * @param event The motion event.
12171     * @return True if the event was handled, false otherwise.
12172     */
12173    public boolean onTrackballEvent(MotionEvent event) {
12174        return false;
12175    }
12176
12177    /**
12178     * Implement this method to handle generic motion events.
12179     * <p>
12180     * Generic motion events describe joystick movements, mouse hovers, track pad
12181     * touches, scroll wheel movements and other input events.  The
12182     * {@link MotionEvent#getSource() source} of the motion event specifies
12183     * the class of input that was received.  Implementations of this method
12184     * must examine the bits in the source before processing the event.
12185     * The following code example shows how this is done.
12186     * </p><p>
12187     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12188     * are delivered to the view under the pointer.  All other generic motion events are
12189     * delivered to the focused view.
12190     * </p>
12191     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12192     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12193     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12194     *             // process the joystick movement...
12195     *             return true;
12196     *         }
12197     *     }
12198     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12199     *         switch (event.getAction()) {
12200     *             case MotionEvent.ACTION_HOVER_MOVE:
12201     *                 // process the mouse hover movement...
12202     *                 return true;
12203     *             case MotionEvent.ACTION_SCROLL:
12204     *                 // process the scroll wheel movement...
12205     *                 return true;
12206     *         }
12207     *     }
12208     *     return super.onGenericMotionEvent(event);
12209     * }</pre>
12210     *
12211     * @param event The generic motion event being processed.
12212     * @return True if the event was handled, false otherwise.
12213     */
12214    public boolean onGenericMotionEvent(MotionEvent event) {
12215        return false;
12216    }
12217
12218    /**
12219     * Implement this method to handle hover events.
12220     * <p>
12221     * This method is called whenever a pointer is hovering into, over, or out of the
12222     * bounds of a view and the view is not currently being touched.
12223     * Hover events are represented as pointer events with action
12224     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12225     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12226     * </p>
12227     * <ul>
12228     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12229     * when the pointer enters the bounds of the view.</li>
12230     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12231     * when the pointer has already entered the bounds of the view and has moved.</li>
12232     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12233     * when the pointer has exited the bounds of the view or when the pointer is
12234     * about to go down due to a button click, tap, or similar user action that
12235     * causes the view to be touched.</li>
12236     * </ul>
12237     * <p>
12238     * The view should implement this method to return true to indicate that it is
12239     * handling the hover event, such as by changing its drawable state.
12240     * </p><p>
12241     * The default implementation calls {@link #setHovered} to update the hovered state
12242     * of the view when a hover enter or hover exit event is received, if the view
12243     * is enabled and is clickable.  The default implementation also sends hover
12244     * accessibility events.
12245     * </p>
12246     *
12247     * @param event The motion event that describes the hover.
12248     * @return True if the view handled the hover event.
12249     *
12250     * @see #isHovered
12251     * @see #setHovered
12252     * @see #onHoverChanged
12253     */
12254    public boolean onHoverEvent(MotionEvent event) {
12255        // The root view may receive hover (or touch) events that are outside the bounds of
12256        // the window.  This code ensures that we only send accessibility events for
12257        // hovers that are actually within the bounds of the root view.
12258        final int action = event.getActionMasked();
12259        if (!mSendingHoverAccessibilityEvents) {
12260            if ((action == MotionEvent.ACTION_HOVER_ENTER
12261                    || action == MotionEvent.ACTION_HOVER_MOVE)
12262                    && !hasHoveredChild()
12263                    && pointInView(event.getX(), event.getY())) {
12264                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12265                mSendingHoverAccessibilityEvents = true;
12266            }
12267        } else {
12268            if (action == MotionEvent.ACTION_HOVER_EXIT
12269                    || (action == MotionEvent.ACTION_MOVE
12270                            && !pointInView(event.getX(), event.getY()))) {
12271                mSendingHoverAccessibilityEvents = false;
12272                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12273            }
12274        }
12275
12276        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12277                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12278                && isOnScrollbar(event.getX(), event.getY())) {
12279            awakenScrollBars();
12280        }
12281
12282        // If we consider ourself hoverable, or if we we're already hovered,
12283        // handle changing state in response to ENTER and EXIT events.
12284        if (isHoverable() || isHovered()) {
12285            switch (action) {
12286                case MotionEvent.ACTION_HOVER_ENTER:
12287                    setHovered(true);
12288                    break;
12289                case MotionEvent.ACTION_HOVER_EXIT:
12290                    setHovered(false);
12291                    break;
12292            }
12293
12294            // Dispatch the event to onGenericMotionEvent before returning true.
12295            // This is to provide compatibility with existing applications that
12296            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12297            // break because of the new default handling for hoverable views
12298            // in onHoverEvent.
12299            // Note that onGenericMotionEvent will be called by default when
12300            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12301            dispatchGenericMotionEventInternal(event);
12302            // The event was already handled by calling setHovered(), so always
12303            // return true.
12304            return true;
12305        }
12306
12307        return false;
12308    }
12309
12310    /**
12311     * Returns true if the view should handle {@link #onHoverEvent}
12312     * by calling {@link #setHovered} to change its hovered state.
12313     *
12314     * @return True if the view is hoverable.
12315     */
12316    private boolean isHoverable() {
12317        final int viewFlags = mViewFlags;
12318        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12319            return false;
12320        }
12321
12322        return (viewFlags & CLICKABLE) == CLICKABLE
12323                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12324                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12325    }
12326
12327    /**
12328     * Returns true if the view is currently hovered.
12329     *
12330     * @return True if the view is currently hovered.
12331     *
12332     * @see #setHovered
12333     * @see #onHoverChanged
12334     */
12335    @ViewDebug.ExportedProperty
12336    public boolean isHovered() {
12337        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12338    }
12339
12340    /**
12341     * Sets whether the view is currently hovered.
12342     * <p>
12343     * Calling this method also changes the drawable state of the view.  This
12344     * enables the view to react to hover by using different drawable resources
12345     * to change its appearance.
12346     * </p><p>
12347     * The {@link #onHoverChanged} method is called when the hovered state changes.
12348     * </p>
12349     *
12350     * @param hovered True if the view is hovered.
12351     *
12352     * @see #isHovered
12353     * @see #onHoverChanged
12354     */
12355    public void setHovered(boolean hovered) {
12356        if (hovered) {
12357            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12358                mPrivateFlags |= PFLAG_HOVERED;
12359                refreshDrawableState();
12360                onHoverChanged(true);
12361            }
12362        } else {
12363            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12364                mPrivateFlags &= ~PFLAG_HOVERED;
12365                refreshDrawableState();
12366                onHoverChanged(false);
12367            }
12368        }
12369    }
12370
12371    /**
12372     * Implement this method to handle hover state changes.
12373     * <p>
12374     * This method is called whenever the hover state changes as a result of a
12375     * call to {@link #setHovered}.
12376     * </p>
12377     *
12378     * @param hovered The current hover state, as returned by {@link #isHovered}.
12379     *
12380     * @see #isHovered
12381     * @see #setHovered
12382     */
12383    public void onHoverChanged(boolean hovered) {
12384    }
12385
12386    /**
12387     * Handles scroll bar dragging by mouse input.
12388     *
12389     * @hide
12390     * @param event The motion event.
12391     *
12392     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12393     */
12394    protected boolean handleScrollBarDragging(MotionEvent event) {
12395        if (mScrollCache == null) {
12396            return false;
12397        }
12398        final float x = event.getX();
12399        final float y = event.getY();
12400        final int action = event.getAction();
12401        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12402                && action != MotionEvent.ACTION_DOWN)
12403                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12404                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12405            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12406            return false;
12407        }
12408
12409        switch (action) {
12410            case MotionEvent.ACTION_MOVE:
12411                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12412                    return false;
12413                }
12414                if (mScrollCache.mScrollBarDraggingState
12415                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12416                    final Rect bounds = mScrollCache.mScrollBarBounds;
12417                    getVerticalScrollBarBounds(bounds, null);
12418                    final int range = computeVerticalScrollRange();
12419                    final int offset = computeVerticalScrollOffset();
12420                    final int extent = computeVerticalScrollExtent();
12421
12422                    final int thumbLength = ScrollBarUtils.getThumbLength(
12423                            bounds.height(), bounds.width(), extent, range);
12424                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12425                            bounds.height(), thumbLength, extent, range, offset);
12426
12427                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12428                    final float maxThumbOffset = bounds.height() - thumbLength;
12429                    final float newThumbOffset =
12430                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12431                    final int height = getHeight();
12432                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12433                            && height > 0 && extent > 0) {
12434                        final int newY = Math.round((range - extent)
12435                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12436                        if (newY != getScrollY()) {
12437                            mScrollCache.mScrollBarDraggingPos = y;
12438                            setScrollY(newY);
12439                        }
12440                    }
12441                    return true;
12442                }
12443                if (mScrollCache.mScrollBarDraggingState
12444                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12445                    final Rect bounds = mScrollCache.mScrollBarBounds;
12446                    getHorizontalScrollBarBounds(bounds, null);
12447                    final int range = computeHorizontalScrollRange();
12448                    final int offset = computeHorizontalScrollOffset();
12449                    final int extent = computeHorizontalScrollExtent();
12450
12451                    final int thumbLength = ScrollBarUtils.getThumbLength(
12452                            bounds.width(), bounds.height(), extent, range);
12453                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12454                            bounds.width(), thumbLength, extent, range, offset);
12455
12456                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12457                    final float maxThumbOffset = bounds.width() - thumbLength;
12458                    final float newThumbOffset =
12459                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12460                    final int width = getWidth();
12461                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12462                            && width > 0 && extent > 0) {
12463                        final int newX = Math.round((range - extent)
12464                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12465                        if (newX != getScrollX()) {
12466                            mScrollCache.mScrollBarDraggingPos = x;
12467                            setScrollX(newX);
12468                        }
12469                    }
12470                    return true;
12471                }
12472            case MotionEvent.ACTION_DOWN:
12473                if (mScrollCache.state == ScrollabilityCache.OFF) {
12474                    return false;
12475                }
12476                if (isOnVerticalScrollbarThumb(x, y)) {
12477                    mScrollCache.mScrollBarDraggingState =
12478                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12479                    mScrollCache.mScrollBarDraggingPos = y;
12480                    return true;
12481                }
12482                if (isOnHorizontalScrollbarThumb(x, y)) {
12483                    mScrollCache.mScrollBarDraggingState =
12484                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12485                    mScrollCache.mScrollBarDraggingPos = x;
12486                    return true;
12487                }
12488        }
12489        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12490        return false;
12491    }
12492
12493    /**
12494     * Implement this method to handle touch screen motion events.
12495     * <p>
12496     * If this method is used to detect click actions, it is recommended that
12497     * the actions be performed by implementing and calling
12498     * {@link #performClick()}. This will ensure consistent system behavior,
12499     * including:
12500     * <ul>
12501     * <li>obeying click sound preferences
12502     * <li>dispatching OnClickListener calls
12503     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12504     * accessibility features are enabled
12505     * </ul>
12506     *
12507     * @param event The motion event.
12508     * @return True if the event was handled, false otherwise.
12509     */
12510    public boolean onTouchEvent(MotionEvent event) {
12511        final float x = event.getX();
12512        final float y = event.getY();
12513        final int viewFlags = mViewFlags;
12514        final int action = event.getAction();
12515
12516        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12517                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12518                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12519
12520        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12521            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12522                setPressed(false);
12523            }
12524            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12525            // A disabled view that is clickable still consumes the touch
12526            // events, it just doesn't respond to them.
12527            return clickable;
12528        }
12529        if (mTouchDelegate != null) {
12530            if (mTouchDelegate.onTouchEvent(event)) {
12531                return true;
12532            }
12533        }
12534
12535        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12536            switch (action) {
12537                case MotionEvent.ACTION_UP:
12538                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12539                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12540                        handleTooltipUp();
12541                    }
12542                    if (!clickable) {
12543                        removeTapCallback();
12544                        removeLongPressCallback();
12545                        mInContextButtonPress = false;
12546                        mHasPerformedLongPress = false;
12547                        mIgnoreNextUpEvent = false;
12548                        break;
12549                    }
12550                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12551                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12552                        // take focus if we don't have it already and we should in
12553                        // touch mode.
12554                        boolean focusTaken = false;
12555                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12556                            focusTaken = requestFocus();
12557                        }
12558
12559                        if (prepressed) {
12560                            // The button is being released before we actually
12561                            // showed it as pressed.  Make it show the pressed
12562                            // state now (before scheduling the click) to ensure
12563                            // the user sees it.
12564                            setPressed(true, x, y);
12565                        }
12566
12567                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12568                            // This is a tap, so remove the longpress check
12569                            removeLongPressCallback();
12570
12571                            // Only perform take click actions if we were in the pressed state
12572                            if (!focusTaken) {
12573                                // Use a Runnable and post this rather than calling
12574                                // performClick directly. This lets other visual state
12575                                // of the view update before click actions start.
12576                                if (mPerformClick == null) {
12577                                    mPerformClick = new PerformClick();
12578                                }
12579                                if (!post(mPerformClick)) {
12580                                    performClick();
12581                                }
12582                            }
12583                        }
12584
12585                        if (mUnsetPressedState == null) {
12586                            mUnsetPressedState = new UnsetPressedState();
12587                        }
12588
12589                        if (prepressed) {
12590                            postDelayed(mUnsetPressedState,
12591                                    ViewConfiguration.getPressedStateDuration());
12592                        } else if (!post(mUnsetPressedState)) {
12593                            // If the post failed, unpress right now
12594                            mUnsetPressedState.run();
12595                        }
12596
12597                        removeTapCallback();
12598                    }
12599                    mIgnoreNextUpEvent = false;
12600                    break;
12601
12602                case MotionEvent.ACTION_DOWN:
12603                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12604                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12605                    }
12606                    mHasPerformedLongPress = false;
12607
12608                    if (!clickable) {
12609                        checkForLongClick(0, x, y);
12610                        break;
12611                    }
12612
12613                    if (performButtonActionOnTouchDown(event)) {
12614                        break;
12615                    }
12616
12617                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12618                    boolean isInScrollingContainer = isInScrollingContainer();
12619
12620                    // For views inside a scrolling container, delay the pressed feedback for
12621                    // a short period in case this is a scroll.
12622                    if (isInScrollingContainer) {
12623                        mPrivateFlags |= PFLAG_PREPRESSED;
12624                        if (mPendingCheckForTap == null) {
12625                            mPendingCheckForTap = new CheckForTap();
12626                        }
12627                        mPendingCheckForTap.x = event.getX();
12628                        mPendingCheckForTap.y = event.getY();
12629                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12630                    } else {
12631                        // Not inside a scrolling container, so show the feedback right away
12632                        setPressed(true, x, y);
12633                        checkForLongClick(0, x, y);
12634                    }
12635                    break;
12636
12637                case MotionEvent.ACTION_CANCEL:
12638                    if (clickable) {
12639                        setPressed(false);
12640                    }
12641                    removeTapCallback();
12642                    removeLongPressCallback();
12643                    mInContextButtonPress = false;
12644                    mHasPerformedLongPress = false;
12645                    mIgnoreNextUpEvent = false;
12646                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12647                    break;
12648
12649                case MotionEvent.ACTION_MOVE:
12650                    if (clickable) {
12651                        drawableHotspotChanged(x, y);
12652                    }
12653
12654                    // Be lenient about moving outside of buttons
12655                    if (!pointInView(x, y, mTouchSlop)) {
12656                        // Outside button
12657                        // Remove any future long press/tap checks
12658                        removeTapCallback();
12659                        removeLongPressCallback();
12660                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12661                            setPressed(false);
12662                        }
12663                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12664                    }
12665                    break;
12666            }
12667
12668            return true;
12669        }
12670
12671        return false;
12672    }
12673
12674    /**
12675     * @hide
12676     */
12677    public boolean isInScrollingContainer() {
12678        ViewParent p = getParent();
12679        while (p != null && p instanceof ViewGroup) {
12680            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12681                return true;
12682            }
12683            p = p.getParent();
12684        }
12685        return false;
12686    }
12687
12688    /**
12689     * Remove the longpress detection timer.
12690     */
12691    private void removeLongPressCallback() {
12692        if (mPendingCheckForLongPress != null) {
12693            removeCallbacks(mPendingCheckForLongPress);
12694        }
12695    }
12696
12697    /**
12698     * Remove the pending click action
12699     */
12700    private void removePerformClickCallback() {
12701        if (mPerformClick != null) {
12702            removeCallbacks(mPerformClick);
12703        }
12704    }
12705
12706    /**
12707     * Remove the prepress detection timer.
12708     */
12709    private void removeUnsetPressCallback() {
12710        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12711            setPressed(false);
12712            removeCallbacks(mUnsetPressedState);
12713        }
12714    }
12715
12716    /**
12717     * Remove the tap detection timer.
12718     */
12719    private void removeTapCallback() {
12720        if (mPendingCheckForTap != null) {
12721            mPrivateFlags &= ~PFLAG_PREPRESSED;
12722            removeCallbacks(mPendingCheckForTap);
12723        }
12724    }
12725
12726    /**
12727     * Cancels a pending long press.  Your subclass can use this if you
12728     * want the context menu to come up if the user presses and holds
12729     * at the same place, but you don't want it to come up if they press
12730     * and then move around enough to cause scrolling.
12731     */
12732    public void cancelLongPress() {
12733        removeLongPressCallback();
12734
12735        /*
12736         * The prepressed state handled by the tap callback is a display
12737         * construct, but the tap callback will post a long press callback
12738         * less its own timeout. Remove it here.
12739         */
12740        removeTapCallback();
12741    }
12742
12743    /**
12744     * Remove the pending callback for sending a
12745     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12746     */
12747    private void removeSendViewScrolledAccessibilityEventCallback() {
12748        if (mSendViewScrolledAccessibilityEvent != null) {
12749            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12750            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12751        }
12752    }
12753
12754    /**
12755     * Sets the TouchDelegate for this View.
12756     */
12757    public void setTouchDelegate(TouchDelegate delegate) {
12758        mTouchDelegate = delegate;
12759    }
12760
12761    /**
12762     * Gets the TouchDelegate for this View.
12763     */
12764    public TouchDelegate getTouchDelegate() {
12765        return mTouchDelegate;
12766    }
12767
12768    /**
12769     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12770     *
12771     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12772     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12773     * available. This method should only be called for touch events.
12774     *
12775     * <p class="note">This api is not intended for most applications. Buffered dispatch
12776     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12777     * streams will not improve your input latency. Side effects include: increased latency,
12778     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12779     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12780     * you.</p>
12781     */
12782    public final void requestUnbufferedDispatch(MotionEvent event) {
12783        final int action = event.getAction();
12784        if (mAttachInfo == null
12785                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12786                || !event.isTouchEvent()) {
12787            return;
12788        }
12789        mAttachInfo.mUnbufferedDispatchRequested = true;
12790    }
12791
12792    /**
12793     * Set flags controlling behavior of this view.
12794     *
12795     * @param flags Constant indicating the value which should be set
12796     * @param mask Constant indicating the bit range that should be changed
12797     */
12798    void setFlags(int flags, int mask) {
12799        final boolean accessibilityEnabled =
12800                AccessibilityManager.getInstance(mContext).isEnabled();
12801        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12802
12803        int old = mViewFlags;
12804        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12805
12806        int changed = mViewFlags ^ old;
12807        if (changed == 0) {
12808            return;
12809        }
12810        int privateFlags = mPrivateFlags;
12811
12812        // If focusable is auto, update the FOCUSABLE bit.
12813        int focusableChangedByAuto = 0;
12814        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12815                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12816            // Heuristic only takes into account whether view is clickable.
12817            final int newFocus;
12818            if ((mViewFlags & CLICKABLE) != 0) {
12819                newFocus = FOCUSABLE;
12820            } else {
12821                newFocus = NOT_FOCUSABLE;
12822            }
12823            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12824            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12825            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12826        }
12827
12828        /* Check if the FOCUSABLE bit has changed */
12829        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12830            if (((old & FOCUSABLE) == FOCUSABLE)
12831                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12832                /* Give up focus if we are no longer focusable */
12833                clearFocus();
12834            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12835                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12836                /*
12837                 * Tell the view system that we are now available to take focus
12838                 * if no one else already has it.
12839                 */
12840                if (mParent != null) {
12841                    ViewRootImpl viewRootImpl = getViewRootImpl();
12842                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12843                            || focusableChangedByAuto == 0
12844                            || viewRootImpl == null
12845                            || viewRootImpl.mThread == Thread.currentThread()) {
12846                        mParent.focusableViewAvailable(this);
12847                    }
12848                }
12849            }
12850        }
12851
12852        final int newVisibility = flags & VISIBILITY_MASK;
12853        if (newVisibility == VISIBLE) {
12854            if ((changed & VISIBILITY_MASK) != 0) {
12855                /*
12856                 * If this view is becoming visible, invalidate it in case it changed while
12857                 * it was not visible. Marking it drawn ensures that the invalidation will
12858                 * go through.
12859                 */
12860                mPrivateFlags |= PFLAG_DRAWN;
12861                invalidate(true);
12862
12863                needGlobalAttributesUpdate(true);
12864
12865                // a view becoming visible is worth notifying the parent
12866                // about in case nothing has focus.  even if this specific view
12867                // isn't focusable, it may contain something that is, so let
12868                // the root view try to give this focus if nothing else does.
12869                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12870                    mParent.focusableViewAvailable(this);
12871                }
12872            }
12873        }
12874
12875        /* Check if the GONE bit has changed */
12876        if ((changed & GONE) != 0) {
12877            needGlobalAttributesUpdate(false);
12878            requestLayout();
12879
12880            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12881                if (hasFocus()) clearFocus();
12882                clearAccessibilityFocus();
12883                destroyDrawingCache();
12884                if (mParent instanceof View) {
12885                    // GONE views noop invalidation, so invalidate the parent
12886                    ((View) mParent).invalidate(true);
12887                }
12888                // Mark the view drawn to ensure that it gets invalidated properly the next
12889                // time it is visible and gets invalidated
12890                mPrivateFlags |= PFLAG_DRAWN;
12891            }
12892            if (mAttachInfo != null) {
12893                mAttachInfo.mViewVisibilityChanged = true;
12894            }
12895        }
12896
12897        /* Check if the VISIBLE bit has changed */
12898        if ((changed & INVISIBLE) != 0) {
12899            needGlobalAttributesUpdate(false);
12900            /*
12901             * If this view is becoming invisible, set the DRAWN flag so that
12902             * the next invalidate() will not be skipped.
12903             */
12904            mPrivateFlags |= PFLAG_DRAWN;
12905
12906            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12907                // root view becoming invisible shouldn't clear focus and accessibility focus
12908                if (getRootView() != this) {
12909                    if (hasFocus()) clearFocus();
12910                    clearAccessibilityFocus();
12911                }
12912            }
12913            if (mAttachInfo != null) {
12914                mAttachInfo.mViewVisibilityChanged = true;
12915            }
12916        }
12917
12918        if ((changed & VISIBILITY_MASK) != 0) {
12919            // If the view is invisible, cleanup its display list to free up resources
12920            if (newVisibility != VISIBLE && mAttachInfo != null) {
12921                cleanupDraw();
12922            }
12923
12924            if (mParent instanceof ViewGroup) {
12925                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12926                        (changed & VISIBILITY_MASK), newVisibility);
12927                ((View) mParent).invalidate(true);
12928            } else if (mParent != null) {
12929                mParent.invalidateChild(this, null);
12930            }
12931
12932            if (mAttachInfo != null) {
12933                dispatchVisibilityChanged(this, newVisibility);
12934
12935                // Aggregated visibility changes are dispatched to attached views
12936                // in visible windows where the parent is currently shown/drawn
12937                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12938                // discounting clipping or overlapping. This makes it a good place
12939                // to change animation states.
12940                if (mParent != null && getWindowVisibility() == VISIBLE &&
12941                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12942                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12943                }
12944                notifySubtreeAccessibilityStateChangedIfNeeded();
12945            }
12946        }
12947
12948        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12949            destroyDrawingCache();
12950        }
12951
12952        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12953            destroyDrawingCache();
12954            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12955            invalidateParentCaches();
12956        }
12957
12958        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12959            destroyDrawingCache();
12960            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12961        }
12962
12963        if ((changed & DRAW_MASK) != 0) {
12964            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12965                if (mBackground != null
12966                        || mDefaultFocusHighlight != null
12967                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12968                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12969                } else {
12970                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12971                }
12972            } else {
12973                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12974            }
12975            requestLayout();
12976            invalidate(true);
12977        }
12978
12979        if ((changed & KEEP_SCREEN_ON) != 0) {
12980            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12981                mParent.recomputeViewAttributes(this);
12982            }
12983        }
12984
12985        if (accessibilityEnabled) {
12986            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
12987                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
12988                    || (changed & CONTEXT_CLICKABLE) != 0) {
12989                if (oldIncludeForAccessibility != includeForAccessibility()) {
12990                    notifySubtreeAccessibilityStateChangedIfNeeded();
12991                } else {
12992                    notifyViewAccessibilityStateChangedIfNeeded(
12993                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12994                }
12995            } else if ((changed & ENABLED_MASK) != 0) {
12996                notifyViewAccessibilityStateChangedIfNeeded(
12997                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12998            }
12999        }
13000    }
13001
13002    /**
13003     * Change the view's z order in the tree, so it's on top of other sibling
13004     * views. This ordering change may affect layout, if the parent container
13005     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13006     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13007     * method should be followed by calls to {@link #requestLayout()} and
13008     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13009     * with the new child ordering.
13010     *
13011     * @see ViewGroup#bringChildToFront(View)
13012     */
13013    public void bringToFront() {
13014        if (mParent != null) {
13015            mParent.bringChildToFront(this);
13016        }
13017    }
13018
13019    /**
13020     * This is called in response to an internal scroll in this view (i.e., the
13021     * view scrolled its own contents). This is typically as a result of
13022     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13023     * called.
13024     *
13025     * @param l Current horizontal scroll origin.
13026     * @param t Current vertical scroll origin.
13027     * @param oldl Previous horizontal scroll origin.
13028     * @param oldt Previous vertical scroll origin.
13029     */
13030    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13031        notifySubtreeAccessibilityStateChangedIfNeeded();
13032
13033        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13034            postSendViewScrolledAccessibilityEventCallback();
13035        }
13036
13037        mBackgroundSizeChanged = true;
13038        mDefaultFocusHighlightSizeChanged = true;
13039        if (mForegroundInfo != null) {
13040            mForegroundInfo.mBoundsChanged = true;
13041        }
13042
13043        final AttachInfo ai = mAttachInfo;
13044        if (ai != null) {
13045            ai.mViewScrollChanged = true;
13046        }
13047
13048        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13049            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13050        }
13051    }
13052
13053    /**
13054     * Interface definition for a callback to be invoked when the scroll
13055     * X or Y positions of a view change.
13056     * <p>
13057     * <b>Note:</b> Some views handle scrolling independently from View and may
13058     * have their own separate listeners for scroll-type events. For example,
13059     * {@link android.widget.ListView ListView} allows clients to register an
13060     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13061     * to listen for changes in list scroll position.
13062     *
13063     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13064     */
13065    public interface OnScrollChangeListener {
13066        /**
13067         * Called when the scroll position of a view changes.
13068         *
13069         * @param v The view whose scroll position has changed.
13070         * @param scrollX Current horizontal scroll origin.
13071         * @param scrollY Current vertical scroll origin.
13072         * @param oldScrollX Previous horizontal scroll origin.
13073         * @param oldScrollY Previous vertical scroll origin.
13074         */
13075        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13076    }
13077
13078    /**
13079     * Interface definition for a callback to be invoked when the layout bounds of a view
13080     * changes due to layout processing.
13081     */
13082    public interface OnLayoutChangeListener {
13083        /**
13084         * Called when the layout bounds of a view changes due to layout processing.
13085         *
13086         * @param v The view whose bounds have changed.
13087         * @param left The new value of the view's left property.
13088         * @param top The new value of the view's top property.
13089         * @param right The new value of the view's right property.
13090         * @param bottom The new value of the view's bottom property.
13091         * @param oldLeft The previous value of the view's left property.
13092         * @param oldTop The previous value of the view's top property.
13093         * @param oldRight The previous value of the view's right property.
13094         * @param oldBottom The previous value of the view's bottom property.
13095         */
13096        void onLayoutChange(View v, int left, int top, int right, int bottom,
13097            int oldLeft, int oldTop, int oldRight, int oldBottom);
13098    }
13099
13100    /**
13101     * This is called during layout when the size of this view has changed. If
13102     * you were just added to the view hierarchy, you're called with the old
13103     * values of 0.
13104     *
13105     * @param w Current width of this view.
13106     * @param h Current height of this view.
13107     * @param oldw Old width of this view.
13108     * @param oldh Old height of this view.
13109     */
13110    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13111    }
13112
13113    /**
13114     * Called by draw to draw the child views. This may be overridden
13115     * by derived classes to gain control just before its children are drawn
13116     * (but after its own view has been drawn).
13117     * @param canvas the canvas on which to draw the view
13118     */
13119    protected void dispatchDraw(Canvas canvas) {
13120
13121    }
13122
13123    /**
13124     * Gets the parent of this view. Note that the parent is a
13125     * ViewParent and not necessarily a View.
13126     *
13127     * @return Parent of this view.
13128     */
13129    public final ViewParent getParent() {
13130        return mParent;
13131    }
13132
13133    /**
13134     * Set the horizontal scrolled position of your view. This will cause a call to
13135     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13136     * invalidated.
13137     * @param value the x position to scroll to
13138     */
13139    public void setScrollX(int value) {
13140        scrollTo(value, mScrollY);
13141    }
13142
13143    /**
13144     * Set the vertical scrolled position of your view. This will cause a call to
13145     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13146     * invalidated.
13147     * @param value the y position to scroll to
13148     */
13149    public void setScrollY(int value) {
13150        scrollTo(mScrollX, value);
13151    }
13152
13153    /**
13154     * Return the scrolled left position of this view. This is the left edge of
13155     * the displayed part of your view. You do not need to draw any pixels
13156     * farther left, since those are outside of the frame of your view on
13157     * screen.
13158     *
13159     * @return The left edge of the displayed part of your view, in pixels.
13160     */
13161    public final int getScrollX() {
13162        return mScrollX;
13163    }
13164
13165    /**
13166     * Return the scrolled top position of this view. This is the top edge of
13167     * the displayed part of your view. You do not need to draw any pixels above
13168     * it, since those are outside of the frame of your view on screen.
13169     *
13170     * @return The top edge of the displayed part of your view, in pixels.
13171     */
13172    public final int getScrollY() {
13173        return mScrollY;
13174    }
13175
13176    /**
13177     * Return the width of the your view.
13178     *
13179     * @return The width of your view, in pixels.
13180     */
13181    @ViewDebug.ExportedProperty(category = "layout")
13182    public final int getWidth() {
13183        return mRight - mLeft;
13184    }
13185
13186    /**
13187     * Return the height of your view.
13188     *
13189     * @return The height of your view, in pixels.
13190     */
13191    @ViewDebug.ExportedProperty(category = "layout")
13192    public final int getHeight() {
13193        return mBottom - mTop;
13194    }
13195
13196    /**
13197     * Return the visible drawing bounds of your view. Fills in the output
13198     * rectangle with the values from getScrollX(), getScrollY(),
13199     * getWidth(), and getHeight(). These bounds do not account for any
13200     * transformation properties currently set on the view, such as
13201     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13202     *
13203     * @param outRect The (scrolled) drawing bounds of the view.
13204     */
13205    public void getDrawingRect(Rect outRect) {
13206        outRect.left = mScrollX;
13207        outRect.top = mScrollY;
13208        outRect.right = mScrollX + (mRight - mLeft);
13209        outRect.bottom = mScrollY + (mBottom - mTop);
13210    }
13211
13212    /**
13213     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13214     * raw width component (that is the result is masked by
13215     * {@link #MEASURED_SIZE_MASK}).
13216     *
13217     * @return The raw measured width of this view.
13218     */
13219    public final int getMeasuredWidth() {
13220        return mMeasuredWidth & MEASURED_SIZE_MASK;
13221    }
13222
13223    /**
13224     * Return the full width measurement information for this view as computed
13225     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13226     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13227     * This should be used during measurement and layout calculations only. Use
13228     * {@link #getWidth()} to see how wide a view is after layout.
13229     *
13230     * @return The measured width of this view as a bit mask.
13231     */
13232    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13233            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13234                    name = "MEASURED_STATE_TOO_SMALL"),
13235    })
13236    public final int getMeasuredWidthAndState() {
13237        return mMeasuredWidth;
13238    }
13239
13240    /**
13241     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13242     * raw height component (that is the result is masked by
13243     * {@link #MEASURED_SIZE_MASK}).
13244     *
13245     * @return The raw measured height of this view.
13246     */
13247    public final int getMeasuredHeight() {
13248        return mMeasuredHeight & MEASURED_SIZE_MASK;
13249    }
13250
13251    /**
13252     * Return the full height measurement information for this view as computed
13253     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13254     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13255     * This should be used during measurement and layout calculations only. Use
13256     * {@link #getHeight()} to see how wide a view is after layout.
13257     *
13258     * @return The measured height of this view as a bit mask.
13259     */
13260    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13261            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13262                    name = "MEASURED_STATE_TOO_SMALL"),
13263    })
13264    public final int getMeasuredHeightAndState() {
13265        return mMeasuredHeight;
13266    }
13267
13268    /**
13269     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13270     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13271     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13272     * and the height component is at the shifted bits
13273     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13274     */
13275    public final int getMeasuredState() {
13276        return (mMeasuredWidth&MEASURED_STATE_MASK)
13277                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13278                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13279    }
13280
13281    /**
13282     * The transform matrix of this view, which is calculated based on the current
13283     * rotation, scale, and pivot properties.
13284     *
13285     * @see #getRotation()
13286     * @see #getScaleX()
13287     * @see #getScaleY()
13288     * @see #getPivotX()
13289     * @see #getPivotY()
13290     * @return The current transform matrix for the view
13291     */
13292    public Matrix getMatrix() {
13293        ensureTransformationInfo();
13294        final Matrix matrix = mTransformationInfo.mMatrix;
13295        mRenderNode.getMatrix(matrix);
13296        return matrix;
13297    }
13298
13299    /**
13300     * Returns true if the transform matrix is the identity matrix.
13301     * Recomputes the matrix if necessary.
13302     *
13303     * @return True if the transform matrix is the identity matrix, false otherwise.
13304     */
13305    final boolean hasIdentityMatrix() {
13306        return mRenderNode.hasIdentityMatrix();
13307    }
13308
13309    void ensureTransformationInfo() {
13310        if (mTransformationInfo == null) {
13311            mTransformationInfo = new TransformationInfo();
13312        }
13313    }
13314
13315    /**
13316     * Utility method to retrieve the inverse of the current mMatrix property.
13317     * We cache the matrix to avoid recalculating it when transform properties
13318     * have not changed.
13319     *
13320     * @return The inverse of the current matrix of this view.
13321     * @hide
13322     */
13323    public final Matrix getInverseMatrix() {
13324        ensureTransformationInfo();
13325        if (mTransformationInfo.mInverseMatrix == null) {
13326            mTransformationInfo.mInverseMatrix = new Matrix();
13327        }
13328        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13329        mRenderNode.getInverseMatrix(matrix);
13330        return matrix;
13331    }
13332
13333    /**
13334     * Gets the distance along the Z axis from the camera to this view.
13335     *
13336     * @see #setCameraDistance(float)
13337     *
13338     * @return The distance along the Z axis.
13339     */
13340    public float getCameraDistance() {
13341        final float dpi = mResources.getDisplayMetrics().densityDpi;
13342        return -(mRenderNode.getCameraDistance() * dpi);
13343    }
13344
13345    /**
13346     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13347     * views are drawn) from the camera to this view. The camera's distance
13348     * affects 3D transformations, for instance rotations around the X and Y
13349     * axis. If the rotationX or rotationY properties are changed and this view is
13350     * large (more than half the size of the screen), it is recommended to always
13351     * use a camera distance that's greater than the height (X axis rotation) or
13352     * the width (Y axis rotation) of this view.</p>
13353     *
13354     * <p>The distance of the camera from the view plane can have an affect on the
13355     * perspective distortion of the view when it is rotated around the x or y axis.
13356     * For example, a large distance will result in a large viewing angle, and there
13357     * will not be much perspective distortion of the view as it rotates. A short
13358     * distance may cause much more perspective distortion upon rotation, and can
13359     * also result in some drawing artifacts if the rotated view ends up partially
13360     * behind the camera (which is why the recommendation is to use a distance at
13361     * least as far as the size of the view, if the view is to be rotated.)</p>
13362     *
13363     * <p>The distance is expressed in "depth pixels." The default distance depends
13364     * on the screen density. For instance, on a medium density display, the
13365     * default distance is 1280. On a high density display, the default distance
13366     * is 1920.</p>
13367     *
13368     * <p>If you want to specify a distance that leads to visually consistent
13369     * results across various densities, use the following formula:</p>
13370     * <pre>
13371     * float scale = context.getResources().getDisplayMetrics().density;
13372     * view.setCameraDistance(distance * scale);
13373     * </pre>
13374     *
13375     * <p>The density scale factor of a high density display is 1.5,
13376     * and 1920 = 1280 * 1.5.</p>
13377     *
13378     * @param distance The distance in "depth pixels", if negative the opposite
13379     *        value is used
13380     *
13381     * @see #setRotationX(float)
13382     * @see #setRotationY(float)
13383     */
13384    public void setCameraDistance(float distance) {
13385        final float dpi = mResources.getDisplayMetrics().densityDpi;
13386
13387        invalidateViewProperty(true, false);
13388        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13389        invalidateViewProperty(false, false);
13390
13391        invalidateParentIfNeededAndWasQuickRejected();
13392    }
13393
13394    /**
13395     * The degrees that the view is rotated around the pivot point.
13396     *
13397     * @see #setRotation(float)
13398     * @see #getPivotX()
13399     * @see #getPivotY()
13400     *
13401     * @return The degrees of rotation.
13402     */
13403    @ViewDebug.ExportedProperty(category = "drawing")
13404    public float getRotation() {
13405        return mRenderNode.getRotation();
13406    }
13407
13408    /**
13409     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13410     * result in clockwise rotation.
13411     *
13412     * @param rotation The degrees of rotation.
13413     *
13414     * @see #getRotation()
13415     * @see #getPivotX()
13416     * @see #getPivotY()
13417     * @see #setRotationX(float)
13418     * @see #setRotationY(float)
13419     *
13420     * @attr ref android.R.styleable#View_rotation
13421     */
13422    public void setRotation(float rotation) {
13423        if (rotation != getRotation()) {
13424            // Double-invalidation is necessary to capture view's old and new areas
13425            invalidateViewProperty(true, false);
13426            mRenderNode.setRotation(rotation);
13427            invalidateViewProperty(false, true);
13428
13429            invalidateParentIfNeededAndWasQuickRejected();
13430            notifySubtreeAccessibilityStateChangedIfNeeded();
13431        }
13432    }
13433
13434    /**
13435     * The degrees that the view is rotated around the vertical axis through the pivot point.
13436     *
13437     * @see #getPivotX()
13438     * @see #getPivotY()
13439     * @see #setRotationY(float)
13440     *
13441     * @return The degrees of Y rotation.
13442     */
13443    @ViewDebug.ExportedProperty(category = "drawing")
13444    public float getRotationY() {
13445        return mRenderNode.getRotationY();
13446    }
13447
13448    /**
13449     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13450     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13451     * down the y axis.
13452     *
13453     * When rotating large views, it is recommended to adjust the camera distance
13454     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13455     *
13456     * @param rotationY The degrees of Y rotation.
13457     *
13458     * @see #getRotationY()
13459     * @see #getPivotX()
13460     * @see #getPivotY()
13461     * @see #setRotation(float)
13462     * @see #setRotationX(float)
13463     * @see #setCameraDistance(float)
13464     *
13465     * @attr ref android.R.styleable#View_rotationY
13466     */
13467    public void setRotationY(float rotationY) {
13468        if (rotationY != getRotationY()) {
13469            invalidateViewProperty(true, false);
13470            mRenderNode.setRotationY(rotationY);
13471            invalidateViewProperty(false, true);
13472
13473            invalidateParentIfNeededAndWasQuickRejected();
13474            notifySubtreeAccessibilityStateChangedIfNeeded();
13475        }
13476    }
13477
13478    /**
13479     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13480     *
13481     * @see #getPivotX()
13482     * @see #getPivotY()
13483     * @see #setRotationX(float)
13484     *
13485     * @return The degrees of X rotation.
13486     */
13487    @ViewDebug.ExportedProperty(category = "drawing")
13488    public float getRotationX() {
13489        return mRenderNode.getRotationX();
13490    }
13491
13492    /**
13493     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13494     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13495     * x axis.
13496     *
13497     * When rotating large views, it is recommended to adjust the camera distance
13498     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13499     *
13500     * @param rotationX The degrees of X rotation.
13501     *
13502     * @see #getRotationX()
13503     * @see #getPivotX()
13504     * @see #getPivotY()
13505     * @see #setRotation(float)
13506     * @see #setRotationY(float)
13507     * @see #setCameraDistance(float)
13508     *
13509     * @attr ref android.R.styleable#View_rotationX
13510     */
13511    public void setRotationX(float rotationX) {
13512        if (rotationX != getRotationX()) {
13513            invalidateViewProperty(true, false);
13514            mRenderNode.setRotationX(rotationX);
13515            invalidateViewProperty(false, true);
13516
13517            invalidateParentIfNeededAndWasQuickRejected();
13518            notifySubtreeAccessibilityStateChangedIfNeeded();
13519        }
13520    }
13521
13522    /**
13523     * The amount that the view is scaled in x around the pivot point, as a proportion of
13524     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13525     *
13526     * <p>By default, this is 1.0f.
13527     *
13528     * @see #getPivotX()
13529     * @see #getPivotY()
13530     * @return The scaling factor.
13531     */
13532    @ViewDebug.ExportedProperty(category = "drawing")
13533    public float getScaleX() {
13534        return mRenderNode.getScaleX();
13535    }
13536
13537    /**
13538     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13539     * the view's unscaled width. A value of 1 means that no scaling is applied.
13540     *
13541     * @param scaleX The scaling factor.
13542     * @see #getPivotX()
13543     * @see #getPivotY()
13544     *
13545     * @attr ref android.R.styleable#View_scaleX
13546     */
13547    public void setScaleX(float scaleX) {
13548        if (scaleX != getScaleX()) {
13549            invalidateViewProperty(true, false);
13550            mRenderNode.setScaleX(scaleX);
13551            invalidateViewProperty(false, true);
13552
13553            invalidateParentIfNeededAndWasQuickRejected();
13554            notifySubtreeAccessibilityStateChangedIfNeeded();
13555        }
13556    }
13557
13558    /**
13559     * The amount that the view is scaled in y around the pivot point, as a proportion of
13560     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13561     *
13562     * <p>By default, this is 1.0f.
13563     *
13564     * @see #getPivotX()
13565     * @see #getPivotY()
13566     * @return The scaling factor.
13567     */
13568    @ViewDebug.ExportedProperty(category = "drawing")
13569    public float getScaleY() {
13570        return mRenderNode.getScaleY();
13571    }
13572
13573    /**
13574     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13575     * the view's unscaled width. A value of 1 means that no scaling is applied.
13576     *
13577     * @param scaleY The scaling factor.
13578     * @see #getPivotX()
13579     * @see #getPivotY()
13580     *
13581     * @attr ref android.R.styleable#View_scaleY
13582     */
13583    public void setScaleY(float scaleY) {
13584        if (scaleY != getScaleY()) {
13585            invalidateViewProperty(true, false);
13586            mRenderNode.setScaleY(scaleY);
13587            invalidateViewProperty(false, true);
13588
13589            invalidateParentIfNeededAndWasQuickRejected();
13590            notifySubtreeAccessibilityStateChangedIfNeeded();
13591        }
13592    }
13593
13594    /**
13595     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13596     * and {@link #setScaleX(float) scaled}.
13597     *
13598     * @see #getRotation()
13599     * @see #getScaleX()
13600     * @see #getScaleY()
13601     * @see #getPivotY()
13602     * @return The x location of the pivot point.
13603     *
13604     * @attr ref android.R.styleable#View_transformPivotX
13605     */
13606    @ViewDebug.ExportedProperty(category = "drawing")
13607    public float getPivotX() {
13608        return mRenderNode.getPivotX();
13609    }
13610
13611    /**
13612     * Sets the x location of the point around which the view is
13613     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13614     * By default, the pivot point is centered on the object.
13615     * Setting this property disables this behavior and causes the view to use only the
13616     * explicitly set pivotX and pivotY values.
13617     *
13618     * @param pivotX The x location of the pivot point.
13619     * @see #getRotation()
13620     * @see #getScaleX()
13621     * @see #getScaleY()
13622     * @see #getPivotY()
13623     *
13624     * @attr ref android.R.styleable#View_transformPivotX
13625     */
13626    public void setPivotX(float pivotX) {
13627        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13628            invalidateViewProperty(true, false);
13629            mRenderNode.setPivotX(pivotX);
13630            invalidateViewProperty(false, true);
13631
13632            invalidateParentIfNeededAndWasQuickRejected();
13633        }
13634    }
13635
13636    /**
13637     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13638     * and {@link #setScaleY(float) scaled}.
13639     *
13640     * @see #getRotation()
13641     * @see #getScaleX()
13642     * @see #getScaleY()
13643     * @see #getPivotY()
13644     * @return The y location of the pivot point.
13645     *
13646     * @attr ref android.R.styleable#View_transformPivotY
13647     */
13648    @ViewDebug.ExportedProperty(category = "drawing")
13649    public float getPivotY() {
13650        return mRenderNode.getPivotY();
13651    }
13652
13653    /**
13654     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13655     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13656     * Setting this property disables this behavior and causes the view to use only the
13657     * explicitly set pivotX and pivotY values.
13658     *
13659     * @param pivotY The y location of the pivot point.
13660     * @see #getRotation()
13661     * @see #getScaleX()
13662     * @see #getScaleY()
13663     * @see #getPivotY()
13664     *
13665     * @attr ref android.R.styleable#View_transformPivotY
13666     */
13667    public void setPivotY(float pivotY) {
13668        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13669            invalidateViewProperty(true, false);
13670            mRenderNode.setPivotY(pivotY);
13671            invalidateViewProperty(false, true);
13672
13673            invalidateParentIfNeededAndWasQuickRejected();
13674        }
13675    }
13676
13677    /**
13678     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13679     * completely transparent and 1 means the view is completely opaque.
13680     *
13681     * <p>By default this is 1.0f.
13682     * @return The opacity of the view.
13683     */
13684    @ViewDebug.ExportedProperty(category = "drawing")
13685    public float getAlpha() {
13686        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13687    }
13688
13689    /**
13690     * Sets the behavior for overlapping rendering for this view (see {@link
13691     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13692     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13693     * providing the value which is then used internally. That is, when {@link
13694     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13695     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13696     * instead.
13697     *
13698     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13699     * instead of that returned by {@link #hasOverlappingRendering()}.
13700     *
13701     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13702     */
13703    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13704        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13705        if (hasOverlappingRendering) {
13706            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13707        } else {
13708            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13709        }
13710    }
13711
13712    /**
13713     * Returns the value for overlapping rendering that is used internally. This is either
13714     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13715     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13716     *
13717     * @return The value for overlapping rendering being used internally.
13718     */
13719    public final boolean getHasOverlappingRendering() {
13720        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13721                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13722                hasOverlappingRendering();
13723    }
13724
13725    /**
13726     * Returns whether this View has content which overlaps.
13727     *
13728     * <p>This function, intended to be overridden by specific View types, is an optimization when
13729     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13730     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13731     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13732     * directly. An example of overlapping rendering is a TextView with a background image, such as
13733     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13734     * ImageView with only the foreground image. The default implementation returns true; subclasses
13735     * should override if they have cases which can be optimized.</p>
13736     *
13737     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13738     * necessitates that a View return true if it uses the methods internally without passing the
13739     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13740     *
13741     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13742     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13743     *
13744     * @return true if the content in this view might overlap, false otherwise.
13745     */
13746    @ViewDebug.ExportedProperty(category = "drawing")
13747    public boolean hasOverlappingRendering() {
13748        return true;
13749    }
13750
13751    /**
13752     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13753     * completely transparent and 1 means the view is completely opaque.
13754     *
13755     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13756     * can have significant performance implications, especially for large views. It is best to use
13757     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13758     *
13759     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13760     * strongly recommended for performance reasons to either override
13761     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13762     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13763     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13764     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13765     * of rendering cost, even for simple or small views. Starting with
13766     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13767     * applied to the view at the rendering level.</p>
13768     *
13769     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13770     * responsible for applying the opacity itself.</p>
13771     *
13772     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13773     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13774     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13775     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13776     *
13777     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13778     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13779     * {@link #hasOverlappingRendering}.</p>
13780     *
13781     * @param alpha The opacity of the view.
13782     *
13783     * @see #hasOverlappingRendering()
13784     * @see #setLayerType(int, android.graphics.Paint)
13785     *
13786     * @attr ref android.R.styleable#View_alpha
13787     */
13788    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13789        ensureTransformationInfo();
13790        if (mTransformationInfo.mAlpha != alpha) {
13791            // Report visibility changes, which can affect children, to accessibility
13792            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13793                notifySubtreeAccessibilityStateChangedIfNeeded();
13794            }
13795            mTransformationInfo.mAlpha = alpha;
13796            if (onSetAlpha((int) (alpha * 255))) {
13797                mPrivateFlags |= PFLAG_ALPHA_SET;
13798                // subclass is handling alpha - don't optimize rendering cache invalidation
13799                invalidateParentCaches();
13800                invalidate(true);
13801            } else {
13802                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13803                invalidateViewProperty(true, false);
13804                mRenderNode.setAlpha(getFinalAlpha());
13805            }
13806        }
13807    }
13808
13809    /**
13810     * Faster version of setAlpha() which performs the same steps except there are
13811     * no calls to invalidate(). The caller of this function should perform proper invalidation
13812     * on the parent and this object. The return value indicates whether the subclass handles
13813     * alpha (the return value for onSetAlpha()).
13814     *
13815     * @param alpha The new value for the alpha property
13816     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13817     *         the new value for the alpha property is different from the old value
13818     */
13819    boolean setAlphaNoInvalidation(float alpha) {
13820        ensureTransformationInfo();
13821        if (mTransformationInfo.mAlpha != alpha) {
13822            mTransformationInfo.mAlpha = alpha;
13823            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13824            if (subclassHandlesAlpha) {
13825                mPrivateFlags |= PFLAG_ALPHA_SET;
13826                return true;
13827            } else {
13828                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13829                mRenderNode.setAlpha(getFinalAlpha());
13830            }
13831        }
13832        return false;
13833    }
13834
13835    /**
13836     * This property is hidden and intended only for use by the Fade transition, which
13837     * animates it to produce a visual translucency that does not side-effect (or get
13838     * affected by) the real alpha property. This value is composited with the other
13839     * alpha value (and the AlphaAnimation value, when that is present) to produce
13840     * a final visual translucency result, which is what is passed into the DisplayList.
13841     *
13842     * @hide
13843     */
13844    public void setTransitionAlpha(float alpha) {
13845        ensureTransformationInfo();
13846        if (mTransformationInfo.mTransitionAlpha != alpha) {
13847            mTransformationInfo.mTransitionAlpha = alpha;
13848            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13849            invalidateViewProperty(true, false);
13850            mRenderNode.setAlpha(getFinalAlpha());
13851        }
13852    }
13853
13854    /**
13855     * Calculates the visual alpha of this view, which is a combination of the actual
13856     * alpha value and the transitionAlpha value (if set).
13857     */
13858    private float getFinalAlpha() {
13859        if (mTransformationInfo != null) {
13860            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13861        }
13862        return 1;
13863    }
13864
13865    /**
13866     * This property is hidden and intended only for use by the Fade transition, which
13867     * animates it to produce a visual translucency that does not side-effect (or get
13868     * affected by) the real alpha property. This value is composited with the other
13869     * alpha value (and the AlphaAnimation value, when that is present) to produce
13870     * a final visual translucency result, which is what is passed into the DisplayList.
13871     *
13872     * @hide
13873     */
13874    @ViewDebug.ExportedProperty(category = "drawing")
13875    public float getTransitionAlpha() {
13876        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13877    }
13878
13879    /**
13880     * Top position of this view relative to its parent.
13881     *
13882     * @return The top of this view, in pixels.
13883     */
13884    @ViewDebug.CapturedViewProperty
13885    public final int getTop() {
13886        return mTop;
13887    }
13888
13889    /**
13890     * Sets the top position of this view relative to its parent. This method is meant to be called
13891     * by the layout system and should not generally be called otherwise, because the property
13892     * may be changed at any time by the layout.
13893     *
13894     * @param top The top of this view, in pixels.
13895     */
13896    public final void setTop(int top) {
13897        if (top != mTop) {
13898            final boolean matrixIsIdentity = hasIdentityMatrix();
13899            if (matrixIsIdentity) {
13900                if (mAttachInfo != null) {
13901                    int minTop;
13902                    int yLoc;
13903                    if (top < mTop) {
13904                        minTop = top;
13905                        yLoc = top - mTop;
13906                    } else {
13907                        minTop = mTop;
13908                        yLoc = 0;
13909                    }
13910                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13911                }
13912            } else {
13913                // Double-invalidation is necessary to capture view's old and new areas
13914                invalidate(true);
13915            }
13916
13917            int width = mRight - mLeft;
13918            int oldHeight = mBottom - mTop;
13919
13920            mTop = top;
13921            mRenderNode.setTop(mTop);
13922
13923            sizeChange(width, mBottom - mTop, width, oldHeight);
13924
13925            if (!matrixIsIdentity) {
13926                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13927                invalidate(true);
13928            }
13929            mBackgroundSizeChanged = true;
13930            mDefaultFocusHighlightSizeChanged = true;
13931            if (mForegroundInfo != null) {
13932                mForegroundInfo.mBoundsChanged = true;
13933            }
13934            invalidateParentIfNeeded();
13935            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13936                // View was rejected last time it was drawn by its parent; this may have changed
13937                invalidateParentIfNeeded();
13938            }
13939        }
13940    }
13941
13942    /**
13943     * Bottom position of this view relative to its parent.
13944     *
13945     * @return The bottom of this view, in pixels.
13946     */
13947    @ViewDebug.CapturedViewProperty
13948    public final int getBottom() {
13949        return mBottom;
13950    }
13951
13952    /**
13953     * True if this view has changed since the last time being drawn.
13954     *
13955     * @return The dirty state of this view.
13956     */
13957    public boolean isDirty() {
13958        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13959    }
13960
13961    /**
13962     * Sets the bottom position of this view relative to its parent. This method is meant to be
13963     * called by the layout system and should not generally be called otherwise, because the
13964     * property may be changed at any time by the layout.
13965     *
13966     * @param bottom The bottom of this view, in pixels.
13967     */
13968    public final void setBottom(int bottom) {
13969        if (bottom != mBottom) {
13970            final boolean matrixIsIdentity = hasIdentityMatrix();
13971            if (matrixIsIdentity) {
13972                if (mAttachInfo != null) {
13973                    int maxBottom;
13974                    if (bottom < mBottom) {
13975                        maxBottom = mBottom;
13976                    } else {
13977                        maxBottom = bottom;
13978                    }
13979                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13980                }
13981            } else {
13982                // Double-invalidation is necessary to capture view's old and new areas
13983                invalidate(true);
13984            }
13985
13986            int width = mRight - mLeft;
13987            int oldHeight = mBottom - mTop;
13988
13989            mBottom = bottom;
13990            mRenderNode.setBottom(mBottom);
13991
13992            sizeChange(width, mBottom - mTop, width, oldHeight);
13993
13994            if (!matrixIsIdentity) {
13995                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13996                invalidate(true);
13997            }
13998            mBackgroundSizeChanged = true;
13999            mDefaultFocusHighlightSizeChanged = true;
14000            if (mForegroundInfo != null) {
14001                mForegroundInfo.mBoundsChanged = true;
14002            }
14003            invalidateParentIfNeeded();
14004            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14005                // View was rejected last time it was drawn by its parent; this may have changed
14006                invalidateParentIfNeeded();
14007            }
14008        }
14009    }
14010
14011    /**
14012     * Left position of this view relative to its parent.
14013     *
14014     * @return The left edge of this view, in pixels.
14015     */
14016    @ViewDebug.CapturedViewProperty
14017    public final int getLeft() {
14018        return mLeft;
14019    }
14020
14021    /**
14022     * Sets the left position of this view relative to its parent. This method is meant to be called
14023     * by the layout system and should not generally be called otherwise, because the property
14024     * may be changed at any time by the layout.
14025     *
14026     * @param left The left of this view, in pixels.
14027     */
14028    public final void setLeft(int left) {
14029        if (left != mLeft) {
14030            final boolean matrixIsIdentity = hasIdentityMatrix();
14031            if (matrixIsIdentity) {
14032                if (mAttachInfo != null) {
14033                    int minLeft;
14034                    int xLoc;
14035                    if (left < mLeft) {
14036                        minLeft = left;
14037                        xLoc = left - mLeft;
14038                    } else {
14039                        minLeft = mLeft;
14040                        xLoc = 0;
14041                    }
14042                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14043                }
14044            } else {
14045                // Double-invalidation is necessary to capture view's old and new areas
14046                invalidate(true);
14047            }
14048
14049            int oldWidth = mRight - mLeft;
14050            int height = mBottom - mTop;
14051
14052            mLeft = left;
14053            mRenderNode.setLeft(left);
14054
14055            sizeChange(mRight - mLeft, height, oldWidth, height);
14056
14057            if (!matrixIsIdentity) {
14058                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14059                invalidate(true);
14060            }
14061            mBackgroundSizeChanged = true;
14062            mDefaultFocusHighlightSizeChanged = true;
14063            if (mForegroundInfo != null) {
14064                mForegroundInfo.mBoundsChanged = true;
14065            }
14066            invalidateParentIfNeeded();
14067            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14068                // View was rejected last time it was drawn by its parent; this may have changed
14069                invalidateParentIfNeeded();
14070            }
14071        }
14072    }
14073
14074    /**
14075     * Right position of this view relative to its parent.
14076     *
14077     * @return The right edge of this view, in pixels.
14078     */
14079    @ViewDebug.CapturedViewProperty
14080    public final int getRight() {
14081        return mRight;
14082    }
14083
14084    /**
14085     * Sets the right position of this view relative to its parent. This method is meant to be called
14086     * by the layout system and should not generally be called otherwise, because the property
14087     * may be changed at any time by the layout.
14088     *
14089     * @param right The right of this view, in pixels.
14090     */
14091    public final void setRight(int right) {
14092        if (right != mRight) {
14093            final boolean matrixIsIdentity = hasIdentityMatrix();
14094            if (matrixIsIdentity) {
14095                if (mAttachInfo != null) {
14096                    int maxRight;
14097                    if (right < mRight) {
14098                        maxRight = mRight;
14099                    } else {
14100                        maxRight = right;
14101                    }
14102                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14103                }
14104            } else {
14105                // Double-invalidation is necessary to capture view's old and new areas
14106                invalidate(true);
14107            }
14108
14109            int oldWidth = mRight - mLeft;
14110            int height = mBottom - mTop;
14111
14112            mRight = right;
14113            mRenderNode.setRight(mRight);
14114
14115            sizeChange(mRight - mLeft, height, oldWidth, height);
14116
14117            if (!matrixIsIdentity) {
14118                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14119                invalidate(true);
14120            }
14121            mBackgroundSizeChanged = true;
14122            mDefaultFocusHighlightSizeChanged = true;
14123            if (mForegroundInfo != null) {
14124                mForegroundInfo.mBoundsChanged = true;
14125            }
14126            invalidateParentIfNeeded();
14127            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14128                // View was rejected last time it was drawn by its parent; this may have changed
14129                invalidateParentIfNeeded();
14130            }
14131        }
14132    }
14133
14134    /**
14135     * The visual x position of this view, in pixels. This is equivalent to the
14136     * {@link #setTranslationX(float) translationX} property plus the current
14137     * {@link #getLeft() left} property.
14138     *
14139     * @return The visual x position of this view, in pixels.
14140     */
14141    @ViewDebug.ExportedProperty(category = "drawing")
14142    public float getX() {
14143        return mLeft + getTranslationX();
14144    }
14145
14146    /**
14147     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14148     * {@link #setTranslationX(float) translationX} property to be the difference between
14149     * the x value passed in and the current {@link #getLeft() left} property.
14150     *
14151     * @param x The visual x position of this view, in pixels.
14152     */
14153    public void setX(float x) {
14154        setTranslationX(x - mLeft);
14155    }
14156
14157    /**
14158     * The visual y position of this view, in pixels. This is equivalent to the
14159     * {@link #setTranslationY(float) translationY} property plus the current
14160     * {@link #getTop() top} property.
14161     *
14162     * @return The visual y position of this view, in pixels.
14163     */
14164    @ViewDebug.ExportedProperty(category = "drawing")
14165    public float getY() {
14166        return mTop + getTranslationY();
14167    }
14168
14169    /**
14170     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14171     * {@link #setTranslationY(float) translationY} property to be the difference between
14172     * the y value passed in and the current {@link #getTop() top} property.
14173     *
14174     * @param y The visual y position of this view, in pixels.
14175     */
14176    public void setY(float y) {
14177        setTranslationY(y - mTop);
14178    }
14179
14180    /**
14181     * The visual z position of this view, in pixels. This is equivalent to the
14182     * {@link #setTranslationZ(float) translationZ} property plus the current
14183     * {@link #getElevation() elevation} property.
14184     *
14185     * @return The visual z position of this view, in pixels.
14186     */
14187    @ViewDebug.ExportedProperty(category = "drawing")
14188    public float getZ() {
14189        return getElevation() + getTranslationZ();
14190    }
14191
14192    /**
14193     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14194     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14195     * the x value passed in and the current {@link #getElevation() elevation} property.
14196     *
14197     * @param z The visual z position of this view, in pixels.
14198     */
14199    public void setZ(float z) {
14200        setTranslationZ(z - getElevation());
14201    }
14202
14203    /**
14204     * The base elevation of this view relative to its parent, in pixels.
14205     *
14206     * @return The base depth position of the view, in pixels.
14207     */
14208    @ViewDebug.ExportedProperty(category = "drawing")
14209    public float getElevation() {
14210        return mRenderNode.getElevation();
14211    }
14212
14213    /**
14214     * Sets the base elevation of this view, in pixels.
14215     *
14216     * @attr ref android.R.styleable#View_elevation
14217     */
14218    public void setElevation(float elevation) {
14219        if (elevation != getElevation()) {
14220            invalidateViewProperty(true, false);
14221            mRenderNode.setElevation(elevation);
14222            invalidateViewProperty(false, true);
14223
14224            invalidateParentIfNeededAndWasQuickRejected();
14225        }
14226    }
14227
14228    /**
14229     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14230     * This position is post-layout, in addition to wherever the object's
14231     * layout placed it.
14232     *
14233     * @return The horizontal position of this view relative to its left position, in pixels.
14234     */
14235    @ViewDebug.ExportedProperty(category = "drawing")
14236    public float getTranslationX() {
14237        return mRenderNode.getTranslationX();
14238    }
14239
14240    /**
14241     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14242     * This effectively positions the object post-layout, in addition to wherever the object's
14243     * layout placed it.
14244     *
14245     * @param translationX The horizontal position of this view relative to its left position,
14246     * in pixels.
14247     *
14248     * @attr ref android.R.styleable#View_translationX
14249     */
14250    public void setTranslationX(float translationX) {
14251        if (translationX != getTranslationX()) {
14252            invalidateViewProperty(true, false);
14253            mRenderNode.setTranslationX(translationX);
14254            invalidateViewProperty(false, true);
14255
14256            invalidateParentIfNeededAndWasQuickRejected();
14257            notifySubtreeAccessibilityStateChangedIfNeeded();
14258        }
14259    }
14260
14261    /**
14262     * The vertical location of this view relative to its {@link #getTop() top} position.
14263     * This position is post-layout, in addition to wherever the object's
14264     * layout placed it.
14265     *
14266     * @return The vertical position of this view relative to its top position,
14267     * in pixels.
14268     */
14269    @ViewDebug.ExportedProperty(category = "drawing")
14270    public float getTranslationY() {
14271        return mRenderNode.getTranslationY();
14272    }
14273
14274    /**
14275     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14276     * This effectively positions the object post-layout, in addition to wherever the object's
14277     * layout placed it.
14278     *
14279     * @param translationY The vertical position of this view relative to its top position,
14280     * in pixels.
14281     *
14282     * @attr ref android.R.styleable#View_translationY
14283     */
14284    public void setTranslationY(float translationY) {
14285        if (translationY != getTranslationY()) {
14286            invalidateViewProperty(true, false);
14287            mRenderNode.setTranslationY(translationY);
14288            invalidateViewProperty(false, true);
14289
14290            invalidateParentIfNeededAndWasQuickRejected();
14291            notifySubtreeAccessibilityStateChangedIfNeeded();
14292        }
14293    }
14294
14295    /**
14296     * The depth location of this view relative to its {@link #getElevation() elevation}.
14297     *
14298     * @return The depth of this view relative to its elevation.
14299     */
14300    @ViewDebug.ExportedProperty(category = "drawing")
14301    public float getTranslationZ() {
14302        return mRenderNode.getTranslationZ();
14303    }
14304
14305    /**
14306     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14307     *
14308     * @attr ref android.R.styleable#View_translationZ
14309     */
14310    public void setTranslationZ(float translationZ) {
14311        if (translationZ != getTranslationZ()) {
14312            invalidateViewProperty(true, false);
14313            mRenderNode.setTranslationZ(translationZ);
14314            invalidateViewProperty(false, true);
14315
14316            invalidateParentIfNeededAndWasQuickRejected();
14317        }
14318    }
14319
14320    /** @hide */
14321    public void setAnimationMatrix(Matrix matrix) {
14322        invalidateViewProperty(true, false);
14323        mRenderNode.setAnimationMatrix(matrix);
14324        invalidateViewProperty(false, true);
14325
14326        invalidateParentIfNeededAndWasQuickRejected();
14327    }
14328
14329    /**
14330     * Returns the current StateListAnimator if exists.
14331     *
14332     * @return StateListAnimator or null if it does not exists
14333     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14334     */
14335    public StateListAnimator getStateListAnimator() {
14336        return mStateListAnimator;
14337    }
14338
14339    /**
14340     * Attaches the provided StateListAnimator to this View.
14341     * <p>
14342     * Any previously attached StateListAnimator will be detached.
14343     *
14344     * @param stateListAnimator The StateListAnimator to update the view
14345     * @see android.animation.StateListAnimator
14346     */
14347    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14348        if (mStateListAnimator == stateListAnimator) {
14349            return;
14350        }
14351        if (mStateListAnimator != null) {
14352            mStateListAnimator.setTarget(null);
14353        }
14354        mStateListAnimator = stateListAnimator;
14355        if (stateListAnimator != null) {
14356            stateListAnimator.setTarget(this);
14357            if (isAttachedToWindow()) {
14358                stateListAnimator.setState(getDrawableState());
14359            }
14360        }
14361    }
14362
14363    /**
14364     * Returns whether the Outline should be used to clip the contents of the View.
14365     * <p>
14366     * Note that this flag will only be respected if the View's Outline returns true from
14367     * {@link Outline#canClip()}.
14368     *
14369     * @see #setOutlineProvider(ViewOutlineProvider)
14370     * @see #setClipToOutline(boolean)
14371     */
14372    public final boolean getClipToOutline() {
14373        return mRenderNode.getClipToOutline();
14374    }
14375
14376    /**
14377     * Sets whether the View's Outline should be used to clip the contents of the View.
14378     * <p>
14379     * Only a single non-rectangular clip can be applied on a View at any time.
14380     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14381     * circular reveal} animation take priority over Outline clipping, and
14382     * child Outline clipping takes priority over Outline clipping done by a
14383     * parent.
14384     * <p>
14385     * Note that this flag will only be respected if the View's Outline returns true from
14386     * {@link Outline#canClip()}.
14387     *
14388     * @see #setOutlineProvider(ViewOutlineProvider)
14389     * @see #getClipToOutline()
14390     */
14391    public void setClipToOutline(boolean clipToOutline) {
14392        damageInParent();
14393        if (getClipToOutline() != clipToOutline) {
14394            mRenderNode.setClipToOutline(clipToOutline);
14395        }
14396    }
14397
14398    // correspond to the enum values of View_outlineProvider
14399    private static final int PROVIDER_BACKGROUND = 0;
14400    private static final int PROVIDER_NONE = 1;
14401    private static final int PROVIDER_BOUNDS = 2;
14402    private static final int PROVIDER_PADDED_BOUNDS = 3;
14403    private void setOutlineProviderFromAttribute(int providerInt) {
14404        switch (providerInt) {
14405            case PROVIDER_BACKGROUND:
14406                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14407                break;
14408            case PROVIDER_NONE:
14409                setOutlineProvider(null);
14410                break;
14411            case PROVIDER_BOUNDS:
14412                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14413                break;
14414            case PROVIDER_PADDED_BOUNDS:
14415                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14416                break;
14417        }
14418    }
14419
14420    /**
14421     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14422     * the shape of the shadow it casts, and enables outline clipping.
14423     * <p>
14424     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14425     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14426     * outline provider with this method allows this behavior to be overridden.
14427     * <p>
14428     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14429     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14430     * <p>
14431     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14432     *
14433     * @see #setClipToOutline(boolean)
14434     * @see #getClipToOutline()
14435     * @see #getOutlineProvider()
14436     */
14437    public void setOutlineProvider(ViewOutlineProvider provider) {
14438        mOutlineProvider = provider;
14439        invalidateOutline();
14440    }
14441
14442    /**
14443     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14444     * that defines the shape of the shadow it casts, and enables outline clipping.
14445     *
14446     * @see #setOutlineProvider(ViewOutlineProvider)
14447     */
14448    public ViewOutlineProvider getOutlineProvider() {
14449        return mOutlineProvider;
14450    }
14451
14452    /**
14453     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14454     *
14455     * @see #setOutlineProvider(ViewOutlineProvider)
14456     */
14457    public void invalidateOutline() {
14458        rebuildOutline();
14459
14460        notifySubtreeAccessibilityStateChangedIfNeeded();
14461        invalidateViewProperty(false, false);
14462    }
14463
14464    /**
14465     * Internal version of {@link #invalidateOutline()} which invalidates the
14466     * outline without invalidating the view itself. This is intended to be called from
14467     * within methods in the View class itself which are the result of the view being
14468     * invalidated already. For example, when we are drawing the background of a View,
14469     * we invalidate the outline in case it changed in the meantime, but we do not
14470     * need to invalidate the view because we're already drawing the background as part
14471     * of drawing the view in response to an earlier invalidation of the view.
14472     */
14473    private void rebuildOutline() {
14474        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14475        if (mAttachInfo == null) return;
14476
14477        if (mOutlineProvider == null) {
14478            // no provider, remove outline
14479            mRenderNode.setOutline(null);
14480        } else {
14481            final Outline outline = mAttachInfo.mTmpOutline;
14482            outline.setEmpty();
14483            outline.setAlpha(1.0f);
14484
14485            mOutlineProvider.getOutline(this, outline);
14486            mRenderNode.setOutline(outline);
14487        }
14488    }
14489
14490    /**
14491     * HierarchyViewer only
14492     *
14493     * @hide
14494     */
14495    @ViewDebug.ExportedProperty(category = "drawing")
14496    public boolean hasShadow() {
14497        return mRenderNode.hasShadow();
14498    }
14499
14500
14501    /** @hide */
14502    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14503        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14504        invalidateViewProperty(false, false);
14505    }
14506
14507    /**
14508     * Hit rectangle in parent's coordinates
14509     *
14510     * @param outRect The hit rectangle of the view.
14511     */
14512    public void getHitRect(Rect outRect) {
14513        if (hasIdentityMatrix() || mAttachInfo == null) {
14514            outRect.set(mLeft, mTop, mRight, mBottom);
14515        } else {
14516            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14517            tmpRect.set(0, 0, getWidth(), getHeight());
14518            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14519            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14520                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14521        }
14522    }
14523
14524    /**
14525     * Determines whether the given point, in local coordinates is inside the view.
14526     */
14527    /*package*/ final boolean pointInView(float localX, float localY) {
14528        return pointInView(localX, localY, 0);
14529    }
14530
14531    /**
14532     * Utility method to determine whether the given point, in local coordinates,
14533     * is inside the view, where the area of the view is expanded by the slop factor.
14534     * This method is called while processing touch-move events to determine if the event
14535     * is still within the view.
14536     *
14537     * @hide
14538     */
14539    public boolean pointInView(float localX, float localY, float slop) {
14540        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14541                localY < ((mBottom - mTop) + slop);
14542    }
14543
14544    /**
14545     * When a view has focus and the user navigates away from it, the next view is searched for
14546     * starting from the rectangle filled in by this method.
14547     *
14548     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14549     * of the view.  However, if your view maintains some idea of internal selection,
14550     * such as a cursor, or a selected row or column, you should override this method and
14551     * fill in a more specific rectangle.
14552     *
14553     * @param r The rectangle to fill in, in this view's coordinates.
14554     */
14555    public void getFocusedRect(Rect r) {
14556        getDrawingRect(r);
14557    }
14558
14559    /**
14560     * If some part of this view is not clipped by any of its parents, then
14561     * return that area in r in global (root) coordinates. To convert r to local
14562     * coordinates (without taking possible View rotations into account), offset
14563     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14564     * If the view is completely clipped or translated out, return false.
14565     *
14566     * @param r If true is returned, r holds the global coordinates of the
14567     *        visible portion of this view.
14568     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14569     *        between this view and its root. globalOffet may be null.
14570     * @return true if r is non-empty (i.e. part of the view is visible at the
14571     *         root level.
14572     */
14573    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14574        int width = mRight - mLeft;
14575        int height = mBottom - mTop;
14576        if (width > 0 && height > 0) {
14577            r.set(0, 0, width, height);
14578            if (globalOffset != null) {
14579                globalOffset.set(-mScrollX, -mScrollY);
14580            }
14581            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14582        }
14583        return false;
14584    }
14585
14586    public final boolean getGlobalVisibleRect(Rect r) {
14587        return getGlobalVisibleRect(r, null);
14588    }
14589
14590    public final boolean getLocalVisibleRect(Rect r) {
14591        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14592        if (getGlobalVisibleRect(r, offset)) {
14593            r.offset(-offset.x, -offset.y); // make r local
14594            return true;
14595        }
14596        return false;
14597    }
14598
14599    /**
14600     * Offset this view's vertical location by the specified number of pixels.
14601     *
14602     * @param offset the number of pixels to offset the view by
14603     */
14604    public void offsetTopAndBottom(int offset) {
14605        if (offset != 0) {
14606            final boolean matrixIsIdentity = hasIdentityMatrix();
14607            if (matrixIsIdentity) {
14608                if (isHardwareAccelerated()) {
14609                    invalidateViewProperty(false, false);
14610                } else {
14611                    final ViewParent p = mParent;
14612                    if (p != null && mAttachInfo != null) {
14613                        final Rect r = mAttachInfo.mTmpInvalRect;
14614                        int minTop;
14615                        int maxBottom;
14616                        int yLoc;
14617                        if (offset < 0) {
14618                            minTop = mTop + offset;
14619                            maxBottom = mBottom;
14620                            yLoc = offset;
14621                        } else {
14622                            minTop = mTop;
14623                            maxBottom = mBottom + offset;
14624                            yLoc = 0;
14625                        }
14626                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14627                        p.invalidateChild(this, r);
14628                    }
14629                }
14630            } else {
14631                invalidateViewProperty(false, false);
14632            }
14633
14634            mTop += offset;
14635            mBottom += offset;
14636            mRenderNode.offsetTopAndBottom(offset);
14637            if (isHardwareAccelerated()) {
14638                invalidateViewProperty(false, false);
14639                invalidateParentIfNeededAndWasQuickRejected();
14640            } else {
14641                if (!matrixIsIdentity) {
14642                    invalidateViewProperty(false, true);
14643                }
14644                invalidateParentIfNeeded();
14645            }
14646            notifySubtreeAccessibilityStateChangedIfNeeded();
14647        }
14648    }
14649
14650    /**
14651     * Offset this view's horizontal location by the specified amount of pixels.
14652     *
14653     * @param offset the number of pixels to offset the view by
14654     */
14655    public void offsetLeftAndRight(int offset) {
14656        if (offset != 0) {
14657            final boolean matrixIsIdentity = hasIdentityMatrix();
14658            if (matrixIsIdentity) {
14659                if (isHardwareAccelerated()) {
14660                    invalidateViewProperty(false, false);
14661                } else {
14662                    final ViewParent p = mParent;
14663                    if (p != null && mAttachInfo != null) {
14664                        final Rect r = mAttachInfo.mTmpInvalRect;
14665                        int minLeft;
14666                        int maxRight;
14667                        if (offset < 0) {
14668                            minLeft = mLeft + offset;
14669                            maxRight = mRight;
14670                        } else {
14671                            minLeft = mLeft;
14672                            maxRight = mRight + offset;
14673                        }
14674                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14675                        p.invalidateChild(this, r);
14676                    }
14677                }
14678            } else {
14679                invalidateViewProperty(false, false);
14680            }
14681
14682            mLeft += offset;
14683            mRight += offset;
14684            mRenderNode.offsetLeftAndRight(offset);
14685            if (isHardwareAccelerated()) {
14686                invalidateViewProperty(false, false);
14687                invalidateParentIfNeededAndWasQuickRejected();
14688            } else {
14689                if (!matrixIsIdentity) {
14690                    invalidateViewProperty(false, true);
14691                }
14692                invalidateParentIfNeeded();
14693            }
14694            notifySubtreeAccessibilityStateChangedIfNeeded();
14695        }
14696    }
14697
14698    /**
14699     * Get the LayoutParams associated with this view. All views should have
14700     * layout parameters. These supply parameters to the <i>parent</i> of this
14701     * view specifying how it should be arranged. There are many subclasses of
14702     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14703     * of ViewGroup that are responsible for arranging their children.
14704     *
14705     * This method may return null if this View is not attached to a parent
14706     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14707     * was not invoked successfully. When a View is attached to a parent
14708     * ViewGroup, this method must not return null.
14709     *
14710     * @return The LayoutParams associated with this view, or null if no
14711     *         parameters have been set yet
14712     */
14713    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14714    public ViewGroup.LayoutParams getLayoutParams() {
14715        return mLayoutParams;
14716    }
14717
14718    /**
14719     * Set the layout parameters associated with this view. These supply
14720     * parameters to the <i>parent</i> of this view specifying how it should be
14721     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14722     * correspond to the different subclasses of ViewGroup that are responsible
14723     * for arranging their children.
14724     *
14725     * @param params The layout parameters for this view, cannot be null
14726     */
14727    public void setLayoutParams(ViewGroup.LayoutParams params) {
14728        if (params == null) {
14729            throw new NullPointerException("Layout parameters cannot be null");
14730        }
14731        mLayoutParams = params;
14732        resolveLayoutParams();
14733        if (mParent instanceof ViewGroup) {
14734            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14735        }
14736        requestLayout();
14737    }
14738
14739    /**
14740     * Resolve the layout parameters depending on the resolved layout direction
14741     *
14742     * @hide
14743     */
14744    public void resolveLayoutParams() {
14745        if (mLayoutParams != null) {
14746            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14747        }
14748    }
14749
14750    /**
14751     * Set the scrolled position of your view. This will cause a call to
14752     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14753     * invalidated.
14754     * @param x the x position to scroll to
14755     * @param y the y position to scroll to
14756     */
14757    public void scrollTo(int x, int y) {
14758        if (mScrollX != x || mScrollY != y) {
14759            int oldX = mScrollX;
14760            int oldY = mScrollY;
14761            mScrollX = x;
14762            mScrollY = y;
14763            invalidateParentCaches();
14764            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14765            if (!awakenScrollBars()) {
14766                postInvalidateOnAnimation();
14767            }
14768        }
14769    }
14770
14771    /**
14772     * Move the scrolled position of your view. This will cause a call to
14773     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14774     * invalidated.
14775     * @param x the amount of pixels to scroll by horizontally
14776     * @param y the amount of pixels to scroll by vertically
14777     */
14778    public void scrollBy(int x, int y) {
14779        scrollTo(mScrollX + x, mScrollY + y);
14780    }
14781
14782    /**
14783     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14784     * animation to fade the scrollbars out after a default delay. If a subclass
14785     * provides animated scrolling, the start delay should equal the duration
14786     * of the scrolling animation.</p>
14787     *
14788     * <p>The animation starts only if at least one of the scrollbars is
14789     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14790     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14791     * this method returns true, and false otherwise. If the animation is
14792     * started, this method calls {@link #invalidate()}; in that case the
14793     * caller should not call {@link #invalidate()}.</p>
14794     *
14795     * <p>This method should be invoked every time a subclass directly updates
14796     * the scroll parameters.</p>
14797     *
14798     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14799     * and {@link #scrollTo(int, int)}.</p>
14800     *
14801     * @return true if the animation is played, false otherwise
14802     *
14803     * @see #awakenScrollBars(int)
14804     * @see #scrollBy(int, int)
14805     * @see #scrollTo(int, int)
14806     * @see #isHorizontalScrollBarEnabled()
14807     * @see #isVerticalScrollBarEnabled()
14808     * @see #setHorizontalScrollBarEnabled(boolean)
14809     * @see #setVerticalScrollBarEnabled(boolean)
14810     */
14811    protected boolean awakenScrollBars() {
14812        return mScrollCache != null &&
14813                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14814    }
14815
14816    /**
14817     * Trigger the scrollbars to draw.
14818     * This method differs from awakenScrollBars() only in its default duration.
14819     * initialAwakenScrollBars() will show the scroll bars for longer than
14820     * usual to give the user more of a chance to notice them.
14821     *
14822     * @return true if the animation is played, false otherwise.
14823     */
14824    private boolean initialAwakenScrollBars() {
14825        return mScrollCache != null &&
14826                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14827    }
14828
14829    /**
14830     * <p>
14831     * Trigger the scrollbars to draw. When invoked this method starts an
14832     * animation to fade the scrollbars out after a fixed delay. If a subclass
14833     * provides animated scrolling, the start delay should equal the duration of
14834     * the scrolling animation.
14835     * </p>
14836     *
14837     * <p>
14838     * The animation starts only if at least one of the scrollbars is enabled,
14839     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14840     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14841     * this method returns true, and false otherwise. If the animation is
14842     * started, this method calls {@link #invalidate()}; in that case the caller
14843     * should not call {@link #invalidate()}.
14844     * </p>
14845     *
14846     * <p>
14847     * This method should be invoked every time a subclass directly updates the
14848     * scroll parameters.
14849     * </p>
14850     *
14851     * @param startDelay the delay, in milliseconds, after which the animation
14852     *        should start; when the delay is 0, the animation starts
14853     *        immediately
14854     * @return true if the animation is played, false otherwise
14855     *
14856     * @see #scrollBy(int, int)
14857     * @see #scrollTo(int, int)
14858     * @see #isHorizontalScrollBarEnabled()
14859     * @see #isVerticalScrollBarEnabled()
14860     * @see #setHorizontalScrollBarEnabled(boolean)
14861     * @see #setVerticalScrollBarEnabled(boolean)
14862     */
14863    protected boolean awakenScrollBars(int startDelay) {
14864        return awakenScrollBars(startDelay, true);
14865    }
14866
14867    /**
14868     * <p>
14869     * Trigger the scrollbars to draw. When invoked this method starts an
14870     * animation to fade the scrollbars out after a fixed delay. If a subclass
14871     * provides animated scrolling, the start delay should equal the duration of
14872     * the scrolling animation.
14873     * </p>
14874     *
14875     * <p>
14876     * The animation starts only if at least one of the scrollbars is enabled,
14877     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14878     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14879     * this method returns true, and false otherwise. If the animation is
14880     * started, this method calls {@link #invalidate()} if the invalidate parameter
14881     * is set to true; in that case the caller
14882     * should not call {@link #invalidate()}.
14883     * </p>
14884     *
14885     * <p>
14886     * This method should be invoked every time a subclass directly updates the
14887     * scroll parameters.
14888     * </p>
14889     *
14890     * @param startDelay the delay, in milliseconds, after which the animation
14891     *        should start; when the delay is 0, the animation starts
14892     *        immediately
14893     *
14894     * @param invalidate Whether this method should call invalidate
14895     *
14896     * @return true if the animation is played, false otherwise
14897     *
14898     * @see #scrollBy(int, int)
14899     * @see #scrollTo(int, int)
14900     * @see #isHorizontalScrollBarEnabled()
14901     * @see #isVerticalScrollBarEnabled()
14902     * @see #setHorizontalScrollBarEnabled(boolean)
14903     * @see #setVerticalScrollBarEnabled(boolean)
14904     */
14905    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14906        final ScrollabilityCache scrollCache = mScrollCache;
14907
14908        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14909            return false;
14910        }
14911
14912        if (scrollCache.scrollBar == null) {
14913            scrollCache.scrollBar = new ScrollBarDrawable();
14914            scrollCache.scrollBar.setState(getDrawableState());
14915            scrollCache.scrollBar.setCallback(this);
14916        }
14917
14918        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14919
14920            if (invalidate) {
14921                // Invalidate to show the scrollbars
14922                postInvalidateOnAnimation();
14923            }
14924
14925            if (scrollCache.state == ScrollabilityCache.OFF) {
14926                // FIXME: this is copied from WindowManagerService.
14927                // We should get this value from the system when it
14928                // is possible to do so.
14929                final int KEY_REPEAT_FIRST_DELAY = 750;
14930                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14931            }
14932
14933            // Tell mScrollCache when we should start fading. This may
14934            // extend the fade start time if one was already scheduled
14935            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14936            scrollCache.fadeStartTime = fadeStartTime;
14937            scrollCache.state = ScrollabilityCache.ON;
14938
14939            // Schedule our fader to run, unscheduling any old ones first
14940            if (mAttachInfo != null) {
14941                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14942                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14943            }
14944
14945            return true;
14946        }
14947
14948        return false;
14949    }
14950
14951    /**
14952     * Do not invalidate views which are not visible and which are not running an animation. They
14953     * will not get drawn and they should not set dirty flags as if they will be drawn
14954     */
14955    private boolean skipInvalidate() {
14956        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14957                (!(mParent instanceof ViewGroup) ||
14958                        !((ViewGroup) mParent).isViewTransitioning(this));
14959    }
14960
14961    /**
14962     * Mark the area defined by dirty as needing to be drawn. If the view is
14963     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14964     * point in the future.
14965     * <p>
14966     * This must be called from a UI thread. To call from a non-UI thread, call
14967     * {@link #postInvalidate()}.
14968     * <p>
14969     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14970     * {@code dirty}.
14971     *
14972     * @param dirty the rectangle representing the bounds of the dirty region
14973     */
14974    public void invalidate(Rect dirty) {
14975        final int scrollX = mScrollX;
14976        final int scrollY = mScrollY;
14977        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14978                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14979    }
14980
14981    /**
14982     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
14983     * coordinates of the dirty rect are relative to the view. If the view is
14984     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14985     * point in the future.
14986     * <p>
14987     * This must be called from a UI thread. To call from a non-UI thread, call
14988     * {@link #postInvalidate()}.
14989     *
14990     * @param l the left position of the dirty region
14991     * @param t the top position of the dirty region
14992     * @param r the right position of the dirty region
14993     * @param b the bottom position of the dirty region
14994     */
14995    public void invalidate(int l, int t, int r, int b) {
14996        final int scrollX = mScrollX;
14997        final int scrollY = mScrollY;
14998        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14999    }
15000
15001    /**
15002     * Invalidate the whole view. If the view is visible,
15003     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15004     * the future.
15005     * <p>
15006     * This must be called from a UI thread. To call from a non-UI thread, call
15007     * {@link #postInvalidate()}.
15008     */
15009    public void invalidate() {
15010        invalidate(true);
15011    }
15012
15013    /**
15014     * This is where the invalidate() work actually happens. A full invalidate()
15015     * causes the drawing cache to be invalidated, but this function can be
15016     * called with invalidateCache set to false to skip that invalidation step
15017     * for cases that do not need it (for example, a component that remains at
15018     * the same dimensions with the same content).
15019     *
15020     * @param invalidateCache Whether the drawing cache for this view should be
15021     *            invalidated as well. This is usually true for a full
15022     *            invalidate, but may be set to false if the View's contents or
15023     *            dimensions have not changed.
15024     * @hide
15025     */
15026    public void invalidate(boolean invalidateCache) {
15027        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15028    }
15029
15030    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15031            boolean fullInvalidate) {
15032        if (mGhostView != null) {
15033            mGhostView.invalidate(true);
15034            return;
15035        }
15036
15037        if (skipInvalidate()) {
15038            return;
15039        }
15040
15041        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15042                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15043                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15044                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15045            if (fullInvalidate) {
15046                mLastIsOpaque = isOpaque();
15047                mPrivateFlags &= ~PFLAG_DRAWN;
15048            }
15049
15050            mPrivateFlags |= PFLAG_DIRTY;
15051
15052            if (invalidateCache) {
15053                mPrivateFlags |= PFLAG_INVALIDATED;
15054                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15055            }
15056
15057            // Propagate the damage rectangle to the parent view.
15058            final AttachInfo ai = mAttachInfo;
15059            final ViewParent p = mParent;
15060            if (p != null && ai != null && l < r && t < b) {
15061                final Rect damage = ai.mTmpInvalRect;
15062                damage.set(l, t, r, b);
15063                p.invalidateChild(this, damage);
15064            }
15065
15066            // Damage the entire projection receiver, if necessary.
15067            if (mBackground != null && mBackground.isProjected()) {
15068                final View receiver = getProjectionReceiver();
15069                if (receiver != null) {
15070                    receiver.damageInParent();
15071                }
15072            }
15073        }
15074    }
15075
15076    /**
15077     * @return this view's projection receiver, or {@code null} if none exists
15078     */
15079    private View getProjectionReceiver() {
15080        ViewParent p = getParent();
15081        while (p != null && p instanceof View) {
15082            final View v = (View) p;
15083            if (v.isProjectionReceiver()) {
15084                return v;
15085            }
15086            p = p.getParent();
15087        }
15088
15089        return null;
15090    }
15091
15092    /**
15093     * @return whether the view is a projection receiver
15094     */
15095    private boolean isProjectionReceiver() {
15096        return mBackground != null;
15097    }
15098
15099    /**
15100     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15101     * set any flags or handle all of the cases handled by the default invalidation methods.
15102     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15103     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15104     * walk up the hierarchy, transforming the dirty rect as necessary.
15105     *
15106     * The method also handles normal invalidation logic if display list properties are not
15107     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15108     * backup approach, to handle these cases used in the various property-setting methods.
15109     *
15110     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15111     * are not being used in this view
15112     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15113     * list properties are not being used in this view
15114     */
15115    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15116        if (!isHardwareAccelerated()
15117                || !mRenderNode.isValid()
15118                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15119            if (invalidateParent) {
15120                invalidateParentCaches();
15121            }
15122            if (forceRedraw) {
15123                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15124            }
15125            invalidate(false);
15126        } else {
15127            damageInParent();
15128        }
15129    }
15130
15131    /**
15132     * Tells the parent view to damage this view's bounds.
15133     *
15134     * @hide
15135     */
15136    protected void damageInParent() {
15137        if (mParent != null && mAttachInfo != null) {
15138            mParent.onDescendantInvalidated(this, this);
15139        }
15140    }
15141
15142    /**
15143     * Utility method to transform a given Rect by the current matrix of this view.
15144     */
15145    void transformRect(final Rect rect) {
15146        if (!getMatrix().isIdentity()) {
15147            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15148            boundingRect.set(rect);
15149            getMatrix().mapRect(boundingRect);
15150            rect.set((int) Math.floor(boundingRect.left),
15151                    (int) Math.floor(boundingRect.top),
15152                    (int) Math.ceil(boundingRect.right),
15153                    (int) Math.ceil(boundingRect.bottom));
15154        }
15155    }
15156
15157    /**
15158     * Used to indicate that the parent of this view should clear its caches. This functionality
15159     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15160     * which is necessary when various parent-managed properties of the view change, such as
15161     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15162     * clears the parent caches and does not causes an invalidate event.
15163     *
15164     * @hide
15165     */
15166    protected void invalidateParentCaches() {
15167        if (mParent instanceof View) {
15168            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15169        }
15170    }
15171
15172    /**
15173     * Used to indicate that the parent of this view should be invalidated. This functionality
15174     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15175     * which is necessary when various parent-managed properties of the view change, such as
15176     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15177     * an invalidation event to the parent.
15178     *
15179     * @hide
15180     */
15181    protected void invalidateParentIfNeeded() {
15182        if (isHardwareAccelerated() && mParent instanceof View) {
15183            ((View) mParent).invalidate(true);
15184        }
15185    }
15186
15187    /**
15188     * @hide
15189     */
15190    protected void invalidateParentIfNeededAndWasQuickRejected() {
15191        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15192            // View was rejected last time it was drawn by its parent; this may have changed
15193            invalidateParentIfNeeded();
15194        }
15195    }
15196
15197    /**
15198     * Indicates whether this View is opaque. An opaque View guarantees that it will
15199     * draw all the pixels overlapping its bounds using a fully opaque color.
15200     *
15201     * Subclasses of View should override this method whenever possible to indicate
15202     * whether an instance is opaque. Opaque Views are treated in a special way by
15203     * the View hierarchy, possibly allowing it to perform optimizations during
15204     * invalidate/draw passes.
15205     *
15206     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15207     */
15208    @ViewDebug.ExportedProperty(category = "drawing")
15209    public boolean isOpaque() {
15210        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15211                getFinalAlpha() >= 1.0f;
15212    }
15213
15214    /**
15215     * @hide
15216     */
15217    protected void computeOpaqueFlags() {
15218        // Opaque if:
15219        //   - Has a background
15220        //   - Background is opaque
15221        //   - Doesn't have scrollbars or scrollbars overlay
15222
15223        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15224            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15225        } else {
15226            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15227        }
15228
15229        final int flags = mViewFlags;
15230        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15231                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15232                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15233            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15234        } else {
15235            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15236        }
15237    }
15238
15239    /**
15240     * @hide
15241     */
15242    protected boolean hasOpaqueScrollbars() {
15243        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15244    }
15245
15246    /**
15247     * @return A handler associated with the thread running the View. This
15248     * handler can be used to pump events in the UI events queue.
15249     */
15250    public Handler getHandler() {
15251        final AttachInfo attachInfo = mAttachInfo;
15252        if (attachInfo != null) {
15253            return attachInfo.mHandler;
15254        }
15255        return null;
15256    }
15257
15258    /**
15259     * Returns the queue of runnable for this view.
15260     *
15261     * @return the queue of runnables for this view
15262     */
15263    private HandlerActionQueue getRunQueue() {
15264        if (mRunQueue == null) {
15265            mRunQueue = new HandlerActionQueue();
15266        }
15267        return mRunQueue;
15268    }
15269
15270    /**
15271     * Gets the view root associated with the View.
15272     * @return The view root, or null if none.
15273     * @hide
15274     */
15275    public ViewRootImpl getViewRootImpl() {
15276        if (mAttachInfo != null) {
15277            return mAttachInfo.mViewRootImpl;
15278        }
15279        return null;
15280    }
15281
15282    /**
15283     * @hide
15284     */
15285    public ThreadedRenderer getThreadedRenderer() {
15286        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15287    }
15288
15289    /**
15290     * <p>Causes the Runnable to be added to the message queue.
15291     * The runnable will be run on the user interface thread.</p>
15292     *
15293     * @param action The Runnable that will be executed.
15294     *
15295     * @return Returns true if the Runnable was successfully placed in to the
15296     *         message queue.  Returns false on failure, usually because the
15297     *         looper processing the message queue is exiting.
15298     *
15299     * @see #postDelayed
15300     * @see #removeCallbacks
15301     */
15302    public boolean post(Runnable action) {
15303        final AttachInfo attachInfo = mAttachInfo;
15304        if (attachInfo != null) {
15305            return attachInfo.mHandler.post(action);
15306        }
15307
15308        // Postpone the runnable until we know on which thread it needs to run.
15309        // Assume that the runnable will be successfully placed after attach.
15310        getRunQueue().post(action);
15311        return true;
15312    }
15313
15314    /**
15315     * <p>Causes the Runnable to be added to the message queue, to be run
15316     * after the specified amount of time elapses.
15317     * The runnable will be run on the user interface thread.</p>
15318     *
15319     * @param action The Runnable that will be executed.
15320     * @param delayMillis The delay (in milliseconds) until the Runnable
15321     *        will be executed.
15322     *
15323     * @return true if the Runnable was successfully placed in to the
15324     *         message queue.  Returns false on failure, usually because the
15325     *         looper processing the message queue is exiting.  Note that a
15326     *         result of true does not mean the Runnable will be processed --
15327     *         if the looper is quit before the delivery time of the message
15328     *         occurs then the message will be dropped.
15329     *
15330     * @see #post
15331     * @see #removeCallbacks
15332     */
15333    public boolean postDelayed(Runnable action, long delayMillis) {
15334        final AttachInfo attachInfo = mAttachInfo;
15335        if (attachInfo != null) {
15336            return attachInfo.mHandler.postDelayed(action, delayMillis);
15337        }
15338
15339        // Postpone the runnable until we know on which thread it needs to run.
15340        // Assume that the runnable will be successfully placed after attach.
15341        getRunQueue().postDelayed(action, delayMillis);
15342        return true;
15343    }
15344
15345    /**
15346     * <p>Causes the Runnable to execute on the next animation time step.
15347     * The runnable will be run on the user interface thread.</p>
15348     *
15349     * @param action The Runnable that will be executed.
15350     *
15351     * @see #postOnAnimationDelayed
15352     * @see #removeCallbacks
15353     */
15354    public void postOnAnimation(Runnable action) {
15355        final AttachInfo attachInfo = mAttachInfo;
15356        if (attachInfo != null) {
15357            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15358                    Choreographer.CALLBACK_ANIMATION, action, null);
15359        } else {
15360            // Postpone the runnable until we know
15361            // on which thread it needs to run.
15362            getRunQueue().post(action);
15363        }
15364    }
15365
15366    /**
15367     * <p>Causes the Runnable to execute on the next animation time step,
15368     * after the specified amount of time elapses.
15369     * The runnable will be run on the user interface thread.</p>
15370     *
15371     * @param action The Runnable that will be executed.
15372     * @param delayMillis The delay (in milliseconds) until the Runnable
15373     *        will be executed.
15374     *
15375     * @see #postOnAnimation
15376     * @see #removeCallbacks
15377     */
15378    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15379        final AttachInfo attachInfo = mAttachInfo;
15380        if (attachInfo != null) {
15381            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15382                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15383        } else {
15384            // Postpone the runnable until we know
15385            // on which thread it needs to run.
15386            getRunQueue().postDelayed(action, delayMillis);
15387        }
15388    }
15389
15390    /**
15391     * <p>Removes the specified Runnable from the message queue.</p>
15392     *
15393     * @param action The Runnable to remove from the message handling queue
15394     *
15395     * @return true if this view could ask the Handler to remove the Runnable,
15396     *         false otherwise. When the returned value is true, the Runnable
15397     *         may or may not have been actually removed from the message queue
15398     *         (for instance, if the Runnable was not in the queue already.)
15399     *
15400     * @see #post
15401     * @see #postDelayed
15402     * @see #postOnAnimation
15403     * @see #postOnAnimationDelayed
15404     */
15405    public boolean removeCallbacks(Runnable action) {
15406        if (action != null) {
15407            final AttachInfo attachInfo = mAttachInfo;
15408            if (attachInfo != null) {
15409                attachInfo.mHandler.removeCallbacks(action);
15410                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15411                        Choreographer.CALLBACK_ANIMATION, action, null);
15412            }
15413            getRunQueue().removeCallbacks(action);
15414        }
15415        return true;
15416    }
15417
15418    /**
15419     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15420     * Use this to invalidate the View from a non-UI thread.</p>
15421     *
15422     * <p>This method can be invoked from outside of the UI thread
15423     * only when this View is attached to a window.</p>
15424     *
15425     * @see #invalidate()
15426     * @see #postInvalidateDelayed(long)
15427     */
15428    public void postInvalidate() {
15429        postInvalidateDelayed(0);
15430    }
15431
15432    /**
15433     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15434     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15435     *
15436     * <p>This method can be invoked from outside of the UI thread
15437     * only when this View is attached to a window.</p>
15438     *
15439     * @param left The left coordinate of the rectangle to invalidate.
15440     * @param top The top coordinate of the rectangle to invalidate.
15441     * @param right The right coordinate of the rectangle to invalidate.
15442     * @param bottom The bottom coordinate of the rectangle to invalidate.
15443     *
15444     * @see #invalidate(int, int, int, int)
15445     * @see #invalidate(Rect)
15446     * @see #postInvalidateDelayed(long, int, int, int, int)
15447     */
15448    public void postInvalidate(int left, int top, int right, int bottom) {
15449        postInvalidateDelayed(0, left, top, right, bottom);
15450    }
15451
15452    /**
15453     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15454     * loop. Waits for the specified amount of time.</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 delayMilliseconds the duration in milliseconds to delay the
15460     *         invalidation by
15461     *
15462     * @see #invalidate()
15463     * @see #postInvalidate()
15464     */
15465    public void postInvalidateDelayed(long delayMilliseconds) {
15466        // We try only with the AttachInfo because there's no point in invalidating
15467        // if we are not attached to our window
15468        final AttachInfo attachInfo = mAttachInfo;
15469        if (attachInfo != null) {
15470            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15471        }
15472    }
15473
15474    /**
15475     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15476     * through the event loop. Waits for the specified amount of time.</p>
15477     *
15478     * <p>This method can be invoked from outside of the UI thread
15479     * only when this View is attached to a window.</p>
15480     *
15481     * @param delayMilliseconds the duration in milliseconds to delay the
15482     *         invalidation by
15483     * @param left The left coordinate of the rectangle to invalidate.
15484     * @param top The top coordinate of the rectangle to invalidate.
15485     * @param right The right coordinate of the rectangle to invalidate.
15486     * @param bottom The bottom coordinate of the rectangle to invalidate.
15487     *
15488     * @see #invalidate(int, int, int, int)
15489     * @see #invalidate(Rect)
15490     * @see #postInvalidate(int, int, int, int)
15491     */
15492    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15493            int right, int bottom) {
15494
15495        // We try only with the AttachInfo because there's no point in invalidating
15496        // if we are not attached to our window
15497        final AttachInfo attachInfo = mAttachInfo;
15498        if (attachInfo != null) {
15499            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15500            info.target = this;
15501            info.left = left;
15502            info.top = top;
15503            info.right = right;
15504            info.bottom = bottom;
15505
15506            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15507        }
15508    }
15509
15510    /**
15511     * <p>Cause an invalidate to happen on the next animation time step, typically the
15512     * next display frame.</p>
15513     *
15514     * <p>This method can be invoked from outside of the UI thread
15515     * only when this View is attached to a window.</p>
15516     *
15517     * @see #invalidate()
15518     */
15519    public void postInvalidateOnAnimation() {
15520        // We try only with the AttachInfo because there's no point in invalidating
15521        // if we are not attached to our window
15522        final AttachInfo attachInfo = mAttachInfo;
15523        if (attachInfo != null) {
15524            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15525        }
15526    }
15527
15528    /**
15529     * <p>Cause an invalidate of the specified area to happen on the next animation
15530     * time step, typically the next display frame.</p>
15531     *
15532     * <p>This method can be invoked from outside of the UI thread
15533     * only when this View is attached to a window.</p>
15534     *
15535     * @param left The left coordinate of the rectangle to invalidate.
15536     * @param top The top coordinate of the rectangle to invalidate.
15537     * @param right The right coordinate of the rectangle to invalidate.
15538     * @param bottom The bottom coordinate of the rectangle to invalidate.
15539     *
15540     * @see #invalidate(int, int, int, int)
15541     * @see #invalidate(Rect)
15542     */
15543    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15544        // We try only with the AttachInfo because there's no point in invalidating
15545        // if we are not attached to our window
15546        final AttachInfo attachInfo = mAttachInfo;
15547        if (attachInfo != null) {
15548            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15549            info.target = this;
15550            info.left = left;
15551            info.top = top;
15552            info.right = right;
15553            info.bottom = bottom;
15554
15555            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15556        }
15557    }
15558
15559    /**
15560     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15561     * This event is sent at most once every
15562     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15563     */
15564    private void postSendViewScrolledAccessibilityEventCallback() {
15565        if (mSendViewScrolledAccessibilityEvent == null) {
15566            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15567        }
15568        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15569            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15570            postDelayed(mSendViewScrolledAccessibilityEvent,
15571                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15572        }
15573    }
15574
15575    /**
15576     * Called by a parent to request that a child update its values for mScrollX
15577     * and mScrollY if necessary. This will typically be done if the child is
15578     * animating a scroll using a {@link android.widget.Scroller Scroller}
15579     * object.
15580     */
15581    public void computeScroll() {
15582    }
15583
15584    /**
15585     * <p>Indicate whether the horizontal edges are faded when the view is
15586     * scrolled horizontally.</p>
15587     *
15588     * @return true if the horizontal edges should are faded on scroll, false
15589     *         otherwise
15590     *
15591     * @see #setHorizontalFadingEdgeEnabled(boolean)
15592     *
15593     * @attr ref android.R.styleable#View_requiresFadingEdge
15594     */
15595    public boolean isHorizontalFadingEdgeEnabled() {
15596        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15597    }
15598
15599    /**
15600     * <p>Define whether the horizontal edges should be faded when this view
15601     * is scrolled horizontally.</p>
15602     *
15603     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15604     *                                    be faded when the view is scrolled
15605     *                                    horizontally
15606     *
15607     * @see #isHorizontalFadingEdgeEnabled()
15608     *
15609     * @attr ref android.R.styleable#View_requiresFadingEdge
15610     */
15611    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15612        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15613            if (horizontalFadingEdgeEnabled) {
15614                initScrollCache();
15615            }
15616
15617            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15618        }
15619    }
15620
15621    /**
15622     * <p>Indicate whether the vertical edges are faded when the view is
15623     * scrolled horizontally.</p>
15624     *
15625     * @return true if the vertical edges should are faded on scroll, false
15626     *         otherwise
15627     *
15628     * @see #setVerticalFadingEdgeEnabled(boolean)
15629     *
15630     * @attr ref android.R.styleable#View_requiresFadingEdge
15631     */
15632    public boolean isVerticalFadingEdgeEnabled() {
15633        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15634    }
15635
15636    /**
15637     * <p>Define whether the vertical edges should be faded when this view
15638     * is scrolled vertically.</p>
15639     *
15640     * @param verticalFadingEdgeEnabled true if the vertical edges should
15641     *                                  be faded when the view is scrolled
15642     *                                  vertically
15643     *
15644     * @see #isVerticalFadingEdgeEnabled()
15645     *
15646     * @attr ref android.R.styleable#View_requiresFadingEdge
15647     */
15648    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15649        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15650            if (verticalFadingEdgeEnabled) {
15651                initScrollCache();
15652            }
15653
15654            mViewFlags ^= FADING_EDGE_VERTICAL;
15655        }
15656    }
15657
15658    /**
15659     * Returns the strength, or intensity, of the top faded edge. The strength is
15660     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15661     * returns 0.0 or 1.0 but no value in between.
15662     *
15663     * Subclasses should override this method to provide a smoother fade transition
15664     * when scrolling occurs.
15665     *
15666     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15667     */
15668    protected float getTopFadingEdgeStrength() {
15669        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15670    }
15671
15672    /**
15673     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15674     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15675     * returns 0.0 or 1.0 but no value in between.
15676     *
15677     * Subclasses should override this method to provide a smoother fade transition
15678     * when scrolling occurs.
15679     *
15680     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15681     */
15682    protected float getBottomFadingEdgeStrength() {
15683        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15684                computeVerticalScrollRange() ? 1.0f : 0.0f;
15685    }
15686
15687    /**
15688     * Returns the strength, or intensity, of the left faded edge. The strength is
15689     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15690     * returns 0.0 or 1.0 but no value in between.
15691     *
15692     * Subclasses should override this method to provide a smoother fade transition
15693     * when scrolling occurs.
15694     *
15695     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15696     */
15697    protected float getLeftFadingEdgeStrength() {
15698        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15699    }
15700
15701    /**
15702     * Returns the strength, or intensity, of the right faded edge. The strength is
15703     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15704     * returns 0.0 or 1.0 but no value in between.
15705     *
15706     * Subclasses should override this method to provide a smoother fade transition
15707     * when scrolling occurs.
15708     *
15709     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15710     */
15711    protected float getRightFadingEdgeStrength() {
15712        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15713                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15714    }
15715
15716    /**
15717     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15718     * scrollbar is not drawn by default.</p>
15719     *
15720     * @return true if the horizontal scrollbar should be painted, false
15721     *         otherwise
15722     *
15723     * @see #setHorizontalScrollBarEnabled(boolean)
15724     */
15725    public boolean isHorizontalScrollBarEnabled() {
15726        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15727    }
15728
15729    /**
15730     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15731     * scrollbar is not drawn by default.</p>
15732     *
15733     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15734     *                                   be painted
15735     *
15736     * @see #isHorizontalScrollBarEnabled()
15737     */
15738    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15739        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15740            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15741            computeOpaqueFlags();
15742            resolvePadding();
15743        }
15744    }
15745
15746    /**
15747     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15748     * scrollbar is not drawn by default.</p>
15749     *
15750     * @return true if the vertical scrollbar should be painted, false
15751     *         otherwise
15752     *
15753     * @see #setVerticalScrollBarEnabled(boolean)
15754     */
15755    public boolean isVerticalScrollBarEnabled() {
15756        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15757    }
15758
15759    /**
15760     * <p>Define whether the vertical scrollbar should be drawn or not. The
15761     * scrollbar is not drawn by default.</p>
15762     *
15763     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15764     *                                 be painted
15765     *
15766     * @see #isVerticalScrollBarEnabled()
15767     */
15768    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15769        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15770            mViewFlags ^= SCROLLBARS_VERTICAL;
15771            computeOpaqueFlags();
15772            resolvePadding();
15773        }
15774    }
15775
15776    /**
15777     * @hide
15778     */
15779    protected void recomputePadding() {
15780        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15781    }
15782
15783    /**
15784     * Define whether scrollbars will fade when the view is not scrolling.
15785     *
15786     * @param fadeScrollbars whether to enable fading
15787     *
15788     * @attr ref android.R.styleable#View_fadeScrollbars
15789     */
15790    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15791        initScrollCache();
15792        final ScrollabilityCache scrollabilityCache = mScrollCache;
15793        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15794        if (fadeScrollbars) {
15795            scrollabilityCache.state = ScrollabilityCache.OFF;
15796        } else {
15797            scrollabilityCache.state = ScrollabilityCache.ON;
15798        }
15799    }
15800
15801    /**
15802     *
15803     * Returns true if scrollbars will fade when this view is not scrolling
15804     *
15805     * @return true if scrollbar fading is enabled
15806     *
15807     * @attr ref android.R.styleable#View_fadeScrollbars
15808     */
15809    public boolean isScrollbarFadingEnabled() {
15810        return mScrollCache != null && mScrollCache.fadeScrollBars;
15811    }
15812
15813    /**
15814     *
15815     * Returns the delay before scrollbars fade.
15816     *
15817     * @return the delay before scrollbars fade
15818     *
15819     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15820     */
15821    public int getScrollBarDefaultDelayBeforeFade() {
15822        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15823                mScrollCache.scrollBarDefaultDelayBeforeFade;
15824    }
15825
15826    /**
15827     * Define the delay before scrollbars fade.
15828     *
15829     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15830     *
15831     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15832     */
15833    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15834        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15835    }
15836
15837    /**
15838     *
15839     * Returns the scrollbar fade duration.
15840     *
15841     * @return the scrollbar fade duration, in milliseconds
15842     *
15843     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15844     */
15845    public int getScrollBarFadeDuration() {
15846        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15847                mScrollCache.scrollBarFadeDuration;
15848    }
15849
15850    /**
15851     * Define the scrollbar fade duration.
15852     *
15853     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15854     *
15855     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15856     */
15857    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15858        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15859    }
15860
15861    /**
15862     *
15863     * Returns the scrollbar size.
15864     *
15865     * @return the scrollbar size
15866     *
15867     * @attr ref android.R.styleable#View_scrollbarSize
15868     */
15869    public int getScrollBarSize() {
15870        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15871                mScrollCache.scrollBarSize;
15872    }
15873
15874    /**
15875     * Define the scrollbar size.
15876     *
15877     * @param scrollBarSize - the scrollbar size
15878     *
15879     * @attr ref android.R.styleable#View_scrollbarSize
15880     */
15881    public void setScrollBarSize(int scrollBarSize) {
15882        getScrollCache().scrollBarSize = scrollBarSize;
15883    }
15884
15885    /**
15886     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15887     * inset. When inset, they add to the padding of the view. And the scrollbars
15888     * can be drawn inside the padding area or on the edge of the view. For example,
15889     * if a view has a background drawable and you want to draw the scrollbars
15890     * inside the padding specified by the drawable, you can use
15891     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15892     * appear at the edge of the view, ignoring the padding, then you can use
15893     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15894     * @param style the style of the scrollbars. Should be one of
15895     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15896     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15897     * @see #SCROLLBARS_INSIDE_OVERLAY
15898     * @see #SCROLLBARS_INSIDE_INSET
15899     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15900     * @see #SCROLLBARS_OUTSIDE_INSET
15901     *
15902     * @attr ref android.R.styleable#View_scrollbarStyle
15903     */
15904    public void setScrollBarStyle(@ScrollBarStyle int style) {
15905        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15906            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15907            computeOpaqueFlags();
15908            resolvePadding();
15909        }
15910    }
15911
15912    /**
15913     * <p>Returns the current scrollbar style.</p>
15914     * @return the current scrollbar style
15915     * @see #SCROLLBARS_INSIDE_OVERLAY
15916     * @see #SCROLLBARS_INSIDE_INSET
15917     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15918     * @see #SCROLLBARS_OUTSIDE_INSET
15919     *
15920     * @attr ref android.R.styleable#View_scrollbarStyle
15921     */
15922    @ViewDebug.ExportedProperty(mapping = {
15923            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15924            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15925            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15926            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15927    })
15928    @ScrollBarStyle
15929    public int getScrollBarStyle() {
15930        return mViewFlags & SCROLLBARS_STYLE_MASK;
15931    }
15932
15933    /**
15934     * <p>Compute the horizontal range that the horizontal scrollbar
15935     * represents.</p>
15936     *
15937     * <p>The range is expressed in arbitrary units that must be the same as the
15938     * units used by {@link #computeHorizontalScrollExtent()} and
15939     * {@link #computeHorizontalScrollOffset()}.</p>
15940     *
15941     * <p>The default range is the drawing width of this view.</p>
15942     *
15943     * @return the total horizontal range represented by the horizontal
15944     *         scrollbar
15945     *
15946     * @see #computeHorizontalScrollExtent()
15947     * @see #computeHorizontalScrollOffset()
15948     * @see android.widget.ScrollBarDrawable
15949     */
15950    protected int computeHorizontalScrollRange() {
15951        return getWidth();
15952    }
15953
15954    /**
15955     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15956     * within the horizontal range. This value is used to compute the position
15957     * of the thumb within the scrollbar's track.</p>
15958     *
15959     * <p>The range is expressed in arbitrary units that must be the same as the
15960     * units used by {@link #computeHorizontalScrollRange()} and
15961     * {@link #computeHorizontalScrollExtent()}.</p>
15962     *
15963     * <p>The default offset is the scroll offset of this view.</p>
15964     *
15965     * @return the horizontal offset of the scrollbar's thumb
15966     *
15967     * @see #computeHorizontalScrollRange()
15968     * @see #computeHorizontalScrollExtent()
15969     * @see android.widget.ScrollBarDrawable
15970     */
15971    protected int computeHorizontalScrollOffset() {
15972        return mScrollX;
15973    }
15974
15975    /**
15976     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15977     * within the horizontal range. This value is used to compute the length
15978     * of the thumb within the scrollbar's track.</p>
15979     *
15980     * <p>The range is expressed in arbitrary units that must be the same as the
15981     * units used by {@link #computeHorizontalScrollRange()} and
15982     * {@link #computeHorizontalScrollOffset()}.</p>
15983     *
15984     * <p>The default extent is the drawing width of this view.</p>
15985     *
15986     * @return the horizontal extent of the scrollbar's thumb
15987     *
15988     * @see #computeHorizontalScrollRange()
15989     * @see #computeHorizontalScrollOffset()
15990     * @see android.widget.ScrollBarDrawable
15991     */
15992    protected int computeHorizontalScrollExtent() {
15993        return getWidth();
15994    }
15995
15996    /**
15997     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15998     *
15999     * <p>The range is expressed in arbitrary units that must be the same as the
16000     * units used by {@link #computeVerticalScrollExtent()} and
16001     * {@link #computeVerticalScrollOffset()}.</p>
16002     *
16003     * @return the total vertical range represented by the vertical scrollbar
16004     *
16005     * <p>The default range is the drawing height of this view.</p>
16006     *
16007     * @see #computeVerticalScrollExtent()
16008     * @see #computeVerticalScrollOffset()
16009     * @see android.widget.ScrollBarDrawable
16010     */
16011    protected int computeVerticalScrollRange() {
16012        return getHeight();
16013    }
16014
16015    /**
16016     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16017     * within the horizontal range. This value is used to compute the position
16018     * of the thumb within the scrollbar's track.</p>
16019     *
16020     * <p>The range is expressed in arbitrary units that must be the same as the
16021     * units used by {@link #computeVerticalScrollRange()} and
16022     * {@link #computeVerticalScrollExtent()}.</p>
16023     *
16024     * <p>The default offset is the scroll offset of this view.</p>
16025     *
16026     * @return the vertical offset of the scrollbar's thumb
16027     *
16028     * @see #computeVerticalScrollRange()
16029     * @see #computeVerticalScrollExtent()
16030     * @see android.widget.ScrollBarDrawable
16031     */
16032    protected int computeVerticalScrollOffset() {
16033        return mScrollY;
16034    }
16035
16036    /**
16037     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16038     * within the vertical range. This value is used to compute the length
16039     * of the thumb within the scrollbar's track.</p>
16040     *
16041     * <p>The range is expressed in arbitrary units that must be the same as the
16042     * units used by {@link #computeVerticalScrollRange()} and
16043     * {@link #computeVerticalScrollOffset()}.</p>
16044     *
16045     * <p>The default extent is the drawing height of this view.</p>
16046     *
16047     * @return the vertical extent of the scrollbar's thumb
16048     *
16049     * @see #computeVerticalScrollRange()
16050     * @see #computeVerticalScrollOffset()
16051     * @see android.widget.ScrollBarDrawable
16052     */
16053    protected int computeVerticalScrollExtent() {
16054        return getHeight();
16055    }
16056
16057    /**
16058     * Check if this view can be scrolled horizontally in a certain direction.
16059     *
16060     * @param direction Negative to check scrolling left, positive to check scrolling right.
16061     * @return true if this view can be scrolled in the specified direction, false otherwise.
16062     */
16063    public boolean canScrollHorizontally(int direction) {
16064        final int offset = computeHorizontalScrollOffset();
16065        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16066        if (range == 0) return false;
16067        if (direction < 0) {
16068            return offset > 0;
16069        } else {
16070            return offset < range - 1;
16071        }
16072    }
16073
16074    /**
16075     * Check if this view can be scrolled vertically in a certain direction.
16076     *
16077     * @param direction Negative to check scrolling up, positive to check scrolling down.
16078     * @return true if this view can be scrolled in the specified direction, false otherwise.
16079     */
16080    public boolean canScrollVertically(int direction) {
16081        final int offset = computeVerticalScrollOffset();
16082        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16083        if (range == 0) return false;
16084        if (direction < 0) {
16085            return offset > 0;
16086        } else {
16087            return offset < range - 1;
16088        }
16089    }
16090
16091    void getScrollIndicatorBounds(@NonNull Rect out) {
16092        out.left = mScrollX;
16093        out.right = mScrollX + mRight - mLeft;
16094        out.top = mScrollY;
16095        out.bottom = mScrollY + mBottom - mTop;
16096    }
16097
16098    private void onDrawScrollIndicators(Canvas c) {
16099        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16100            // No scroll indicators enabled.
16101            return;
16102        }
16103
16104        final Drawable dr = mScrollIndicatorDrawable;
16105        if (dr == null) {
16106            // Scroll indicators aren't supported here.
16107            return;
16108        }
16109
16110        final int h = dr.getIntrinsicHeight();
16111        final int w = dr.getIntrinsicWidth();
16112        final Rect rect = mAttachInfo.mTmpInvalRect;
16113        getScrollIndicatorBounds(rect);
16114
16115        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16116            final boolean canScrollUp = canScrollVertically(-1);
16117            if (canScrollUp) {
16118                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16119                dr.draw(c);
16120            }
16121        }
16122
16123        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16124            final boolean canScrollDown = canScrollVertically(1);
16125            if (canScrollDown) {
16126                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16127                dr.draw(c);
16128            }
16129        }
16130
16131        final int leftRtl;
16132        final int rightRtl;
16133        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16134            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16135            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16136        } else {
16137            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16138            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16139        }
16140
16141        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16142        if ((mPrivateFlags3 & leftMask) != 0) {
16143            final boolean canScrollLeft = canScrollHorizontally(-1);
16144            if (canScrollLeft) {
16145                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16146                dr.draw(c);
16147            }
16148        }
16149
16150        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16151        if ((mPrivateFlags3 & rightMask) != 0) {
16152            final boolean canScrollRight = canScrollHorizontally(1);
16153            if (canScrollRight) {
16154                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16155                dr.draw(c);
16156            }
16157        }
16158    }
16159
16160    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16161            @Nullable Rect touchBounds) {
16162        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16163        if (bounds == null) {
16164            return;
16165        }
16166        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16167        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16168                && !isVerticalScrollBarHidden();
16169        final int size = getHorizontalScrollbarHeight();
16170        final int verticalScrollBarGap = drawVerticalScrollBar ?
16171                getVerticalScrollbarWidth() : 0;
16172        final int width = mRight - mLeft;
16173        final int height = mBottom - mTop;
16174        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16175        bounds.left = mScrollX + (mPaddingLeft & inside);
16176        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16177        bounds.bottom = bounds.top + size;
16178
16179        if (touchBounds == null) {
16180            return;
16181        }
16182        if (touchBounds != bounds) {
16183            touchBounds.set(bounds);
16184        }
16185        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16186        if (touchBounds.height() < minTouchTarget) {
16187            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16188            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16189            touchBounds.top = touchBounds.bottom - minTouchTarget;
16190        }
16191        if (touchBounds.width() < minTouchTarget) {
16192            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16193            touchBounds.left -= adjust;
16194            touchBounds.right = touchBounds.left + minTouchTarget;
16195        }
16196    }
16197
16198    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16199        if (mRoundScrollbarRenderer == null) {
16200            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16201        } else {
16202            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16203        }
16204    }
16205
16206    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16207        final int width = mRight - mLeft;
16208        final int height = mBottom - mTop;
16209        // Do not take padding into account as we always want the scrollbars
16210        // to hug the screen for round wearable devices.
16211        bounds.left = mScrollX;
16212        bounds.top = mScrollY;
16213        bounds.right = bounds.left + width;
16214        bounds.bottom = mScrollY + height;
16215    }
16216
16217    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16218            @Nullable Rect touchBounds) {
16219        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16220        if (bounds == null) {
16221            return;
16222        }
16223        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16224        final int size = getVerticalScrollbarWidth();
16225        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16226        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16227            verticalScrollbarPosition = isLayoutRtl() ?
16228                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16229        }
16230        final int width = mRight - mLeft;
16231        final int height = mBottom - mTop;
16232        switch (verticalScrollbarPosition) {
16233            default:
16234            case SCROLLBAR_POSITION_RIGHT:
16235                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16236                break;
16237            case SCROLLBAR_POSITION_LEFT:
16238                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16239                break;
16240        }
16241        bounds.top = mScrollY + (mPaddingTop & inside);
16242        bounds.right = bounds.left + size;
16243        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16244
16245        if (touchBounds == null) {
16246            return;
16247        }
16248        if (touchBounds != bounds) {
16249            touchBounds.set(bounds);
16250        }
16251        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16252        if (touchBounds.width() < minTouchTarget) {
16253            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16254            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16255                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16256                touchBounds.left = touchBounds.right - minTouchTarget;
16257            } else {
16258                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16259                touchBounds.right = touchBounds.left + minTouchTarget;
16260            }
16261        }
16262        if (touchBounds.height() < minTouchTarget) {
16263            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16264            touchBounds.top -= adjust;
16265            touchBounds.bottom = touchBounds.top + minTouchTarget;
16266        }
16267    }
16268
16269    /**
16270     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16271     * scrollbars are painted only if they have been awakened first.</p>
16272     *
16273     * @param canvas the canvas on which to draw the scrollbars
16274     *
16275     * @see #awakenScrollBars(int)
16276     */
16277    protected final void onDrawScrollBars(Canvas canvas) {
16278        // scrollbars are drawn only when the animation is running
16279        final ScrollabilityCache cache = mScrollCache;
16280
16281        if (cache != null) {
16282
16283            int state = cache.state;
16284
16285            if (state == ScrollabilityCache.OFF) {
16286                return;
16287            }
16288
16289            boolean invalidate = false;
16290
16291            if (state == ScrollabilityCache.FADING) {
16292                // We're fading -- get our fade interpolation
16293                if (cache.interpolatorValues == null) {
16294                    cache.interpolatorValues = new float[1];
16295                }
16296
16297                float[] values = cache.interpolatorValues;
16298
16299                // Stops the animation if we're done
16300                if (cache.scrollBarInterpolator.timeToValues(values) ==
16301                        Interpolator.Result.FREEZE_END) {
16302                    cache.state = ScrollabilityCache.OFF;
16303                } else {
16304                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16305                }
16306
16307                // This will make the scroll bars inval themselves after
16308                // drawing. We only want this when we're fading so that
16309                // we prevent excessive redraws
16310                invalidate = true;
16311            } else {
16312                // We're just on -- but we may have been fading before so
16313                // reset alpha
16314                cache.scrollBar.mutate().setAlpha(255);
16315            }
16316
16317            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16318            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16319                    && !isVerticalScrollBarHidden();
16320
16321            // Fork out the scroll bar drawing for round wearable devices.
16322            if (mRoundScrollbarRenderer != null) {
16323                if (drawVerticalScrollBar) {
16324                    final Rect bounds = cache.mScrollBarBounds;
16325                    getVerticalScrollBarBounds(bounds, null);
16326                    mRoundScrollbarRenderer.drawRoundScrollbars(
16327                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16328                    if (invalidate) {
16329                        invalidate();
16330                    }
16331                }
16332                // Do not draw horizontal scroll bars for round wearable devices.
16333            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16334                final ScrollBarDrawable scrollBar = cache.scrollBar;
16335
16336                if (drawHorizontalScrollBar) {
16337                    scrollBar.setParameters(computeHorizontalScrollRange(),
16338                            computeHorizontalScrollOffset(),
16339                            computeHorizontalScrollExtent(), false);
16340                    final Rect bounds = cache.mScrollBarBounds;
16341                    getHorizontalScrollBarBounds(bounds, null);
16342                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16343                            bounds.right, bounds.bottom);
16344                    if (invalidate) {
16345                        invalidate(bounds);
16346                    }
16347                }
16348
16349                if (drawVerticalScrollBar) {
16350                    scrollBar.setParameters(computeVerticalScrollRange(),
16351                            computeVerticalScrollOffset(),
16352                            computeVerticalScrollExtent(), true);
16353                    final Rect bounds = cache.mScrollBarBounds;
16354                    getVerticalScrollBarBounds(bounds, null);
16355                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16356                            bounds.right, bounds.bottom);
16357                    if (invalidate) {
16358                        invalidate(bounds);
16359                    }
16360                }
16361            }
16362        }
16363    }
16364
16365    /**
16366     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16367     * FastScroller is visible.
16368     * @return whether to temporarily hide the vertical scrollbar
16369     * @hide
16370     */
16371    protected boolean isVerticalScrollBarHidden() {
16372        return false;
16373    }
16374
16375    /**
16376     * <p>Draw the horizontal scrollbar if
16377     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16378     *
16379     * @param canvas the canvas on which to draw the scrollbar
16380     * @param scrollBar the scrollbar's drawable
16381     *
16382     * @see #isHorizontalScrollBarEnabled()
16383     * @see #computeHorizontalScrollRange()
16384     * @see #computeHorizontalScrollExtent()
16385     * @see #computeHorizontalScrollOffset()
16386     * @see android.widget.ScrollBarDrawable
16387     * @hide
16388     */
16389    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16390            int l, int t, int r, int b) {
16391        scrollBar.setBounds(l, t, r, b);
16392        scrollBar.draw(canvas);
16393    }
16394
16395    /**
16396     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16397     * 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 #isVerticalScrollBarEnabled()
16403     * @see #computeVerticalScrollRange()
16404     * @see #computeVerticalScrollExtent()
16405     * @see #computeVerticalScrollOffset()
16406     * @see android.widget.ScrollBarDrawable
16407     * @hide
16408     */
16409    protected void onDrawVerticalScrollBar(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     * Implement this to do your drawing.
16417     *
16418     * @param canvas the canvas on which the background will be drawn
16419     */
16420    protected void onDraw(Canvas canvas) {
16421    }
16422
16423    /*
16424     * Caller is responsible for calling requestLayout if necessary.
16425     * (This allows addViewInLayout to not request a new layout.)
16426     */
16427    void assignParent(ViewParent parent) {
16428        if (mParent == null) {
16429            mParent = parent;
16430        } else if (parent == null) {
16431            mParent = null;
16432        } else {
16433            throw new RuntimeException("view " + this + " being added, but"
16434                    + " it already has a parent");
16435        }
16436    }
16437
16438    /**
16439     * This is called when the view is attached to a window.  At this point it
16440     * has a Surface and will start drawing.  Note that this function is
16441     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16442     * however it may be called any time before the first onDraw -- including
16443     * before or after {@link #onMeasure(int, int)}.
16444     *
16445     * @see #onDetachedFromWindow()
16446     */
16447    @CallSuper
16448    protected void onAttachedToWindow() {
16449        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16450            mParent.requestTransparentRegion(this);
16451        }
16452
16453        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16454
16455        jumpDrawablesToCurrentState();
16456
16457        resetSubtreeAccessibilityStateChanged();
16458
16459        // rebuild, since Outline not maintained while View is detached
16460        rebuildOutline();
16461
16462        if (isFocused()) {
16463            InputMethodManager imm = InputMethodManager.peekInstance();
16464            if (imm != null) {
16465                imm.focusIn(this);
16466            }
16467        }
16468    }
16469
16470    /**
16471     * Resolve all RTL related properties.
16472     *
16473     * @return true if resolution of RTL properties has been done
16474     *
16475     * @hide
16476     */
16477    public boolean resolveRtlPropertiesIfNeeded() {
16478        if (!needRtlPropertiesResolution()) return false;
16479
16480        // Order is important here: LayoutDirection MUST be resolved first
16481        if (!isLayoutDirectionResolved()) {
16482            resolveLayoutDirection();
16483            resolveLayoutParams();
16484        }
16485        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16486        if (!isTextDirectionResolved()) {
16487            resolveTextDirection();
16488        }
16489        if (!isTextAlignmentResolved()) {
16490            resolveTextAlignment();
16491        }
16492        // Should resolve Drawables before Padding because we need the layout direction of the
16493        // Drawable to correctly resolve Padding.
16494        if (!areDrawablesResolved()) {
16495            resolveDrawables();
16496        }
16497        if (!isPaddingResolved()) {
16498            resolvePadding();
16499        }
16500        onRtlPropertiesChanged(getLayoutDirection());
16501        return true;
16502    }
16503
16504    /**
16505     * Reset resolution of all RTL related properties.
16506     *
16507     * @hide
16508     */
16509    public void resetRtlProperties() {
16510        resetResolvedLayoutDirection();
16511        resetResolvedTextDirection();
16512        resetResolvedTextAlignment();
16513        resetResolvedPadding();
16514        resetResolvedDrawables();
16515    }
16516
16517    /**
16518     * @see #onScreenStateChanged(int)
16519     */
16520    void dispatchScreenStateChanged(int screenState) {
16521        onScreenStateChanged(screenState);
16522    }
16523
16524    /**
16525     * This method is called whenever the state of the screen this view is
16526     * attached to changes. A state change will usually occurs when the screen
16527     * turns on or off (whether it happens automatically or the user does it
16528     * manually.)
16529     *
16530     * @param screenState The new state of the screen. Can be either
16531     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16532     */
16533    public void onScreenStateChanged(int screenState) {
16534    }
16535
16536    /**
16537     * @see #onMovedToDisplay(int, Configuration)
16538     */
16539    void dispatchMovedToDisplay(Display display, Configuration config) {
16540        mAttachInfo.mDisplay = display;
16541        mAttachInfo.mDisplayState = display.getState();
16542        onMovedToDisplay(display.getDisplayId(), config);
16543    }
16544
16545    /**
16546     * Called by the system when the hosting activity is moved from one display to another without
16547     * recreation. This means that the activity is declared to handle all changes to configuration
16548     * that happened when it was switched to another display, so it wasn't destroyed and created
16549     * again.
16550     *
16551     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16552     * applied configuration actually changed. It is up to app developer to choose whether to handle
16553     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16554     * call.
16555     *
16556     * <p>Use this callback to track changes to the displays if some functionality relies on an
16557     * association with some display properties.
16558     *
16559     * @param displayId The id of the display to which the view was moved.
16560     * @param config Configuration of the resources on new display after move.
16561     *
16562     * @see #onConfigurationChanged(Configuration)
16563     */
16564    public void onMovedToDisplay(int displayId, Configuration config) {
16565    }
16566
16567    /**
16568     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16569     */
16570    private boolean hasRtlSupport() {
16571        return mContext.getApplicationInfo().hasRtlSupport();
16572    }
16573
16574    /**
16575     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16576     * RTL not supported)
16577     */
16578    private boolean isRtlCompatibilityMode() {
16579        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16580        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16581    }
16582
16583    /**
16584     * @return true if RTL properties need resolution.
16585     *
16586     */
16587    private boolean needRtlPropertiesResolution() {
16588        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16589    }
16590
16591    /**
16592     * Called when any RTL property (layout direction or text direction or text alignment) has
16593     * been changed.
16594     *
16595     * Subclasses need to override this method to take care of cached information that depends on the
16596     * resolved layout direction, or to inform child views that inherit their layout direction.
16597     *
16598     * The default implementation does nothing.
16599     *
16600     * @param layoutDirection the direction of the layout
16601     *
16602     * @see #LAYOUT_DIRECTION_LTR
16603     * @see #LAYOUT_DIRECTION_RTL
16604     */
16605    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16606    }
16607
16608    /**
16609     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16610     * that the parent directionality can and will be resolved before its children.
16611     *
16612     * @return true if resolution has been done, false otherwise.
16613     *
16614     * @hide
16615     */
16616    public boolean resolveLayoutDirection() {
16617        // Clear any previous layout direction resolution
16618        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16619
16620        if (hasRtlSupport()) {
16621            // Set resolved depending on layout direction
16622            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16623                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16624                case LAYOUT_DIRECTION_INHERIT:
16625                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16626                    // later to get the correct resolved value
16627                    if (!canResolveLayoutDirection()) return false;
16628
16629                    // Parent has not yet resolved, LTR is still the default
16630                    try {
16631                        if (!mParent.isLayoutDirectionResolved()) return false;
16632
16633                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16634                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16635                        }
16636                    } catch (AbstractMethodError e) {
16637                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16638                                " does not fully implement ViewParent", e);
16639                    }
16640                    break;
16641                case LAYOUT_DIRECTION_RTL:
16642                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16643                    break;
16644                case LAYOUT_DIRECTION_LOCALE:
16645                    if((LAYOUT_DIRECTION_RTL ==
16646                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16647                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16648                    }
16649                    break;
16650                default:
16651                    // Nothing to do, LTR by default
16652            }
16653        }
16654
16655        // Set to resolved
16656        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16657        return true;
16658    }
16659
16660    /**
16661     * Check if layout direction resolution can be done.
16662     *
16663     * @return true if layout direction resolution can be done otherwise return false.
16664     */
16665    public boolean canResolveLayoutDirection() {
16666        switch (getRawLayoutDirection()) {
16667            case LAYOUT_DIRECTION_INHERIT:
16668                if (mParent != null) {
16669                    try {
16670                        return mParent.canResolveLayoutDirection();
16671                    } catch (AbstractMethodError e) {
16672                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16673                                " does not fully implement ViewParent", e);
16674                    }
16675                }
16676                return false;
16677
16678            default:
16679                return true;
16680        }
16681    }
16682
16683    /**
16684     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16685     * {@link #onMeasure(int, int)}.
16686     *
16687     * @hide
16688     */
16689    public void resetResolvedLayoutDirection() {
16690        // Reset the current resolved bits
16691        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16692    }
16693
16694    /**
16695     * @return true if the layout direction is inherited.
16696     *
16697     * @hide
16698     */
16699    public boolean isLayoutDirectionInherited() {
16700        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16701    }
16702
16703    /**
16704     * @return true if layout direction has been resolved.
16705     */
16706    public boolean isLayoutDirectionResolved() {
16707        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16708    }
16709
16710    /**
16711     * Return if padding has been resolved
16712     *
16713     * @hide
16714     */
16715    boolean isPaddingResolved() {
16716        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16717    }
16718
16719    /**
16720     * Resolves padding depending on layout direction, if applicable, and
16721     * recomputes internal padding values to adjust for scroll bars.
16722     *
16723     * @hide
16724     */
16725    public void resolvePadding() {
16726        final int resolvedLayoutDirection = getLayoutDirection();
16727
16728        if (!isRtlCompatibilityMode()) {
16729            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16730            // If start / end padding are defined, they will be resolved (hence overriding) to
16731            // left / right or right / left depending on the resolved layout direction.
16732            // If start / end padding are not defined, use the left / right ones.
16733            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16734                Rect padding = sThreadLocal.get();
16735                if (padding == null) {
16736                    padding = new Rect();
16737                    sThreadLocal.set(padding);
16738                }
16739                mBackground.getPadding(padding);
16740                if (!mLeftPaddingDefined) {
16741                    mUserPaddingLeftInitial = padding.left;
16742                }
16743                if (!mRightPaddingDefined) {
16744                    mUserPaddingRightInitial = padding.right;
16745                }
16746            }
16747            switch (resolvedLayoutDirection) {
16748                case LAYOUT_DIRECTION_RTL:
16749                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16750                        mUserPaddingRight = mUserPaddingStart;
16751                    } else {
16752                        mUserPaddingRight = mUserPaddingRightInitial;
16753                    }
16754                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16755                        mUserPaddingLeft = mUserPaddingEnd;
16756                    } else {
16757                        mUserPaddingLeft = mUserPaddingLeftInitial;
16758                    }
16759                    break;
16760                case LAYOUT_DIRECTION_LTR:
16761                default:
16762                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16763                        mUserPaddingLeft = mUserPaddingStart;
16764                    } else {
16765                        mUserPaddingLeft = mUserPaddingLeftInitial;
16766                    }
16767                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16768                        mUserPaddingRight = mUserPaddingEnd;
16769                    } else {
16770                        mUserPaddingRight = mUserPaddingRightInitial;
16771                    }
16772            }
16773
16774            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16775        }
16776
16777        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16778        onRtlPropertiesChanged(resolvedLayoutDirection);
16779
16780        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16781    }
16782
16783    /**
16784     * Reset the resolved layout direction.
16785     *
16786     * @hide
16787     */
16788    public void resetResolvedPadding() {
16789        resetResolvedPaddingInternal();
16790    }
16791
16792    /**
16793     * Used when we only want to reset *this* view's padding and not trigger overrides
16794     * in ViewGroup that reset children too.
16795     */
16796    void resetResolvedPaddingInternal() {
16797        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16798    }
16799
16800    /**
16801     * This is called when the view is detached from a window.  At this point it
16802     * no longer has a surface for drawing.
16803     *
16804     * @see #onAttachedToWindow()
16805     */
16806    @CallSuper
16807    protected void onDetachedFromWindow() {
16808    }
16809
16810    /**
16811     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16812     * after onDetachedFromWindow().
16813     *
16814     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16815     * The super method should be called at the end of the overridden method to ensure
16816     * subclasses are destroyed first
16817     *
16818     * @hide
16819     */
16820    @CallSuper
16821    protected void onDetachedFromWindowInternal() {
16822        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16823        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16824        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16825
16826        removeUnsetPressCallback();
16827        removeLongPressCallback();
16828        removePerformClickCallback();
16829        removeSendViewScrolledAccessibilityEventCallback();
16830        stopNestedScroll();
16831
16832        // Anything that started animating right before detach should already
16833        // be in its final state when re-attached.
16834        jumpDrawablesToCurrentState();
16835
16836        destroyDrawingCache();
16837
16838        cleanupDraw();
16839        mCurrentAnimation = null;
16840
16841        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16842            hideTooltip();
16843        }
16844    }
16845
16846    private void cleanupDraw() {
16847        resetDisplayList();
16848        if (mAttachInfo != null) {
16849            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16850        }
16851    }
16852
16853    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16854    }
16855
16856    /**
16857     * @return The number of times this view has been attached to a window
16858     */
16859    protected int getWindowAttachCount() {
16860        return mWindowAttachCount;
16861    }
16862
16863    /**
16864     * Retrieve a unique token identifying the window this view is attached to.
16865     * @return Return the window's token for use in
16866     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16867     */
16868    public IBinder getWindowToken() {
16869        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16870    }
16871
16872    /**
16873     * Retrieve the {@link WindowId} for the window this view is
16874     * currently attached to.
16875     */
16876    public WindowId getWindowId() {
16877        if (mAttachInfo == null) {
16878            return null;
16879        }
16880        if (mAttachInfo.mWindowId == null) {
16881            try {
16882                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16883                        mAttachInfo.mWindowToken);
16884                mAttachInfo.mWindowId = new WindowId(
16885                        mAttachInfo.mIWindowId);
16886            } catch (RemoteException e) {
16887            }
16888        }
16889        return mAttachInfo.mWindowId;
16890    }
16891
16892    /**
16893     * Retrieve a unique token identifying the top-level "real" window of
16894     * the window that this view is attached to.  That is, this is like
16895     * {@link #getWindowToken}, except if the window this view in is a panel
16896     * window (attached to another containing window), then the token of
16897     * the containing window is returned instead.
16898     *
16899     * @return Returns the associated window token, either
16900     * {@link #getWindowToken()} or the containing window's token.
16901     */
16902    public IBinder getApplicationWindowToken() {
16903        AttachInfo ai = mAttachInfo;
16904        if (ai != null) {
16905            IBinder appWindowToken = ai.mPanelParentWindowToken;
16906            if (appWindowToken == null) {
16907                appWindowToken = ai.mWindowToken;
16908            }
16909            return appWindowToken;
16910        }
16911        return null;
16912    }
16913
16914    /**
16915     * Gets the logical display to which the view's window has been attached.
16916     *
16917     * @return The logical display, or null if the view is not currently attached to a window.
16918     */
16919    public Display getDisplay() {
16920        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16921    }
16922
16923    /**
16924     * Retrieve private session object this view hierarchy is using to
16925     * communicate with the window manager.
16926     * @return the session object to communicate with the window manager
16927     */
16928    /*package*/ IWindowSession getWindowSession() {
16929        return mAttachInfo != null ? mAttachInfo.mSession : null;
16930    }
16931
16932    /**
16933     * Return the visibility value of the least visible component passed.
16934     */
16935    int combineVisibility(int vis1, int vis2) {
16936        // This works because VISIBLE < INVISIBLE < GONE.
16937        return Math.max(vis1, vis2);
16938    }
16939
16940    /**
16941     * @param info the {@link android.view.View.AttachInfo} to associated with
16942     *        this view
16943     */
16944    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16945        mAttachInfo = info;
16946        if (mOverlay != null) {
16947            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16948        }
16949        mWindowAttachCount++;
16950        // We will need to evaluate the drawable state at least once.
16951        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16952        if (mFloatingTreeObserver != null) {
16953            info.mTreeObserver.merge(mFloatingTreeObserver);
16954            mFloatingTreeObserver = null;
16955        }
16956
16957        registerPendingFrameMetricsObservers();
16958
16959        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16960            mAttachInfo.mScrollContainers.add(this);
16961            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16962        }
16963        // Transfer all pending runnables.
16964        if (mRunQueue != null) {
16965            mRunQueue.executeActions(info.mHandler);
16966            mRunQueue = null;
16967        }
16968        performCollectViewAttributes(mAttachInfo, visibility);
16969        onAttachedToWindow();
16970
16971        ListenerInfo li = mListenerInfo;
16972        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16973                li != null ? li.mOnAttachStateChangeListeners : null;
16974        if (listeners != null && listeners.size() > 0) {
16975            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16976            // perform the dispatching. The iterator is a safe guard against listeners that
16977            // could mutate the list by calling the various add/remove methods. This prevents
16978            // the array from being modified while we iterate it.
16979            for (OnAttachStateChangeListener listener : listeners) {
16980                listener.onViewAttachedToWindow(this);
16981            }
16982        }
16983
16984        int vis = info.mWindowVisibility;
16985        if (vis != GONE) {
16986            onWindowVisibilityChanged(vis);
16987            if (isShown()) {
16988                // Calling onVisibilityAggregated directly here since the subtree will also
16989                // receive dispatchAttachedToWindow and this same call
16990                onVisibilityAggregated(vis == VISIBLE);
16991            }
16992        }
16993
16994        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
16995        // As all views in the subtree will already receive dispatchAttachedToWindow
16996        // traversing the subtree again here is not desired.
16997        onVisibilityChanged(this, visibility);
16998
16999        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17000            // If nobody has evaluated the drawable state yet, then do it now.
17001            refreshDrawableState();
17002        }
17003        needGlobalAttributesUpdate(false);
17004
17005        notifyEnterOrExitForAutoFillIfNeeded(true);
17006    }
17007
17008    void dispatchDetachedFromWindow() {
17009        AttachInfo info = mAttachInfo;
17010        if (info != null) {
17011            int vis = info.mWindowVisibility;
17012            if (vis != GONE) {
17013                onWindowVisibilityChanged(GONE);
17014                if (isShown()) {
17015                    // Invoking onVisibilityAggregated directly here since the subtree
17016                    // will also receive detached from window
17017                    onVisibilityAggregated(false);
17018                }
17019            }
17020        }
17021
17022        onDetachedFromWindow();
17023        onDetachedFromWindowInternal();
17024
17025        InputMethodManager imm = InputMethodManager.peekInstance();
17026        if (imm != null) {
17027            imm.onViewDetachedFromWindow(this);
17028        }
17029
17030        ListenerInfo li = mListenerInfo;
17031        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17032                li != null ? li.mOnAttachStateChangeListeners : null;
17033        if (listeners != null && listeners.size() > 0) {
17034            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17035            // perform the dispatching. The iterator is a safe guard against listeners that
17036            // could mutate the list by calling the various add/remove methods. This prevents
17037            // the array from being modified while we iterate it.
17038            for (OnAttachStateChangeListener listener : listeners) {
17039                listener.onViewDetachedFromWindow(this);
17040            }
17041        }
17042
17043        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17044            mAttachInfo.mScrollContainers.remove(this);
17045            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17046        }
17047
17048        mAttachInfo = null;
17049        if (mOverlay != null) {
17050            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17051        }
17052
17053        notifyEnterOrExitForAutoFillIfNeeded(false);
17054    }
17055
17056    /**
17057     * Cancel any deferred high-level input events that were previously posted to the event queue.
17058     *
17059     * <p>Many views post high-level events such as click handlers to the event queue
17060     * to run deferred in order to preserve a desired user experience - clearing visible
17061     * pressed states before executing, etc. This method will abort any events of this nature
17062     * that are currently in flight.</p>
17063     *
17064     * <p>Custom views that generate their own high-level deferred input events should override
17065     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17066     *
17067     * <p>This will also cancel pending input events for any child views.</p>
17068     *
17069     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17070     * This will not impact newer events posted after this call that may occur as a result of
17071     * lower-level input events still waiting in the queue. If you are trying to prevent
17072     * double-submitted  events for the duration of some sort of asynchronous transaction
17073     * you should also take other steps to protect against unexpected double inputs e.g. calling
17074     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17075     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17076     */
17077    public final void cancelPendingInputEvents() {
17078        dispatchCancelPendingInputEvents();
17079    }
17080
17081    /**
17082     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17083     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17084     */
17085    void dispatchCancelPendingInputEvents() {
17086        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17087        onCancelPendingInputEvents();
17088        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17089            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17090                    " did not call through to super.onCancelPendingInputEvents()");
17091        }
17092    }
17093
17094    /**
17095     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17096     * a parent view.
17097     *
17098     * <p>This method is responsible for removing any pending high-level input events that were
17099     * posted to the event queue to run later. Custom view classes that post their own deferred
17100     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17101     * {@link android.os.Handler} should override this method, call
17102     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17103     * </p>
17104     */
17105    public void onCancelPendingInputEvents() {
17106        removePerformClickCallback();
17107        cancelLongPress();
17108        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17109    }
17110
17111    /**
17112     * Store this view hierarchy's frozen state into the given container.
17113     *
17114     * @param container The SparseArray in which to save the view's state.
17115     *
17116     * @see #restoreHierarchyState(android.util.SparseArray)
17117     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17118     * @see #onSaveInstanceState()
17119     */
17120    public void saveHierarchyState(SparseArray<Parcelable> container) {
17121        dispatchSaveInstanceState(container);
17122    }
17123
17124    /**
17125     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17126     * this view and its children. May be overridden to modify how freezing happens to a
17127     * view's children; for example, some views may want to not store state for their children.
17128     *
17129     * @param container The SparseArray in which to save the view's state.
17130     *
17131     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17132     * @see #saveHierarchyState(android.util.SparseArray)
17133     * @see #onSaveInstanceState()
17134     */
17135    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17136        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17137            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17138            Parcelable state = onSaveInstanceState();
17139            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17140                throw new IllegalStateException(
17141                        "Derived class did not call super.onSaveInstanceState()");
17142            }
17143            if (state != null) {
17144                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17145                // + ": " + state);
17146                container.put(mID, state);
17147            }
17148        }
17149    }
17150
17151    /**
17152     * Hook allowing a view to generate a representation of its internal state
17153     * that can later be used to create a new instance with that same state.
17154     * This state should only contain information that is not persistent or can
17155     * not be reconstructed later. For example, you will never store your
17156     * current position on screen because that will be computed again when a
17157     * new instance of the view is placed in its view hierarchy.
17158     * <p>
17159     * Some examples of things you may store here: the current cursor position
17160     * in a text view (but usually not the text itself since that is stored in a
17161     * content provider or other persistent storage), the currently selected
17162     * item in a list view.
17163     *
17164     * @return Returns a Parcelable object containing the view's current dynamic
17165     *         state, or null if there is nothing interesting to save. The
17166     *         default implementation returns null.
17167     * @see #onRestoreInstanceState(android.os.Parcelable)
17168     * @see #saveHierarchyState(android.util.SparseArray)
17169     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17170     * @see #setSaveEnabled(boolean)
17171     */
17172    @CallSuper
17173    protected Parcelable onSaveInstanceState() {
17174        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17175        if (mStartActivityRequestWho != null || isAutofilled()
17176                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17177            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17178
17179            if (mStartActivityRequestWho != null) {
17180                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17181            }
17182
17183            if (isAutofilled()) {
17184                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17185            }
17186
17187            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17188                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17189            }
17190
17191            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17192            state.mIsAutofilled = isAutofilled();
17193            state.mAccessibilityViewId = mAccessibilityViewId;
17194            return state;
17195        }
17196        return BaseSavedState.EMPTY_STATE;
17197    }
17198
17199    /**
17200     * Restore this view hierarchy's frozen state from the given container.
17201     *
17202     * @param container The SparseArray which holds previously frozen states.
17203     *
17204     * @see #saveHierarchyState(android.util.SparseArray)
17205     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17206     * @see #onRestoreInstanceState(android.os.Parcelable)
17207     */
17208    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17209        dispatchRestoreInstanceState(container);
17210    }
17211
17212    /**
17213     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17214     * state for this view and its children. May be overridden to modify how restoring
17215     * happens to a view's children; for example, some views may want to not store state
17216     * for their children.
17217     *
17218     * @param container The SparseArray which holds previously saved state.
17219     *
17220     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17221     * @see #restoreHierarchyState(android.util.SparseArray)
17222     * @see #onRestoreInstanceState(android.os.Parcelable)
17223     */
17224    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17225        if (mID != NO_ID) {
17226            Parcelable state = container.get(mID);
17227            if (state != null) {
17228                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17229                // + ": " + state);
17230                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17231                onRestoreInstanceState(state);
17232                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17233                    throw new IllegalStateException(
17234                            "Derived class did not call super.onRestoreInstanceState()");
17235                }
17236            }
17237        }
17238    }
17239
17240    /**
17241     * Hook allowing a view to re-apply a representation of its internal state that had previously
17242     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17243     * null state.
17244     *
17245     * @param state The frozen state that had previously been returned by
17246     *        {@link #onSaveInstanceState}.
17247     *
17248     * @see #onSaveInstanceState()
17249     * @see #restoreHierarchyState(android.util.SparseArray)
17250     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17251     */
17252    @CallSuper
17253    protected void onRestoreInstanceState(Parcelable state) {
17254        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17255        if (state != null && !(state instanceof AbsSavedState)) {
17256            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17257                    + "received " + state.getClass().toString() + " instead. This usually happens "
17258                    + "when two views of different type have the same id in the same hierarchy. "
17259                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17260                    + "other views do not use the same id.");
17261        }
17262        if (state != null && state instanceof BaseSavedState) {
17263            BaseSavedState baseState = (BaseSavedState) state;
17264
17265            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17266                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17267            }
17268            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17269                setAutofilled(baseState.mIsAutofilled);
17270            }
17271            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17272                mAccessibilityViewId = baseState.mAccessibilityViewId;
17273            }
17274        }
17275    }
17276
17277    /**
17278     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17279     *
17280     * @return the drawing start time in milliseconds
17281     */
17282    public long getDrawingTime() {
17283        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17284    }
17285
17286    /**
17287     * <p>Enables or disables the duplication of the parent's state into this view. When
17288     * duplication is enabled, this view gets its drawable state from its parent rather
17289     * than from its own internal properties.</p>
17290     *
17291     * <p>Note: in the current implementation, setting this property to true after the
17292     * view was added to a ViewGroup might have no effect at all. This property should
17293     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17294     *
17295     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17296     * property is enabled, an exception will be thrown.</p>
17297     *
17298     * <p>Note: if the child view uses and updates additional states which are unknown to the
17299     * parent, these states should not be affected by this method.</p>
17300     *
17301     * @param enabled True to enable duplication of the parent's drawable state, false
17302     *                to disable it.
17303     *
17304     * @see #getDrawableState()
17305     * @see #isDuplicateParentStateEnabled()
17306     */
17307    public void setDuplicateParentStateEnabled(boolean enabled) {
17308        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17309    }
17310
17311    /**
17312     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17313     *
17314     * @return True if this view's drawable state is duplicated from the parent,
17315     *         false otherwise
17316     *
17317     * @see #getDrawableState()
17318     * @see #setDuplicateParentStateEnabled(boolean)
17319     */
17320    public boolean isDuplicateParentStateEnabled() {
17321        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17322    }
17323
17324    /**
17325     * <p>Specifies the type of layer backing this view. The layer can be
17326     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17327     * {@link #LAYER_TYPE_HARDWARE}.</p>
17328     *
17329     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17330     * instance that controls how the layer is composed on screen. The following
17331     * properties of the paint are taken into account when composing the layer:</p>
17332     * <ul>
17333     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17334     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17335     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17336     * </ul>
17337     *
17338     * <p>If this view has an alpha value set to < 1.0 by calling
17339     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17340     * by this view's alpha value.</p>
17341     *
17342     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17343     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17344     * for more information on when and how to use layers.</p>
17345     *
17346     * @param layerType The type of layer to use with this view, must be one of
17347     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17348     *        {@link #LAYER_TYPE_HARDWARE}
17349     * @param paint The paint used to compose the layer. This argument is optional
17350     *        and can be null. It is ignored when the layer type is
17351     *        {@link #LAYER_TYPE_NONE}
17352     *
17353     * @see #getLayerType()
17354     * @see #LAYER_TYPE_NONE
17355     * @see #LAYER_TYPE_SOFTWARE
17356     * @see #LAYER_TYPE_HARDWARE
17357     * @see #setAlpha(float)
17358     *
17359     * @attr ref android.R.styleable#View_layerType
17360     */
17361    public void setLayerType(int layerType, @Nullable Paint paint) {
17362        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17363            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17364                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17365        }
17366
17367        boolean typeChanged = mRenderNode.setLayerType(layerType);
17368
17369        if (!typeChanged) {
17370            setLayerPaint(paint);
17371            return;
17372        }
17373
17374        if (layerType != LAYER_TYPE_SOFTWARE) {
17375            // Destroy any previous software drawing cache if present
17376            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17377            // drawing cache created in View#draw when drawing to a SW canvas.
17378            destroyDrawingCache();
17379        }
17380
17381        mLayerType = layerType;
17382        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17383        mRenderNode.setLayerPaint(mLayerPaint);
17384
17385        // draw() behaves differently if we are on a layer, so we need to
17386        // invalidate() here
17387        invalidateParentCaches();
17388        invalidate(true);
17389    }
17390
17391    /**
17392     * Updates the {@link Paint} object used with the current layer (used only if the current
17393     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17394     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17395     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17396     * ensure that the view gets redrawn immediately.
17397     *
17398     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17399     * instance that controls how the layer is composed on screen. The following
17400     * properties of the paint are taken into account when composing the layer:</p>
17401     * <ul>
17402     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17403     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17404     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17405     * </ul>
17406     *
17407     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17408     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17409     *
17410     * @param paint The paint used to compose the layer. This argument is optional
17411     *        and can be null. It is ignored when the layer type is
17412     *        {@link #LAYER_TYPE_NONE}
17413     *
17414     * @see #setLayerType(int, android.graphics.Paint)
17415     */
17416    public void setLayerPaint(@Nullable Paint paint) {
17417        int layerType = getLayerType();
17418        if (layerType != LAYER_TYPE_NONE) {
17419            mLayerPaint = paint;
17420            if (layerType == LAYER_TYPE_HARDWARE) {
17421                if (mRenderNode.setLayerPaint(paint)) {
17422                    invalidateViewProperty(false, false);
17423                }
17424            } else {
17425                invalidate();
17426            }
17427        }
17428    }
17429
17430    /**
17431     * Indicates what type of layer is currently associated with this view. By default
17432     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17433     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17434     * for more information on the different types of layers.
17435     *
17436     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17437     *         {@link #LAYER_TYPE_HARDWARE}
17438     *
17439     * @see #setLayerType(int, android.graphics.Paint)
17440     * @see #buildLayer()
17441     * @see #LAYER_TYPE_NONE
17442     * @see #LAYER_TYPE_SOFTWARE
17443     * @see #LAYER_TYPE_HARDWARE
17444     */
17445    public int getLayerType() {
17446        return mLayerType;
17447    }
17448
17449    /**
17450     * Forces this view's layer to be created and this view to be rendered
17451     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17452     * invoking this method will have no effect.
17453     *
17454     * This method can for instance be used to render a view into its layer before
17455     * starting an animation. If this view is complex, rendering into the layer
17456     * before starting the animation will avoid skipping frames.
17457     *
17458     * @throws IllegalStateException If this view is not attached to a window
17459     *
17460     * @see #setLayerType(int, android.graphics.Paint)
17461     */
17462    public void buildLayer() {
17463        if (mLayerType == LAYER_TYPE_NONE) return;
17464
17465        final AttachInfo attachInfo = mAttachInfo;
17466        if (attachInfo == null) {
17467            throw new IllegalStateException("This view must be attached to a window first");
17468        }
17469
17470        if (getWidth() == 0 || getHeight() == 0) {
17471            return;
17472        }
17473
17474        switch (mLayerType) {
17475            case LAYER_TYPE_HARDWARE:
17476                updateDisplayListIfDirty();
17477                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17478                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17479                }
17480                break;
17481            case LAYER_TYPE_SOFTWARE:
17482                buildDrawingCache(true);
17483                break;
17484        }
17485    }
17486
17487    /**
17488     * Destroys all hardware rendering resources. This method is invoked
17489     * when the system needs to reclaim resources. Upon execution of this
17490     * method, you should free any OpenGL resources created by the view.
17491     *
17492     * Note: you <strong>must</strong> call
17493     * <code>super.destroyHardwareResources()</code> when overriding
17494     * this method.
17495     *
17496     * @hide
17497     */
17498    @CallSuper
17499    protected void destroyHardwareResources() {
17500        if (mOverlay != null) {
17501            mOverlay.getOverlayView().destroyHardwareResources();
17502        }
17503        if (mGhostView != null) {
17504            mGhostView.destroyHardwareResources();
17505        }
17506    }
17507
17508    /**
17509     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17510     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17511     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17512     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17513     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17514     * null.</p>
17515     *
17516     * <p>Enabling the drawing cache is similar to
17517     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17518     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17519     * drawing cache has no effect on rendering because the system uses a different mechanism
17520     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17521     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17522     * for information on how to enable software and hardware layers.</p>
17523     *
17524     * <p>This API can be used to manually generate
17525     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17526     * {@link #getDrawingCache()}.</p>
17527     *
17528     * @param enabled true to enable the drawing cache, false otherwise
17529     *
17530     * @see #isDrawingCacheEnabled()
17531     * @see #getDrawingCache()
17532     * @see #buildDrawingCache()
17533     * @see #setLayerType(int, android.graphics.Paint)
17534     */
17535    public void setDrawingCacheEnabled(boolean enabled) {
17536        mCachingFailed = false;
17537        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17538    }
17539
17540    /**
17541     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17542     *
17543     * @return true if the drawing cache is enabled
17544     *
17545     * @see #setDrawingCacheEnabled(boolean)
17546     * @see #getDrawingCache()
17547     */
17548    @ViewDebug.ExportedProperty(category = "drawing")
17549    public boolean isDrawingCacheEnabled() {
17550        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17551    }
17552
17553    /**
17554     * Debugging utility which recursively outputs the dirty state of a view and its
17555     * descendants.
17556     *
17557     * @hide
17558     */
17559    @SuppressWarnings({"UnusedDeclaration"})
17560    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17561        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17562                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17563                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17564                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17565        if (clear) {
17566            mPrivateFlags &= clearMask;
17567        }
17568        if (this instanceof ViewGroup) {
17569            ViewGroup parent = (ViewGroup) this;
17570            final int count = parent.getChildCount();
17571            for (int i = 0; i < count; i++) {
17572                final View child = parent.getChildAt(i);
17573                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17574            }
17575        }
17576    }
17577
17578    /**
17579     * This method is used by ViewGroup to cause its children to restore or recreate their
17580     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17581     * to recreate its own display list, which would happen if it went through the normal
17582     * draw/dispatchDraw mechanisms.
17583     *
17584     * @hide
17585     */
17586    protected void dispatchGetDisplayList() {}
17587
17588    /**
17589     * A view that is not attached or hardware accelerated cannot create a display list.
17590     * This method checks these conditions and returns the appropriate result.
17591     *
17592     * @return true if view has the ability to create a display list, false otherwise.
17593     *
17594     * @hide
17595     */
17596    public boolean canHaveDisplayList() {
17597        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17598    }
17599
17600    /**
17601     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17602     * @hide
17603     */
17604    @NonNull
17605    public RenderNode updateDisplayListIfDirty() {
17606        final RenderNode renderNode = mRenderNode;
17607        if (!canHaveDisplayList()) {
17608            // can't populate RenderNode, don't try
17609            return renderNode;
17610        }
17611
17612        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17613                || !renderNode.isValid()
17614                || (mRecreateDisplayList)) {
17615            // Don't need to recreate the display list, just need to tell our
17616            // children to restore/recreate theirs
17617            if (renderNode.isValid()
17618                    && !mRecreateDisplayList) {
17619                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17620                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17621                dispatchGetDisplayList();
17622
17623                return renderNode; // no work needed
17624            }
17625
17626            // If we got here, we're recreating it. Mark it as such to ensure that
17627            // we copy in child display lists into ours in drawChild()
17628            mRecreateDisplayList = true;
17629
17630            int width = mRight - mLeft;
17631            int height = mBottom - mTop;
17632            int layerType = getLayerType();
17633
17634            final DisplayListCanvas canvas = renderNode.start(width, height);
17635            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17636
17637            try {
17638                if (layerType == LAYER_TYPE_SOFTWARE) {
17639                    buildDrawingCache(true);
17640                    Bitmap cache = getDrawingCache(true);
17641                    if (cache != null) {
17642                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17643                    }
17644                } else {
17645                    computeScroll();
17646
17647                    canvas.translate(-mScrollX, -mScrollY);
17648                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17649                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17650
17651                    // Fast path for layouts with no backgrounds
17652                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17653                        dispatchDraw(canvas);
17654                        drawAutofilledHighlight(canvas);
17655                        if (mOverlay != null && !mOverlay.isEmpty()) {
17656                            mOverlay.getOverlayView().draw(canvas);
17657                        }
17658                        if (debugDraw()) {
17659                            debugDrawFocus(canvas);
17660                        }
17661                    } else {
17662                        draw(canvas);
17663                    }
17664                }
17665            } finally {
17666                renderNode.end(canvas);
17667                setDisplayListProperties(renderNode);
17668            }
17669        } else {
17670            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17671            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17672        }
17673        return renderNode;
17674    }
17675
17676    private void resetDisplayList() {
17677        mRenderNode.discardDisplayList();
17678        if (mBackgroundRenderNode != null) {
17679            mBackgroundRenderNode.discardDisplayList();
17680        }
17681    }
17682
17683    /**
17684     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17685     *
17686     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17687     *
17688     * @see #getDrawingCache(boolean)
17689     */
17690    public Bitmap getDrawingCache() {
17691        return getDrawingCache(false);
17692    }
17693
17694    /**
17695     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17696     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17697     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17698     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17699     * request the drawing cache by calling this method and draw it on screen if the
17700     * returned bitmap is not null.</p>
17701     *
17702     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17703     * this method will create a bitmap of the same size as this view. Because this bitmap
17704     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17705     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17706     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17707     * size than the view. This implies that your application must be able to handle this
17708     * size.</p>
17709     *
17710     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17711     *        the current density of the screen when the application is in compatibility
17712     *        mode.
17713     *
17714     * @return A bitmap representing this view or null if cache is disabled.
17715     *
17716     * @see #setDrawingCacheEnabled(boolean)
17717     * @see #isDrawingCacheEnabled()
17718     * @see #buildDrawingCache(boolean)
17719     * @see #destroyDrawingCache()
17720     */
17721    public Bitmap getDrawingCache(boolean autoScale) {
17722        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17723            return null;
17724        }
17725        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17726            buildDrawingCache(autoScale);
17727        }
17728        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17729    }
17730
17731    /**
17732     * <p>Frees the resources used by the drawing cache. If you call
17733     * {@link #buildDrawingCache()} manually without calling
17734     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17735     * should cleanup the cache with this method afterwards.</p>
17736     *
17737     * @see #setDrawingCacheEnabled(boolean)
17738     * @see #buildDrawingCache()
17739     * @see #getDrawingCache()
17740     */
17741    public void destroyDrawingCache() {
17742        if (mDrawingCache != null) {
17743            mDrawingCache.recycle();
17744            mDrawingCache = null;
17745        }
17746        if (mUnscaledDrawingCache != null) {
17747            mUnscaledDrawingCache.recycle();
17748            mUnscaledDrawingCache = null;
17749        }
17750    }
17751
17752    /**
17753     * Setting a solid background color for the drawing cache's bitmaps will improve
17754     * performance and memory usage. Note, though that this should only be used if this
17755     * view will always be drawn on top of a solid color.
17756     *
17757     * @param color The background color to use for the drawing cache's bitmap
17758     *
17759     * @see #setDrawingCacheEnabled(boolean)
17760     * @see #buildDrawingCache()
17761     * @see #getDrawingCache()
17762     */
17763    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17764        if (color != mDrawingCacheBackgroundColor) {
17765            mDrawingCacheBackgroundColor = color;
17766            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17767        }
17768    }
17769
17770    /**
17771     * @see #setDrawingCacheBackgroundColor(int)
17772     *
17773     * @return The background color to used for the drawing cache's bitmap
17774     */
17775    @ColorInt
17776    public int getDrawingCacheBackgroundColor() {
17777        return mDrawingCacheBackgroundColor;
17778    }
17779
17780    /**
17781     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17782     *
17783     * @see #buildDrawingCache(boolean)
17784     */
17785    public void buildDrawingCache() {
17786        buildDrawingCache(false);
17787    }
17788
17789    /**
17790     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17791     *
17792     * <p>If you call {@link #buildDrawingCache()} manually without calling
17793     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17794     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17795     *
17796     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17797     * this method will create a bitmap of the same size as this view. Because this bitmap
17798     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17799     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17800     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17801     * size than the view. This implies that your application must be able to handle this
17802     * size.</p>
17803     *
17804     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17805     * you do not need the drawing cache bitmap, calling this method will increase memory
17806     * usage and cause the view to be rendered in software once, thus negatively impacting
17807     * performance.</p>
17808     *
17809     * @see #getDrawingCache()
17810     * @see #destroyDrawingCache()
17811     */
17812    public void buildDrawingCache(boolean autoScale) {
17813        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17814                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17815            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17816                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17817                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17818            }
17819            try {
17820                buildDrawingCacheImpl(autoScale);
17821            } finally {
17822                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17823            }
17824        }
17825    }
17826
17827    /**
17828     * private, internal implementation of buildDrawingCache, used to enable tracing
17829     */
17830    private void buildDrawingCacheImpl(boolean autoScale) {
17831        mCachingFailed = false;
17832
17833        int width = mRight - mLeft;
17834        int height = mBottom - mTop;
17835
17836        final AttachInfo attachInfo = mAttachInfo;
17837        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17838
17839        if (autoScale && scalingRequired) {
17840            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17841            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17842        }
17843
17844        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17845        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17846        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17847
17848        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17849        final long drawingCacheSize =
17850                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17851        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17852            if (width > 0 && height > 0) {
17853                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17854                        + " too large to fit into a software layer (or drawing cache), needs "
17855                        + projectedBitmapSize + " bytes, only "
17856                        + drawingCacheSize + " available");
17857            }
17858            destroyDrawingCache();
17859            mCachingFailed = true;
17860            return;
17861        }
17862
17863        boolean clear = true;
17864        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17865
17866        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17867            Bitmap.Config quality;
17868            if (!opaque) {
17869                // Never pick ARGB_4444 because it looks awful
17870                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17871                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17872                    case DRAWING_CACHE_QUALITY_AUTO:
17873                    case DRAWING_CACHE_QUALITY_LOW:
17874                    case DRAWING_CACHE_QUALITY_HIGH:
17875                    default:
17876                        quality = Bitmap.Config.ARGB_8888;
17877                        break;
17878                }
17879            } else {
17880                // Optimization for translucent windows
17881                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17882                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17883            }
17884
17885            // Try to cleanup memory
17886            if (bitmap != null) bitmap.recycle();
17887
17888            try {
17889                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17890                        width, height, quality);
17891                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17892                if (autoScale) {
17893                    mDrawingCache = bitmap;
17894                } else {
17895                    mUnscaledDrawingCache = bitmap;
17896                }
17897                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17898            } catch (OutOfMemoryError e) {
17899                // If there is not enough memory to create the bitmap cache, just
17900                // ignore the issue as bitmap caches are not required to draw the
17901                // view hierarchy
17902                if (autoScale) {
17903                    mDrawingCache = null;
17904                } else {
17905                    mUnscaledDrawingCache = null;
17906                }
17907                mCachingFailed = true;
17908                return;
17909            }
17910
17911            clear = drawingCacheBackgroundColor != 0;
17912        }
17913
17914        Canvas canvas;
17915        if (attachInfo != null) {
17916            canvas = attachInfo.mCanvas;
17917            if (canvas == null) {
17918                canvas = new Canvas();
17919            }
17920            canvas.setBitmap(bitmap);
17921            // Temporarily clobber the cached Canvas in case one of our children
17922            // is also using a drawing cache. Without this, the children would
17923            // steal the canvas by attaching their own bitmap to it and bad, bad
17924            // thing would happen (invisible views, corrupted drawings, etc.)
17925            attachInfo.mCanvas = null;
17926        } else {
17927            // This case should hopefully never or seldom happen
17928            canvas = new Canvas(bitmap);
17929        }
17930
17931        if (clear) {
17932            bitmap.eraseColor(drawingCacheBackgroundColor);
17933        }
17934
17935        computeScroll();
17936        final int restoreCount = canvas.save();
17937
17938        if (autoScale && scalingRequired) {
17939            final float scale = attachInfo.mApplicationScale;
17940            canvas.scale(scale, scale);
17941        }
17942
17943        canvas.translate(-mScrollX, -mScrollY);
17944
17945        mPrivateFlags |= PFLAG_DRAWN;
17946        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17947                mLayerType != LAYER_TYPE_NONE) {
17948            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17949        }
17950
17951        // Fast path for layouts with no backgrounds
17952        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17953            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17954            dispatchDraw(canvas);
17955            drawAutofilledHighlight(canvas);
17956            if (mOverlay != null && !mOverlay.isEmpty()) {
17957                mOverlay.getOverlayView().draw(canvas);
17958            }
17959        } else {
17960            draw(canvas);
17961        }
17962
17963        canvas.restoreToCount(restoreCount);
17964        canvas.setBitmap(null);
17965
17966        if (attachInfo != null) {
17967            // Restore the cached Canvas for our siblings
17968            attachInfo.mCanvas = canvas;
17969        }
17970    }
17971
17972    /**
17973     * Create a snapshot of the view into a bitmap.  We should probably make
17974     * some form of this public, but should think about the API.
17975     *
17976     * @hide
17977     */
17978    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17979        int width = mRight - mLeft;
17980        int height = mBottom - mTop;
17981
17982        final AttachInfo attachInfo = mAttachInfo;
17983        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
17984        width = (int) ((width * scale) + 0.5f);
17985        height = (int) ((height * scale) + 0.5f);
17986
17987        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17988                width > 0 ? width : 1, height > 0 ? height : 1, quality);
17989        if (bitmap == null) {
17990            throw new OutOfMemoryError();
17991        }
17992
17993        Resources resources = getResources();
17994        if (resources != null) {
17995            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
17996        }
17997
17998        Canvas canvas;
17999        if (attachInfo != null) {
18000            canvas = attachInfo.mCanvas;
18001            if (canvas == null) {
18002                canvas = new Canvas();
18003            }
18004            canvas.setBitmap(bitmap);
18005            // Temporarily clobber the cached Canvas in case one of our children
18006            // is also using a drawing cache. Without this, the children would
18007            // steal the canvas by attaching their own bitmap to it and bad, bad
18008            // things would happen (invisible views, corrupted drawings, etc.)
18009            attachInfo.mCanvas = null;
18010        } else {
18011            // This case should hopefully never or seldom happen
18012            canvas = new Canvas(bitmap);
18013        }
18014        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18015        canvas.setHwBitmapsInSwModeEnabled(true);
18016        if ((backgroundColor & 0xff000000) != 0) {
18017            bitmap.eraseColor(backgroundColor);
18018        }
18019
18020        computeScroll();
18021        final int restoreCount = canvas.save();
18022        canvas.scale(scale, scale);
18023        canvas.translate(-mScrollX, -mScrollY);
18024
18025        // Temporarily remove the dirty mask
18026        int flags = mPrivateFlags;
18027        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18028
18029        // Fast path for layouts with no backgrounds
18030        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18031            dispatchDraw(canvas);
18032            drawAutofilledHighlight(canvas);
18033            if (mOverlay != null && !mOverlay.isEmpty()) {
18034                mOverlay.getOverlayView().draw(canvas);
18035            }
18036        } else {
18037            draw(canvas);
18038        }
18039
18040        mPrivateFlags = flags;
18041
18042        canvas.restoreToCount(restoreCount);
18043        canvas.setBitmap(null);
18044        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18045
18046        if (attachInfo != null) {
18047            // Restore the cached Canvas for our siblings
18048            attachInfo.mCanvas = canvas;
18049        }
18050
18051        return bitmap;
18052    }
18053
18054    /**
18055     * Indicates whether this View is currently in edit mode. A View is usually
18056     * in edit mode when displayed within a developer tool. For instance, if
18057     * this View is being drawn by a visual user interface builder, this method
18058     * should return true.
18059     *
18060     * Subclasses should check the return value of this method to provide
18061     * different behaviors if their normal behavior might interfere with the
18062     * host environment. For instance: the class spawns a thread in its
18063     * constructor, the drawing code relies on device-specific features, etc.
18064     *
18065     * This method is usually checked in the drawing code of custom widgets.
18066     *
18067     * @return True if this View is in edit mode, false otherwise.
18068     */
18069    public boolean isInEditMode() {
18070        return false;
18071    }
18072
18073    /**
18074     * If the View draws content inside its padding and enables fading edges,
18075     * it needs to support padding offsets. Padding offsets are added to the
18076     * fading edges to extend the length of the fade so that it covers pixels
18077     * drawn inside the padding.
18078     *
18079     * Subclasses of this class should override this method if they need
18080     * to draw content inside the padding.
18081     *
18082     * @return True if padding offset must be applied, false otherwise.
18083     *
18084     * @see #getLeftPaddingOffset()
18085     * @see #getRightPaddingOffset()
18086     * @see #getTopPaddingOffset()
18087     * @see #getBottomPaddingOffset()
18088     *
18089     * @since CURRENT
18090     */
18091    protected boolean isPaddingOffsetRequired() {
18092        return false;
18093    }
18094
18095    /**
18096     * Amount by which to extend the left fading region. Called only when
18097     * {@link #isPaddingOffsetRequired()} returns true.
18098     *
18099     * @return The left padding offset in pixels.
18100     *
18101     * @see #isPaddingOffsetRequired()
18102     *
18103     * @since CURRENT
18104     */
18105    protected int getLeftPaddingOffset() {
18106        return 0;
18107    }
18108
18109    /**
18110     * Amount by which to extend the right fading region. Called only when
18111     * {@link #isPaddingOffsetRequired()} returns true.
18112     *
18113     * @return The right padding offset in pixels.
18114     *
18115     * @see #isPaddingOffsetRequired()
18116     *
18117     * @since CURRENT
18118     */
18119    protected int getRightPaddingOffset() {
18120        return 0;
18121    }
18122
18123    /**
18124     * Amount by which to extend the top fading region. Called only when
18125     * {@link #isPaddingOffsetRequired()} returns true.
18126     *
18127     * @return The top padding offset in pixels.
18128     *
18129     * @see #isPaddingOffsetRequired()
18130     *
18131     * @since CURRENT
18132     */
18133    protected int getTopPaddingOffset() {
18134        return 0;
18135    }
18136
18137    /**
18138     * Amount by which to extend the bottom fading region. Called only when
18139     * {@link #isPaddingOffsetRequired()} returns true.
18140     *
18141     * @return The bottom padding offset in pixels.
18142     *
18143     * @see #isPaddingOffsetRequired()
18144     *
18145     * @since CURRENT
18146     */
18147    protected int getBottomPaddingOffset() {
18148        return 0;
18149    }
18150
18151    /**
18152     * @hide
18153     * @param offsetRequired
18154     */
18155    protected int getFadeTop(boolean offsetRequired) {
18156        int top = mPaddingTop;
18157        if (offsetRequired) top += getTopPaddingOffset();
18158        return top;
18159    }
18160
18161    /**
18162     * @hide
18163     * @param offsetRequired
18164     */
18165    protected int getFadeHeight(boolean offsetRequired) {
18166        int padding = mPaddingTop;
18167        if (offsetRequired) padding += getTopPaddingOffset();
18168        return mBottom - mTop - mPaddingBottom - padding;
18169    }
18170
18171    /**
18172     * <p>Indicates whether this view is attached to a hardware accelerated
18173     * window or not.</p>
18174     *
18175     * <p>Even if this method returns true, it does not mean that every call
18176     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18177     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18178     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18179     * window is hardware accelerated,
18180     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18181     * return false, and this method will return true.</p>
18182     *
18183     * @return True if the view is attached to a window and the window is
18184     *         hardware accelerated; false in any other case.
18185     */
18186    @ViewDebug.ExportedProperty(category = "drawing")
18187    public boolean isHardwareAccelerated() {
18188        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18189    }
18190
18191    /**
18192     * Sets a rectangular area on this view to which the view will be clipped
18193     * when it is drawn. Setting the value to null will remove the clip bounds
18194     * and the view will draw normally, using its full bounds.
18195     *
18196     * @param clipBounds The rectangular area, in the local coordinates of
18197     * this view, to which future drawing operations will be clipped.
18198     */
18199    public void setClipBounds(Rect clipBounds) {
18200        if (clipBounds == mClipBounds
18201                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18202            return;
18203        }
18204        if (clipBounds != null) {
18205            if (mClipBounds == null) {
18206                mClipBounds = new Rect(clipBounds);
18207            } else {
18208                mClipBounds.set(clipBounds);
18209            }
18210        } else {
18211            mClipBounds = null;
18212        }
18213        mRenderNode.setClipBounds(mClipBounds);
18214        invalidateViewProperty(false, false);
18215    }
18216
18217    /**
18218     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18219     *
18220     * @return A copy of the current clip bounds if clip bounds are set,
18221     * otherwise null.
18222     */
18223    public Rect getClipBounds() {
18224        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18225    }
18226
18227
18228    /**
18229     * Populates an output rectangle with the clip bounds of the view,
18230     * returning {@code true} if successful or {@code false} if the view's
18231     * clip bounds are {@code null}.
18232     *
18233     * @param outRect rectangle in which to place the clip bounds of the view
18234     * @return {@code true} if successful or {@code false} if the view's
18235     *         clip bounds are {@code null}
18236     */
18237    public boolean getClipBounds(Rect outRect) {
18238        if (mClipBounds != null) {
18239            outRect.set(mClipBounds);
18240            return true;
18241        }
18242        return false;
18243    }
18244
18245    /**
18246     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18247     * case of an active Animation being run on the view.
18248     */
18249    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18250            Animation a, boolean scalingRequired) {
18251        Transformation invalidationTransform;
18252        final int flags = parent.mGroupFlags;
18253        final boolean initialized = a.isInitialized();
18254        if (!initialized) {
18255            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18256            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18257            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18258            onAnimationStart();
18259        }
18260
18261        final Transformation t = parent.getChildTransformation();
18262        boolean more = a.getTransformation(drawingTime, t, 1f);
18263        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18264            if (parent.mInvalidationTransformation == null) {
18265                parent.mInvalidationTransformation = new Transformation();
18266            }
18267            invalidationTransform = parent.mInvalidationTransformation;
18268            a.getTransformation(drawingTime, invalidationTransform, 1f);
18269        } else {
18270            invalidationTransform = t;
18271        }
18272
18273        if (more) {
18274            if (!a.willChangeBounds()) {
18275                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18276                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18277                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18278                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18279                    // The child need to draw an animation, potentially offscreen, so
18280                    // make sure we do not cancel invalidate requests
18281                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18282                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18283                }
18284            } else {
18285                if (parent.mInvalidateRegion == null) {
18286                    parent.mInvalidateRegion = new RectF();
18287                }
18288                final RectF region = parent.mInvalidateRegion;
18289                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18290                        invalidationTransform);
18291
18292                // The child need to draw an animation, potentially offscreen, so
18293                // make sure we do not cancel invalidate requests
18294                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18295
18296                final int left = mLeft + (int) region.left;
18297                final int top = mTop + (int) region.top;
18298                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18299                        top + (int) (region.height() + .5f));
18300            }
18301        }
18302        return more;
18303    }
18304
18305    /**
18306     * This method is called by getDisplayList() when a display list is recorded for a View.
18307     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18308     */
18309    void setDisplayListProperties(RenderNode renderNode) {
18310        if (renderNode != null) {
18311            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18312            renderNode.setClipToBounds(mParent instanceof ViewGroup
18313                    && ((ViewGroup) mParent).getClipChildren());
18314
18315            float alpha = 1;
18316            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18317                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18318                ViewGroup parentVG = (ViewGroup) mParent;
18319                final Transformation t = parentVG.getChildTransformation();
18320                if (parentVG.getChildStaticTransformation(this, t)) {
18321                    final int transformType = t.getTransformationType();
18322                    if (transformType != Transformation.TYPE_IDENTITY) {
18323                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18324                            alpha = t.getAlpha();
18325                        }
18326                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18327                            renderNode.setStaticMatrix(t.getMatrix());
18328                        }
18329                    }
18330                }
18331            }
18332            if (mTransformationInfo != null) {
18333                alpha *= getFinalAlpha();
18334                if (alpha < 1) {
18335                    final int multipliedAlpha = (int) (255 * alpha);
18336                    if (onSetAlpha(multipliedAlpha)) {
18337                        alpha = 1;
18338                    }
18339                }
18340                renderNode.setAlpha(alpha);
18341            } else if (alpha < 1) {
18342                renderNode.setAlpha(alpha);
18343            }
18344        }
18345    }
18346
18347    /**
18348     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18349     *
18350     * This is where the View specializes rendering behavior based on layer type,
18351     * and hardware acceleration.
18352     */
18353    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18354        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18355        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18356         *
18357         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18358         * HW accelerated, it can't handle drawing RenderNodes.
18359         */
18360        boolean drawingWithRenderNode = mAttachInfo != null
18361                && mAttachInfo.mHardwareAccelerated
18362                && hardwareAcceleratedCanvas;
18363
18364        boolean more = false;
18365        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18366        final int parentFlags = parent.mGroupFlags;
18367
18368        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18369            parent.getChildTransformation().clear();
18370            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18371        }
18372
18373        Transformation transformToApply = null;
18374        boolean concatMatrix = false;
18375        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18376        final Animation a = getAnimation();
18377        if (a != null) {
18378            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18379            concatMatrix = a.willChangeTransformationMatrix();
18380            if (concatMatrix) {
18381                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18382            }
18383            transformToApply = parent.getChildTransformation();
18384        } else {
18385            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18386                // No longer animating: clear out old animation matrix
18387                mRenderNode.setAnimationMatrix(null);
18388                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18389            }
18390            if (!drawingWithRenderNode
18391                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18392                final Transformation t = parent.getChildTransformation();
18393                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18394                if (hasTransform) {
18395                    final int transformType = t.getTransformationType();
18396                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18397                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18398                }
18399            }
18400        }
18401
18402        concatMatrix |= !childHasIdentityMatrix;
18403
18404        // Sets the flag as early as possible to allow draw() implementations
18405        // to call invalidate() successfully when doing animations
18406        mPrivateFlags |= PFLAG_DRAWN;
18407
18408        if (!concatMatrix &&
18409                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18410                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18411                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18412                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18413            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18414            return more;
18415        }
18416        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18417
18418        if (hardwareAcceleratedCanvas) {
18419            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18420            // retain the flag's value temporarily in the mRecreateDisplayList flag
18421            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18422            mPrivateFlags &= ~PFLAG_INVALIDATED;
18423        }
18424
18425        RenderNode renderNode = null;
18426        Bitmap cache = null;
18427        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18428        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18429             if (layerType != LAYER_TYPE_NONE) {
18430                 // If not drawing with RenderNode, treat HW layers as SW
18431                 layerType = LAYER_TYPE_SOFTWARE;
18432                 buildDrawingCache(true);
18433            }
18434            cache = getDrawingCache(true);
18435        }
18436
18437        if (drawingWithRenderNode) {
18438            // Delay getting the display list until animation-driven alpha values are
18439            // set up and possibly passed on to the view
18440            renderNode = updateDisplayListIfDirty();
18441            if (!renderNode.isValid()) {
18442                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18443                // to getDisplayList(), the display list will be marked invalid and we should not
18444                // try to use it again.
18445                renderNode = null;
18446                drawingWithRenderNode = false;
18447            }
18448        }
18449
18450        int sx = 0;
18451        int sy = 0;
18452        if (!drawingWithRenderNode) {
18453            computeScroll();
18454            sx = mScrollX;
18455            sy = mScrollY;
18456        }
18457
18458        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18459        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18460
18461        int restoreTo = -1;
18462        if (!drawingWithRenderNode || transformToApply != null) {
18463            restoreTo = canvas.save();
18464        }
18465        if (offsetForScroll) {
18466            canvas.translate(mLeft - sx, mTop - sy);
18467        } else {
18468            if (!drawingWithRenderNode) {
18469                canvas.translate(mLeft, mTop);
18470            }
18471            if (scalingRequired) {
18472                if (drawingWithRenderNode) {
18473                    // TODO: Might not need this if we put everything inside the DL
18474                    restoreTo = canvas.save();
18475                }
18476                // mAttachInfo cannot be null, otherwise scalingRequired == false
18477                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18478                canvas.scale(scale, scale);
18479            }
18480        }
18481
18482        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18483        if (transformToApply != null
18484                || alpha < 1
18485                || !hasIdentityMatrix()
18486                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18487            if (transformToApply != null || !childHasIdentityMatrix) {
18488                int transX = 0;
18489                int transY = 0;
18490
18491                if (offsetForScroll) {
18492                    transX = -sx;
18493                    transY = -sy;
18494                }
18495
18496                if (transformToApply != null) {
18497                    if (concatMatrix) {
18498                        if (drawingWithRenderNode) {
18499                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18500                        } else {
18501                            // Undo the scroll translation, apply the transformation matrix,
18502                            // then redo the scroll translate to get the correct result.
18503                            canvas.translate(-transX, -transY);
18504                            canvas.concat(transformToApply.getMatrix());
18505                            canvas.translate(transX, transY);
18506                        }
18507                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18508                    }
18509
18510                    float transformAlpha = transformToApply.getAlpha();
18511                    if (transformAlpha < 1) {
18512                        alpha *= transformAlpha;
18513                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18514                    }
18515                }
18516
18517                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18518                    canvas.translate(-transX, -transY);
18519                    canvas.concat(getMatrix());
18520                    canvas.translate(transX, transY);
18521                }
18522            }
18523
18524            // Deal with alpha if it is or used to be <1
18525            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18526                if (alpha < 1) {
18527                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18528                } else {
18529                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18530                }
18531                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18532                if (!drawingWithDrawingCache) {
18533                    final int multipliedAlpha = (int) (255 * alpha);
18534                    if (!onSetAlpha(multipliedAlpha)) {
18535                        if (drawingWithRenderNode) {
18536                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18537                        } else if (layerType == LAYER_TYPE_NONE) {
18538                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18539                                    multipliedAlpha);
18540                        }
18541                    } else {
18542                        // Alpha is handled by the child directly, clobber the layer's alpha
18543                        mPrivateFlags |= PFLAG_ALPHA_SET;
18544                    }
18545                }
18546            }
18547        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18548            onSetAlpha(255);
18549            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18550        }
18551
18552        if (!drawingWithRenderNode) {
18553            // apply clips directly, since RenderNode won't do it for this draw
18554            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18555                if (offsetForScroll) {
18556                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18557                } else {
18558                    if (!scalingRequired || cache == null) {
18559                        canvas.clipRect(0, 0, getWidth(), getHeight());
18560                    } else {
18561                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18562                    }
18563                }
18564            }
18565
18566            if (mClipBounds != null) {
18567                // clip bounds ignore scroll
18568                canvas.clipRect(mClipBounds);
18569            }
18570        }
18571
18572        if (!drawingWithDrawingCache) {
18573            if (drawingWithRenderNode) {
18574                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18575                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18576            } else {
18577                // Fast path for layouts with no backgrounds
18578                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18579                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18580                    dispatchDraw(canvas);
18581                } else {
18582                    draw(canvas);
18583                }
18584            }
18585        } else if (cache != null) {
18586            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18587            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18588                // no layer paint, use temporary paint to draw bitmap
18589                Paint cachePaint = parent.mCachePaint;
18590                if (cachePaint == null) {
18591                    cachePaint = new Paint();
18592                    cachePaint.setDither(false);
18593                    parent.mCachePaint = cachePaint;
18594                }
18595                cachePaint.setAlpha((int) (alpha * 255));
18596                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18597            } else {
18598                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18599                int layerPaintAlpha = mLayerPaint.getAlpha();
18600                if (alpha < 1) {
18601                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18602                }
18603                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18604                if (alpha < 1) {
18605                    mLayerPaint.setAlpha(layerPaintAlpha);
18606                }
18607            }
18608        }
18609
18610        if (restoreTo >= 0) {
18611            canvas.restoreToCount(restoreTo);
18612        }
18613
18614        if (a != null && !more) {
18615            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18616                onSetAlpha(255);
18617            }
18618            parent.finishAnimatingView(this, a);
18619        }
18620
18621        if (more && hardwareAcceleratedCanvas) {
18622            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18623                // alpha animations should cause the child to recreate its display list
18624                invalidate(true);
18625            }
18626        }
18627
18628        mRecreateDisplayList = false;
18629
18630        return more;
18631    }
18632
18633    static Paint getDebugPaint() {
18634        if (sDebugPaint == null) {
18635            sDebugPaint = new Paint();
18636            sDebugPaint.setAntiAlias(false);
18637        }
18638        return sDebugPaint;
18639    }
18640
18641    final int dipsToPixels(int dips) {
18642        float scale = getContext().getResources().getDisplayMetrics().density;
18643        return (int) (dips * scale + 0.5f);
18644    }
18645
18646    final private void debugDrawFocus(Canvas canvas) {
18647        if (isFocused()) {
18648            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18649            final int l = mScrollX;
18650            final int r = l + mRight - mLeft;
18651            final int t = mScrollY;
18652            final int b = t + mBottom - mTop;
18653
18654            final Paint paint = getDebugPaint();
18655            paint.setColor(DEBUG_CORNERS_COLOR);
18656
18657            // Draw squares in corners.
18658            paint.setStyle(Paint.Style.FILL);
18659            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18660            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18661            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18662            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18663
18664            // Draw big X across the view.
18665            paint.setStyle(Paint.Style.STROKE);
18666            canvas.drawLine(l, t, r, b, paint);
18667            canvas.drawLine(l, b, r, t, paint);
18668        }
18669    }
18670
18671    /**
18672     * Manually render this view (and all of its children) to the given Canvas.
18673     * The view must have already done a full layout before this function is
18674     * called.  When implementing a view, implement
18675     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18676     * If you do need to override this method, call the superclass version.
18677     *
18678     * @param canvas The Canvas to which the View is rendered.
18679     */
18680    @CallSuper
18681    public void draw(Canvas canvas) {
18682        final int privateFlags = mPrivateFlags;
18683        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18684                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18685        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18686
18687        /*
18688         * Draw traversal performs several drawing steps which must be executed
18689         * in the appropriate order:
18690         *
18691         *      1. Draw the background
18692         *      2. If necessary, save the canvas' layers to prepare for fading
18693         *      3. Draw view's content
18694         *      4. Draw children
18695         *      5. If necessary, draw the fading edges and restore layers
18696         *      6. Draw decorations (scrollbars for instance)
18697         */
18698
18699        // Step 1, draw the background, if needed
18700        int saveCount;
18701
18702        if (!dirtyOpaque) {
18703            drawBackground(canvas);
18704        }
18705
18706        // skip step 2 & 5 if possible (common case)
18707        final int viewFlags = mViewFlags;
18708        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18709        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18710        if (!verticalEdges && !horizontalEdges) {
18711            // Step 3, draw the content
18712            if (!dirtyOpaque) onDraw(canvas);
18713
18714            // Step 4, draw the children
18715            dispatchDraw(canvas);
18716
18717            drawAutofilledHighlight(canvas);
18718
18719            // Overlay is part of the content and draws beneath Foreground
18720            if (mOverlay != null && !mOverlay.isEmpty()) {
18721                mOverlay.getOverlayView().dispatchDraw(canvas);
18722            }
18723
18724            // Step 6, draw decorations (foreground, scrollbars)
18725            onDrawForeground(canvas);
18726
18727            // Step 7, draw the default focus highlight
18728            drawDefaultFocusHighlight(canvas);
18729
18730            if (debugDraw()) {
18731                debugDrawFocus(canvas);
18732            }
18733
18734            // we're done...
18735            return;
18736        }
18737
18738        /*
18739         * Here we do the full fledged routine...
18740         * (this is an uncommon case where speed matters less,
18741         * this is why we repeat some of the tests that have been
18742         * done above)
18743         */
18744
18745        boolean drawTop = false;
18746        boolean drawBottom = false;
18747        boolean drawLeft = false;
18748        boolean drawRight = false;
18749
18750        float topFadeStrength = 0.0f;
18751        float bottomFadeStrength = 0.0f;
18752        float leftFadeStrength = 0.0f;
18753        float rightFadeStrength = 0.0f;
18754
18755        // Step 2, save the canvas' layers
18756        int paddingLeft = mPaddingLeft;
18757
18758        final boolean offsetRequired = isPaddingOffsetRequired();
18759        if (offsetRequired) {
18760            paddingLeft += getLeftPaddingOffset();
18761        }
18762
18763        int left = mScrollX + paddingLeft;
18764        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18765        int top = mScrollY + getFadeTop(offsetRequired);
18766        int bottom = top + getFadeHeight(offsetRequired);
18767
18768        if (offsetRequired) {
18769            right += getRightPaddingOffset();
18770            bottom += getBottomPaddingOffset();
18771        }
18772
18773        final ScrollabilityCache scrollabilityCache = mScrollCache;
18774        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18775        int length = (int) fadeHeight;
18776
18777        // clip the fade length if top and bottom fades overlap
18778        // overlapping fades produce odd-looking artifacts
18779        if (verticalEdges && (top + length > bottom - length)) {
18780            length = (bottom - top) / 2;
18781        }
18782
18783        // also clip horizontal fades if necessary
18784        if (horizontalEdges && (left + length > right - length)) {
18785            length = (right - left) / 2;
18786        }
18787
18788        if (verticalEdges) {
18789            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18790            drawTop = topFadeStrength * fadeHeight > 1.0f;
18791            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18792            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18793        }
18794
18795        if (horizontalEdges) {
18796            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18797            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18798            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18799            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18800        }
18801
18802        saveCount = canvas.getSaveCount();
18803
18804        int solidColor = getSolidColor();
18805        if (solidColor == 0) {
18806            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18807
18808            if (drawTop) {
18809                canvas.saveLayer(left, top, right, top + length, null, flags);
18810            }
18811
18812            if (drawBottom) {
18813                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18814            }
18815
18816            if (drawLeft) {
18817                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18818            }
18819
18820            if (drawRight) {
18821                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18822            }
18823        } else {
18824            scrollabilityCache.setFadeColor(solidColor);
18825        }
18826
18827        // Step 3, draw the content
18828        if (!dirtyOpaque) onDraw(canvas);
18829
18830        // Step 4, draw the children
18831        dispatchDraw(canvas);
18832
18833        // Step 5, draw the fade effect and restore layers
18834        final Paint p = scrollabilityCache.paint;
18835        final Matrix matrix = scrollabilityCache.matrix;
18836        final Shader fade = scrollabilityCache.shader;
18837
18838        if (drawTop) {
18839            matrix.setScale(1, fadeHeight * topFadeStrength);
18840            matrix.postTranslate(left, top);
18841            fade.setLocalMatrix(matrix);
18842            p.setShader(fade);
18843            canvas.drawRect(left, top, right, top + length, p);
18844        }
18845
18846        if (drawBottom) {
18847            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18848            matrix.postRotate(180);
18849            matrix.postTranslate(left, bottom);
18850            fade.setLocalMatrix(matrix);
18851            p.setShader(fade);
18852            canvas.drawRect(left, bottom - length, right, bottom, p);
18853        }
18854
18855        if (drawLeft) {
18856            matrix.setScale(1, fadeHeight * leftFadeStrength);
18857            matrix.postRotate(-90);
18858            matrix.postTranslate(left, top);
18859            fade.setLocalMatrix(matrix);
18860            p.setShader(fade);
18861            canvas.drawRect(left, top, left + length, bottom, p);
18862        }
18863
18864        if (drawRight) {
18865            matrix.setScale(1, fadeHeight * rightFadeStrength);
18866            matrix.postRotate(90);
18867            matrix.postTranslate(right, top);
18868            fade.setLocalMatrix(matrix);
18869            p.setShader(fade);
18870            canvas.drawRect(right - length, top, right, bottom, p);
18871        }
18872
18873        canvas.restoreToCount(saveCount);
18874
18875        drawAutofilledHighlight(canvas);
18876
18877        // Overlay is part of the content and draws beneath Foreground
18878        if (mOverlay != null && !mOverlay.isEmpty()) {
18879            mOverlay.getOverlayView().dispatchDraw(canvas);
18880        }
18881
18882        // Step 6, draw decorations (foreground, scrollbars)
18883        onDrawForeground(canvas);
18884
18885        if (debugDraw()) {
18886            debugDrawFocus(canvas);
18887        }
18888    }
18889
18890    /**
18891     * Draws the background onto the specified canvas.
18892     *
18893     * @param canvas Canvas on which to draw the background
18894     */
18895    private void drawBackground(Canvas canvas) {
18896        final Drawable background = mBackground;
18897        if (background == null) {
18898            return;
18899        }
18900
18901        setBackgroundBounds();
18902
18903        // Attempt to use a display list if requested.
18904        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18905                && mAttachInfo.mThreadedRenderer != null) {
18906            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18907
18908            final RenderNode renderNode = mBackgroundRenderNode;
18909            if (renderNode != null && renderNode.isValid()) {
18910                setBackgroundRenderNodeProperties(renderNode);
18911                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18912                return;
18913            }
18914        }
18915
18916        final int scrollX = mScrollX;
18917        final int scrollY = mScrollY;
18918        if ((scrollX | scrollY) == 0) {
18919            background.draw(canvas);
18920        } else {
18921            canvas.translate(scrollX, scrollY);
18922            background.draw(canvas);
18923            canvas.translate(-scrollX, -scrollY);
18924        }
18925    }
18926
18927    /**
18928     * Sets the correct background bounds and rebuilds the outline, if needed.
18929     * <p/>
18930     * This is called by LayoutLib.
18931     */
18932    void setBackgroundBounds() {
18933        if (mBackgroundSizeChanged && mBackground != null) {
18934            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18935            mBackgroundSizeChanged = false;
18936            rebuildOutline();
18937        }
18938    }
18939
18940    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18941        renderNode.setTranslationX(mScrollX);
18942        renderNode.setTranslationY(mScrollY);
18943    }
18944
18945    /**
18946     * Creates a new display list or updates the existing display list for the
18947     * specified Drawable.
18948     *
18949     * @param drawable Drawable for which to create a display list
18950     * @param renderNode Existing RenderNode, or {@code null}
18951     * @return A valid display list for the specified drawable
18952     */
18953    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18954        if (renderNode == null) {
18955            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18956        }
18957
18958        final Rect bounds = drawable.getBounds();
18959        final int width = bounds.width();
18960        final int height = bounds.height();
18961        final DisplayListCanvas canvas = renderNode.start(width, height);
18962
18963        // Reverse left/top translation done by drawable canvas, which will
18964        // instead be applied by rendernode's LTRB bounds below. This way, the
18965        // drawable's bounds match with its rendernode bounds and its content
18966        // will lie within those bounds in the rendernode tree.
18967        canvas.translate(-bounds.left, -bounds.top);
18968
18969        try {
18970            drawable.draw(canvas);
18971        } finally {
18972            renderNode.end(canvas);
18973        }
18974
18975        // Set up drawable properties that are view-independent.
18976        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18977        renderNode.setProjectBackwards(drawable.isProjected());
18978        renderNode.setProjectionReceiver(true);
18979        renderNode.setClipToBounds(false);
18980        return renderNode;
18981    }
18982
18983    /**
18984     * Returns the overlay for this view, creating it if it does not yet exist.
18985     * Adding drawables to the overlay will cause them to be displayed whenever
18986     * the view itself is redrawn. Objects in the overlay should be actively
18987     * managed: remove them when they should not be displayed anymore. The
18988     * overlay will always have the same size as its host view.
18989     *
18990     * <p>Note: Overlays do not currently work correctly with {@link
18991     * SurfaceView} or {@link TextureView}; contents in overlays for these
18992     * types of views may not display correctly.</p>
18993     *
18994     * @return The ViewOverlay object for this view.
18995     * @see ViewOverlay
18996     */
18997    public ViewOverlay getOverlay() {
18998        if (mOverlay == null) {
18999            mOverlay = new ViewOverlay(mContext, this);
19000        }
19001        return mOverlay;
19002    }
19003
19004    /**
19005     * Override this if your view is known to always be drawn on top of a solid color background,
19006     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19007     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19008     * should be set to 0xFF.
19009     *
19010     * @see #setVerticalFadingEdgeEnabled(boolean)
19011     * @see #setHorizontalFadingEdgeEnabled(boolean)
19012     *
19013     * @return The known solid color background for this view, or 0 if the color may vary
19014     */
19015    @ViewDebug.ExportedProperty(category = "drawing")
19016    @ColorInt
19017    public int getSolidColor() {
19018        return 0;
19019    }
19020
19021    /**
19022     * Build a human readable string representation of the specified view flags.
19023     *
19024     * @param flags the view flags to convert to a string
19025     * @return a String representing the supplied flags
19026     */
19027    private static String printFlags(int flags) {
19028        String output = "";
19029        int numFlags = 0;
19030        if ((flags & FOCUSABLE) == FOCUSABLE) {
19031            output += "TAKES_FOCUS";
19032            numFlags++;
19033        }
19034
19035        switch (flags & VISIBILITY_MASK) {
19036        case INVISIBLE:
19037            if (numFlags > 0) {
19038                output += " ";
19039            }
19040            output += "INVISIBLE";
19041            // USELESS HERE numFlags++;
19042            break;
19043        case GONE:
19044            if (numFlags > 0) {
19045                output += " ";
19046            }
19047            output += "GONE";
19048            // USELESS HERE numFlags++;
19049            break;
19050        default:
19051            break;
19052        }
19053        return output;
19054    }
19055
19056    /**
19057     * Build a human readable string representation of the specified private
19058     * view flags.
19059     *
19060     * @param privateFlags the private view flags to convert to a string
19061     * @return a String representing the supplied flags
19062     */
19063    private static String printPrivateFlags(int privateFlags) {
19064        String output = "";
19065        int numFlags = 0;
19066
19067        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19068            output += "WANTS_FOCUS";
19069            numFlags++;
19070        }
19071
19072        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19073            if (numFlags > 0) {
19074                output += " ";
19075            }
19076            output += "FOCUSED";
19077            numFlags++;
19078        }
19079
19080        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19081            if (numFlags > 0) {
19082                output += " ";
19083            }
19084            output += "SELECTED";
19085            numFlags++;
19086        }
19087
19088        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19089            if (numFlags > 0) {
19090                output += " ";
19091            }
19092            output += "IS_ROOT_NAMESPACE";
19093            numFlags++;
19094        }
19095
19096        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19097            if (numFlags > 0) {
19098                output += " ";
19099            }
19100            output += "HAS_BOUNDS";
19101            numFlags++;
19102        }
19103
19104        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19105            if (numFlags > 0) {
19106                output += " ";
19107            }
19108            output += "DRAWN";
19109            // USELESS HERE numFlags++;
19110        }
19111        return output;
19112    }
19113
19114    /**
19115     * <p>Indicates whether or not this view's layout will be requested during
19116     * the next hierarchy layout pass.</p>
19117     *
19118     * @return true if the layout will be forced during next layout pass
19119     */
19120    public boolean isLayoutRequested() {
19121        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19122    }
19123
19124    /**
19125     * Return true if o is a ViewGroup that is laying out using optical bounds.
19126     * @hide
19127     */
19128    public static boolean isLayoutModeOptical(Object o) {
19129        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19130    }
19131
19132    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19133        Insets parentInsets = mParent instanceof View ?
19134                ((View) mParent).getOpticalInsets() : Insets.NONE;
19135        Insets childInsets = getOpticalInsets();
19136        return setFrame(
19137                left   + parentInsets.left - childInsets.left,
19138                top    + parentInsets.top  - childInsets.top,
19139                right  + parentInsets.left + childInsets.right,
19140                bottom + parentInsets.top  + childInsets.bottom);
19141    }
19142
19143    /**
19144     * Assign a size and position to a view and all of its
19145     * descendants
19146     *
19147     * <p>This is the second phase of the layout mechanism.
19148     * (The first is measuring). In this phase, each parent calls
19149     * layout on all of its children to position them.
19150     * This is typically done using the child measurements
19151     * that were stored in the measure pass().</p>
19152     *
19153     * <p>Derived classes should not override this method.
19154     * Derived classes with children should override
19155     * onLayout. In that method, they should
19156     * call layout on each of their children.</p>
19157     *
19158     * @param l Left position, relative to parent
19159     * @param t Top position, relative to parent
19160     * @param r Right position, relative to parent
19161     * @param b Bottom position, relative to parent
19162     */
19163    @SuppressWarnings({"unchecked"})
19164    public void layout(int l, int t, int r, int b) {
19165        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19166            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19167            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19168        }
19169
19170        int oldL = mLeft;
19171        int oldT = mTop;
19172        int oldB = mBottom;
19173        int oldR = mRight;
19174
19175        boolean changed = isLayoutModeOptical(mParent) ?
19176                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19177
19178        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19179            onLayout(changed, l, t, r, b);
19180
19181            if (shouldDrawRoundScrollbar()) {
19182                if(mRoundScrollbarRenderer == null) {
19183                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19184                }
19185            } else {
19186                mRoundScrollbarRenderer = null;
19187            }
19188
19189            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19190
19191            ListenerInfo li = mListenerInfo;
19192            if (li != null && li.mOnLayoutChangeListeners != null) {
19193                ArrayList<OnLayoutChangeListener> listenersCopy =
19194                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19195                int numListeners = listenersCopy.size();
19196                for (int i = 0; i < numListeners; ++i) {
19197                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19198                }
19199            }
19200        }
19201
19202        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19203        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19204    }
19205
19206    /**
19207     * Called from layout when this view should
19208     * assign a size and position to each of its children.
19209     *
19210     * Derived classes with children should override
19211     * this method and call layout on each of
19212     * their children.
19213     * @param changed This is a new size or position for this view
19214     * @param left Left position, relative to parent
19215     * @param top Top position, relative to parent
19216     * @param right Right position, relative to parent
19217     * @param bottom Bottom position, relative to parent
19218     */
19219    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19220    }
19221
19222    /**
19223     * Assign a size and position to this view.
19224     *
19225     * This is called from layout.
19226     *
19227     * @param left Left position, relative to parent
19228     * @param top Top position, relative to parent
19229     * @param right Right position, relative to parent
19230     * @param bottom Bottom position, relative to parent
19231     * @return true if the new size and position are different than the
19232     *         previous ones
19233     * {@hide}
19234     */
19235    protected boolean setFrame(int left, int top, int right, int bottom) {
19236        boolean changed = false;
19237
19238        if (DBG) {
19239            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19240                    + right + "," + bottom + ")");
19241        }
19242
19243        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19244            changed = true;
19245
19246            // Remember our drawn bit
19247            int drawn = mPrivateFlags & PFLAG_DRAWN;
19248
19249            int oldWidth = mRight - mLeft;
19250            int oldHeight = mBottom - mTop;
19251            int newWidth = right - left;
19252            int newHeight = bottom - top;
19253            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19254
19255            // Invalidate our old position
19256            invalidate(sizeChanged);
19257
19258            mLeft = left;
19259            mTop = top;
19260            mRight = right;
19261            mBottom = bottom;
19262            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19263
19264            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19265
19266
19267            if (sizeChanged) {
19268                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19269            }
19270
19271            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19272                // If we are visible, force the DRAWN bit to on so that
19273                // this invalidate will go through (at least to our parent).
19274                // This is because someone may have invalidated this view
19275                // before this call to setFrame came in, thereby clearing
19276                // the DRAWN bit.
19277                mPrivateFlags |= PFLAG_DRAWN;
19278                invalidate(sizeChanged);
19279                // parent display list may need to be recreated based on a change in the bounds
19280                // of any child
19281                invalidateParentCaches();
19282            }
19283
19284            // Reset drawn bit to original value (invalidate turns it off)
19285            mPrivateFlags |= drawn;
19286
19287            mBackgroundSizeChanged = true;
19288            mDefaultFocusHighlightSizeChanged = true;
19289            if (mForegroundInfo != null) {
19290                mForegroundInfo.mBoundsChanged = true;
19291            }
19292
19293            notifySubtreeAccessibilityStateChangedIfNeeded();
19294        }
19295        return changed;
19296    }
19297
19298    /**
19299     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19300     * @hide
19301     */
19302    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19303        setFrame(left, top, right, bottom);
19304    }
19305
19306    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19307        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19308        if (mOverlay != null) {
19309            mOverlay.getOverlayView().setRight(newWidth);
19310            mOverlay.getOverlayView().setBottom(newHeight);
19311        }
19312        rebuildOutline();
19313    }
19314
19315    /**
19316     * Finalize inflating a view from XML.  This is called as the last phase
19317     * of inflation, after all child views have been added.
19318     *
19319     * <p>Even if the subclass overrides onFinishInflate, they should always be
19320     * sure to call the super method, so that we get called.
19321     */
19322    @CallSuper
19323    protected void onFinishInflate() {
19324    }
19325
19326    /**
19327     * Returns the resources associated with this view.
19328     *
19329     * @return Resources object.
19330     */
19331    public Resources getResources() {
19332        return mResources;
19333    }
19334
19335    /**
19336     * Invalidates the specified Drawable.
19337     *
19338     * @param drawable the drawable to invalidate
19339     */
19340    @Override
19341    public void invalidateDrawable(@NonNull Drawable drawable) {
19342        if (verifyDrawable(drawable)) {
19343            final Rect dirty = drawable.getDirtyBounds();
19344            final int scrollX = mScrollX;
19345            final int scrollY = mScrollY;
19346
19347            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19348                    dirty.right + scrollX, dirty.bottom + scrollY);
19349            rebuildOutline();
19350        }
19351    }
19352
19353    /**
19354     * Schedules an action on a drawable to occur at a specified time.
19355     *
19356     * @param who the recipient of the action
19357     * @param what the action to run on the drawable
19358     * @param when the time at which the action must occur. Uses the
19359     *        {@link SystemClock#uptimeMillis} timebase.
19360     */
19361    @Override
19362    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19363        if (verifyDrawable(who) && what != null) {
19364            final long delay = when - SystemClock.uptimeMillis();
19365            if (mAttachInfo != null) {
19366                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19367                        Choreographer.CALLBACK_ANIMATION, what, who,
19368                        Choreographer.subtractFrameDelay(delay));
19369            } else {
19370                // Postpone the runnable until we know
19371                // on which thread it needs to run.
19372                getRunQueue().postDelayed(what, delay);
19373            }
19374        }
19375    }
19376
19377    /**
19378     * Cancels a scheduled action on a drawable.
19379     *
19380     * @param who the recipient of the action
19381     * @param what the action to cancel
19382     */
19383    @Override
19384    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19385        if (verifyDrawable(who) && what != null) {
19386            if (mAttachInfo != null) {
19387                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19388                        Choreographer.CALLBACK_ANIMATION, what, who);
19389            }
19390            getRunQueue().removeCallbacks(what);
19391        }
19392    }
19393
19394    /**
19395     * Unschedule any events associated with the given Drawable.  This can be
19396     * used when selecting a new Drawable into a view, so that the previous
19397     * one is completely unscheduled.
19398     *
19399     * @param who The Drawable to unschedule.
19400     *
19401     * @see #drawableStateChanged
19402     */
19403    public void unscheduleDrawable(Drawable who) {
19404        if (mAttachInfo != null && who != null) {
19405            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19406                    Choreographer.CALLBACK_ANIMATION, null, who);
19407        }
19408    }
19409
19410    /**
19411     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19412     * that the View directionality can and will be resolved before its Drawables.
19413     *
19414     * Will call {@link View#onResolveDrawables} when resolution is done.
19415     *
19416     * @hide
19417     */
19418    protected void resolveDrawables() {
19419        // Drawables resolution may need to happen before resolving the layout direction (which is
19420        // done only during the measure() call).
19421        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19422        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19423        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19424        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19425        // direction to be resolved as its resolved value will be the same as its raw value.
19426        if (!isLayoutDirectionResolved() &&
19427                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19428            return;
19429        }
19430
19431        final int layoutDirection = isLayoutDirectionResolved() ?
19432                getLayoutDirection() : getRawLayoutDirection();
19433
19434        if (mBackground != null) {
19435            mBackground.setLayoutDirection(layoutDirection);
19436        }
19437        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19438            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19439        }
19440        if (mDefaultFocusHighlight != null) {
19441            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19442        }
19443        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19444        onResolveDrawables(layoutDirection);
19445    }
19446
19447    boolean areDrawablesResolved() {
19448        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19449    }
19450
19451    /**
19452     * Called when layout direction has been resolved.
19453     *
19454     * The default implementation does nothing.
19455     *
19456     * @param layoutDirection The resolved layout direction.
19457     *
19458     * @see #LAYOUT_DIRECTION_LTR
19459     * @see #LAYOUT_DIRECTION_RTL
19460     *
19461     * @hide
19462     */
19463    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19464    }
19465
19466    /**
19467     * @hide
19468     */
19469    protected void resetResolvedDrawables() {
19470        resetResolvedDrawablesInternal();
19471    }
19472
19473    void resetResolvedDrawablesInternal() {
19474        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19475    }
19476
19477    /**
19478     * If your view subclass is displaying its own Drawable objects, it should
19479     * override this function and return true for any Drawable it is
19480     * displaying.  This allows animations for those drawables to be
19481     * scheduled.
19482     *
19483     * <p>Be sure to call through to the super class when overriding this
19484     * function.
19485     *
19486     * @param who The Drawable to verify.  Return true if it is one you are
19487     *            displaying, else return the result of calling through to the
19488     *            super class.
19489     *
19490     * @return boolean If true than the Drawable is being displayed in the
19491     *         view; else false and it is not allowed to animate.
19492     *
19493     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19494     * @see #drawableStateChanged()
19495     */
19496    @CallSuper
19497    protected boolean verifyDrawable(@NonNull Drawable who) {
19498        // Avoid verifying the scroll bar drawable so that we don't end up in
19499        // an invalidation loop. This effectively prevents the scroll bar
19500        // drawable from triggering invalidations and scheduling runnables.
19501        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19502                || (mDefaultFocusHighlight == who);
19503    }
19504
19505    /**
19506     * This function is called whenever the state of the view changes in such
19507     * a way that it impacts the state of drawables being shown.
19508     * <p>
19509     * If the View has a StateListAnimator, it will also be called to run necessary state
19510     * change animations.
19511     * <p>
19512     * Be sure to call through to the superclass when overriding this function.
19513     *
19514     * @see Drawable#setState(int[])
19515     */
19516    @CallSuper
19517    protected void drawableStateChanged() {
19518        final int[] state = getDrawableState();
19519        boolean changed = false;
19520
19521        final Drawable bg = mBackground;
19522        if (bg != null && bg.isStateful()) {
19523            changed |= bg.setState(state);
19524        }
19525
19526        final Drawable hl = mDefaultFocusHighlight;
19527        if (hl != null && hl.isStateful()) {
19528            changed |= hl.setState(state);
19529        }
19530
19531        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19532        if (fg != null && fg.isStateful()) {
19533            changed |= fg.setState(state);
19534        }
19535
19536        if (mScrollCache != null) {
19537            final Drawable scrollBar = mScrollCache.scrollBar;
19538            if (scrollBar != null && scrollBar.isStateful()) {
19539                changed |= scrollBar.setState(state)
19540                        && mScrollCache.state != ScrollabilityCache.OFF;
19541            }
19542        }
19543
19544        if (mStateListAnimator != null) {
19545            mStateListAnimator.setState(state);
19546        }
19547
19548        if (changed) {
19549            invalidate();
19550        }
19551    }
19552
19553    /**
19554     * This function is called whenever the view hotspot changes and needs to
19555     * be propagated to drawables or child views managed by the view.
19556     * <p>
19557     * Dispatching to child views is handled by
19558     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19559     * <p>
19560     * Be sure to call through to the superclass when overriding this function.
19561     *
19562     * @param x hotspot x coordinate
19563     * @param y hotspot y coordinate
19564     */
19565    @CallSuper
19566    public void drawableHotspotChanged(float x, float y) {
19567        if (mBackground != null) {
19568            mBackground.setHotspot(x, y);
19569        }
19570        if (mDefaultFocusHighlight != null) {
19571            mDefaultFocusHighlight.setHotspot(x, y);
19572        }
19573        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19574            mForegroundInfo.mDrawable.setHotspot(x, y);
19575        }
19576
19577        dispatchDrawableHotspotChanged(x, y);
19578    }
19579
19580    /**
19581     * Dispatches drawableHotspotChanged to all of this View's children.
19582     *
19583     * @param x hotspot x coordinate
19584     * @param y hotspot y coordinate
19585     * @see #drawableHotspotChanged(float, float)
19586     */
19587    public void dispatchDrawableHotspotChanged(float x, float y) {
19588    }
19589
19590    /**
19591     * Call this to force a view to update its drawable state. This will cause
19592     * drawableStateChanged to be called on this view. Views that are interested
19593     * in the new state should call getDrawableState.
19594     *
19595     * @see #drawableStateChanged
19596     * @see #getDrawableState
19597     */
19598    public void refreshDrawableState() {
19599        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19600        drawableStateChanged();
19601
19602        ViewParent parent = mParent;
19603        if (parent != null) {
19604            parent.childDrawableStateChanged(this);
19605        }
19606    }
19607
19608    /**
19609     * Create a default focus highlight if it doesn't exist.
19610     * @return a default focus highlight.
19611     */
19612    private Drawable getDefaultFocusHighlightDrawable() {
19613        if (mDefaultFocusHighlightCache == null) {
19614            if (mContext != null) {
19615                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
19616                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
19617                mDefaultFocusHighlightCache = ta.getDrawable(0);
19618                ta.recycle();
19619            }
19620        }
19621        return mDefaultFocusHighlightCache;
19622    }
19623
19624    /**
19625     * Set the current default focus highlight.
19626     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
19627     */
19628    private void setDefaultFocusHighlight(Drawable highlight) {
19629        mDefaultFocusHighlight = highlight;
19630        mDefaultFocusHighlightSizeChanged = true;
19631        if (highlight != null) {
19632            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19633                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19634            }
19635            highlight.setLayoutDirection(getLayoutDirection());
19636            if (highlight.isStateful()) {
19637                highlight.setState(getDrawableState());
19638            }
19639            if (isAttachedToWindow()) {
19640                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19641            }
19642            // Set callback last, since the view may still be initializing.
19643            highlight.setCallback(this);
19644        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
19645                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19646            mPrivateFlags |= PFLAG_SKIP_DRAW;
19647        }
19648        requestLayout();
19649        invalidate();
19650    }
19651
19652    /**
19653     * Check whether we need to draw a default focus highlight when this view gets focused,
19654     * which requires:
19655     * <ul>
19656     *     <li>In the background, {@link android.R.attr#state_focused} is not defined.</li>
19657     *     <li>This view is not in touch mode.</li>
19658     *     <li>This view doesn't opt out for a default focus highlight, via
19659     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
19660     *     <li>This view is attached to window.</li>
19661     * </ul>
19662     * @return {@code true} if a default focus highlight is needed.
19663     */
19664    private boolean isDefaultFocusHighlightNeeded(Drawable background) {
19665        final boolean hasFocusStateSpecified = background == null || !background.isStateful()
19666                || !background.hasFocusStateSpecified();
19667        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
19668                && isAttachedToWindow() && sUseDefaultFocusHighlight;
19669    }
19670
19671    /**
19672     * When this view is focused, switches on/off the default focused highlight.
19673     * <p>
19674     * This always happens when this view is focused, and only at this moment the default focus
19675     * highlight can be visible.
19676     */
19677    private void switchDefaultFocusHighlight() {
19678        if (isFocused()) {
19679            final boolean needed = isDefaultFocusHighlightNeeded(mBackground);
19680            final boolean active = mDefaultFocusHighlight != null;
19681            if (needed && !active) {
19682                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
19683            } else if (!needed && active) {
19684                // The highlight is no longer needed, so tear it down.
19685                setDefaultFocusHighlight(null);
19686            }
19687        }
19688    }
19689
19690    /**
19691     * Draw the default focus highlight onto the canvas.
19692     * @param canvas the canvas where we're drawing the highlight.
19693     */
19694    private void drawDefaultFocusHighlight(Canvas canvas) {
19695        if (mDefaultFocusHighlight != null) {
19696            if (mDefaultFocusHighlightSizeChanged) {
19697                mDefaultFocusHighlightSizeChanged = false;
19698                final int l = mScrollX;
19699                final int r = l + mRight - mLeft;
19700                final int t = mScrollY;
19701                final int b = t + mBottom - mTop;
19702                mDefaultFocusHighlight.setBounds(l, t, r, b);
19703            }
19704            mDefaultFocusHighlight.draw(canvas);
19705        }
19706    }
19707
19708    /**
19709     * Return an array of resource IDs of the drawable states representing the
19710     * current state of the view.
19711     *
19712     * @return The current drawable state
19713     *
19714     * @see Drawable#setState(int[])
19715     * @see #drawableStateChanged()
19716     * @see #onCreateDrawableState(int)
19717     */
19718    public final int[] getDrawableState() {
19719        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19720            return mDrawableState;
19721        } else {
19722            mDrawableState = onCreateDrawableState(0);
19723            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19724            return mDrawableState;
19725        }
19726    }
19727
19728    /**
19729     * Generate the new {@link android.graphics.drawable.Drawable} state for
19730     * this view. This is called by the view
19731     * system when the cached Drawable state is determined to be invalid.  To
19732     * retrieve the current state, you should use {@link #getDrawableState}.
19733     *
19734     * @param extraSpace if non-zero, this is the number of extra entries you
19735     * would like in the returned array in which you can place your own
19736     * states.
19737     *
19738     * @return Returns an array holding the current {@link Drawable} state of
19739     * the view.
19740     *
19741     * @see #mergeDrawableStates(int[], int[])
19742     */
19743    protected int[] onCreateDrawableState(int extraSpace) {
19744        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19745                mParent instanceof View) {
19746            return ((View) mParent).onCreateDrawableState(extraSpace);
19747        }
19748
19749        int[] drawableState;
19750
19751        int privateFlags = mPrivateFlags;
19752
19753        int viewStateIndex = 0;
19754        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19755        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19756        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19757        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19758        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19759        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19760        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19761                ThreadedRenderer.isAvailable()) {
19762            // This is set if HW acceleration is requested, even if the current
19763            // process doesn't allow it.  This is just to allow app preview
19764            // windows to better match their app.
19765            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19766        }
19767        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19768
19769        final int privateFlags2 = mPrivateFlags2;
19770        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19771            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19772        }
19773        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19774            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19775        }
19776
19777        drawableState = StateSet.get(viewStateIndex);
19778
19779        //noinspection ConstantIfStatement
19780        if (false) {
19781            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19782            Log.i("View", toString()
19783                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19784                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19785                    + " fo=" + hasFocus()
19786                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19787                    + " wf=" + hasWindowFocus()
19788                    + ": " + Arrays.toString(drawableState));
19789        }
19790
19791        if (extraSpace == 0) {
19792            return drawableState;
19793        }
19794
19795        final int[] fullState;
19796        if (drawableState != null) {
19797            fullState = new int[drawableState.length + extraSpace];
19798            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19799        } else {
19800            fullState = new int[extraSpace];
19801        }
19802
19803        return fullState;
19804    }
19805
19806    /**
19807     * Merge your own state values in <var>additionalState</var> into the base
19808     * state values <var>baseState</var> that were returned by
19809     * {@link #onCreateDrawableState(int)}.
19810     *
19811     * @param baseState The base state values returned by
19812     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19813     * own additional state values.
19814     *
19815     * @param additionalState The additional state values you would like
19816     * added to <var>baseState</var>; this array is not modified.
19817     *
19818     * @return As a convenience, the <var>baseState</var> array you originally
19819     * passed into the function is returned.
19820     *
19821     * @see #onCreateDrawableState(int)
19822     */
19823    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19824        final int N = baseState.length;
19825        int i = N - 1;
19826        while (i >= 0 && baseState[i] == 0) {
19827            i--;
19828        }
19829        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19830        return baseState;
19831    }
19832
19833    /**
19834     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19835     * on all Drawable objects associated with this view.
19836     * <p>
19837     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19838     * attached to this view.
19839     */
19840    @CallSuper
19841    public void jumpDrawablesToCurrentState() {
19842        if (mBackground != null) {
19843            mBackground.jumpToCurrentState();
19844        }
19845        if (mStateListAnimator != null) {
19846            mStateListAnimator.jumpToCurrentState();
19847        }
19848        if (mDefaultFocusHighlight != null) {
19849            mDefaultFocusHighlight.jumpToCurrentState();
19850        }
19851        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19852            mForegroundInfo.mDrawable.jumpToCurrentState();
19853        }
19854    }
19855
19856    /**
19857     * Sets the background color for this view.
19858     * @param color the color of the background
19859     */
19860    @RemotableViewMethod
19861    public void setBackgroundColor(@ColorInt int color) {
19862        if (mBackground instanceof ColorDrawable) {
19863            ((ColorDrawable) mBackground.mutate()).setColor(color);
19864            computeOpaqueFlags();
19865            mBackgroundResource = 0;
19866        } else {
19867            setBackground(new ColorDrawable(color));
19868        }
19869    }
19870
19871    /**
19872     * Set the background to a given resource. The resource should refer to
19873     * a Drawable object or 0 to remove the background.
19874     * @param resid The identifier of the resource.
19875     *
19876     * @attr ref android.R.styleable#View_background
19877     */
19878    @RemotableViewMethod
19879    public void setBackgroundResource(@DrawableRes int resid) {
19880        if (resid != 0 && resid == mBackgroundResource) {
19881            return;
19882        }
19883
19884        Drawable d = null;
19885        if (resid != 0) {
19886            d = mContext.getDrawable(resid);
19887        }
19888        setBackground(d);
19889
19890        mBackgroundResource = resid;
19891    }
19892
19893    /**
19894     * Set the background to a given Drawable, or remove the background. If the
19895     * background has padding, this View's padding is set to the background's
19896     * padding. However, when a background is removed, this View's padding isn't
19897     * touched. If setting the padding is desired, please use
19898     * {@link #setPadding(int, int, int, int)}.
19899     *
19900     * @param background The Drawable to use as the background, or null to remove the
19901     *        background
19902     */
19903    public void setBackground(Drawable background) {
19904        //noinspection deprecation
19905        setBackgroundDrawable(background);
19906    }
19907
19908    /**
19909     * @deprecated use {@link #setBackground(Drawable)} instead
19910     */
19911    @Deprecated
19912    public void setBackgroundDrawable(Drawable background) {
19913        computeOpaqueFlags();
19914
19915        if (background == mBackground) {
19916            return;
19917        }
19918
19919        boolean requestLayout = false;
19920
19921        mBackgroundResource = 0;
19922
19923        /*
19924         * Regardless of whether we're setting a new background or not, we want
19925         * to clear the previous drawable. setVisible first while we still have the callback set.
19926         */
19927        if (mBackground != null) {
19928            if (isAttachedToWindow()) {
19929                mBackground.setVisible(false, false);
19930            }
19931            mBackground.setCallback(null);
19932            unscheduleDrawable(mBackground);
19933        }
19934
19935        if (background != null) {
19936            Rect padding = sThreadLocal.get();
19937            if (padding == null) {
19938                padding = new Rect();
19939                sThreadLocal.set(padding);
19940            }
19941            resetResolvedDrawablesInternal();
19942            background.setLayoutDirection(getLayoutDirection());
19943            if (background.getPadding(padding)) {
19944                resetResolvedPaddingInternal();
19945                switch (background.getLayoutDirection()) {
19946                    case LAYOUT_DIRECTION_RTL:
19947                        mUserPaddingLeftInitial = padding.right;
19948                        mUserPaddingRightInitial = padding.left;
19949                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19950                        break;
19951                    case LAYOUT_DIRECTION_LTR:
19952                    default:
19953                        mUserPaddingLeftInitial = padding.left;
19954                        mUserPaddingRightInitial = padding.right;
19955                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19956                }
19957                mLeftPaddingDefined = false;
19958                mRightPaddingDefined = false;
19959            }
19960
19961            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19962            // if it has a different minimum size, we should layout again
19963            if (mBackground == null
19964                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19965                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19966                requestLayout = true;
19967            }
19968
19969            // Set mBackground before we set this as the callback and start making other
19970            // background drawable state change calls. In particular, the setVisible call below
19971            // can result in drawables attempting to start animations or otherwise invalidate,
19972            // which requires the view set as the callback (us) to recognize the drawable as
19973            // belonging to it as per verifyDrawable.
19974            mBackground = background;
19975            if (background.isStateful()) {
19976                background.setState(getDrawableState());
19977            }
19978            if (isAttachedToWindow()) {
19979                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19980            }
19981
19982            applyBackgroundTint();
19983
19984            // Set callback last, since the view may still be initializing.
19985            background.setCallback(this);
19986
19987            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19988                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19989                requestLayout = true;
19990            }
19991        } else {
19992            /* Remove the background */
19993            mBackground = null;
19994            if ((mViewFlags & WILL_NOT_DRAW) != 0
19995                    && (mDefaultFocusHighlight == null)
19996                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19997                mPrivateFlags |= PFLAG_SKIP_DRAW;
19998            }
19999
20000            /*
20001             * When the background is set, we try to apply its padding to this
20002             * View. When the background is removed, we don't touch this View's
20003             * padding. This is noted in the Javadocs. Hence, we don't need to
20004             * requestLayout(), the invalidate() below is sufficient.
20005             */
20006
20007            // The old background's minimum size could have affected this
20008            // View's layout, so let's requestLayout
20009            requestLayout = true;
20010        }
20011
20012        computeOpaqueFlags();
20013
20014        if (requestLayout) {
20015            requestLayout();
20016        }
20017
20018        mBackgroundSizeChanged = true;
20019        invalidate(true);
20020        invalidateOutline();
20021    }
20022
20023    /**
20024     * Gets the background drawable
20025     *
20026     * @return The drawable used as the background for this view, if any.
20027     *
20028     * @see #setBackground(Drawable)
20029     *
20030     * @attr ref android.R.styleable#View_background
20031     */
20032    public Drawable getBackground() {
20033        return mBackground;
20034    }
20035
20036    /**
20037     * Applies a tint to the background drawable. Does not modify the current tint
20038     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20039     * <p>
20040     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20041     * mutate the drawable and apply the specified tint and tint mode using
20042     * {@link Drawable#setTintList(ColorStateList)}.
20043     *
20044     * @param tint the tint to apply, may be {@code null} to clear tint
20045     *
20046     * @attr ref android.R.styleable#View_backgroundTint
20047     * @see #getBackgroundTintList()
20048     * @see Drawable#setTintList(ColorStateList)
20049     */
20050    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20051        if (mBackgroundTint == null) {
20052            mBackgroundTint = new TintInfo();
20053        }
20054        mBackgroundTint.mTintList = tint;
20055        mBackgroundTint.mHasTintList = true;
20056
20057        applyBackgroundTint();
20058    }
20059
20060    /**
20061     * Return the tint applied to the background drawable, if specified.
20062     *
20063     * @return the tint applied to the background drawable
20064     * @attr ref android.R.styleable#View_backgroundTint
20065     * @see #setBackgroundTintList(ColorStateList)
20066     */
20067    @Nullable
20068    public ColorStateList getBackgroundTintList() {
20069        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20070    }
20071
20072    /**
20073     * Specifies the blending mode used to apply the tint specified by
20074     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20075     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20076     *
20077     * @param tintMode the blending mode used to apply the tint, may be
20078     *                 {@code null} to clear tint
20079     * @attr ref android.R.styleable#View_backgroundTintMode
20080     * @see #getBackgroundTintMode()
20081     * @see Drawable#setTintMode(PorterDuff.Mode)
20082     */
20083    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20084        if (mBackgroundTint == null) {
20085            mBackgroundTint = new TintInfo();
20086        }
20087        mBackgroundTint.mTintMode = tintMode;
20088        mBackgroundTint.mHasTintMode = true;
20089
20090        applyBackgroundTint();
20091    }
20092
20093    /**
20094     * Return the blending mode used to apply the tint to the background
20095     * drawable, if specified.
20096     *
20097     * @return the blending mode used to apply the tint to the background
20098     *         drawable
20099     * @attr ref android.R.styleable#View_backgroundTintMode
20100     * @see #setBackgroundTintMode(PorterDuff.Mode)
20101     */
20102    @Nullable
20103    public PorterDuff.Mode getBackgroundTintMode() {
20104        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20105    }
20106
20107    private void applyBackgroundTint() {
20108        if (mBackground != null && mBackgroundTint != null) {
20109            final TintInfo tintInfo = mBackgroundTint;
20110            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20111                mBackground = mBackground.mutate();
20112
20113                if (tintInfo.mHasTintList) {
20114                    mBackground.setTintList(tintInfo.mTintList);
20115                }
20116
20117                if (tintInfo.mHasTintMode) {
20118                    mBackground.setTintMode(tintInfo.mTintMode);
20119                }
20120
20121                // The drawable (or one of its children) may not have been
20122                // stateful before applying the tint, so let's try again.
20123                if (mBackground.isStateful()) {
20124                    mBackground.setState(getDrawableState());
20125                }
20126            }
20127        }
20128    }
20129
20130    /**
20131     * Returns the drawable used as the foreground of this View. The
20132     * foreground drawable, if non-null, is always drawn on top of the view's content.
20133     *
20134     * @return a Drawable or null if no foreground was set
20135     *
20136     * @see #onDrawForeground(Canvas)
20137     */
20138    public Drawable getForeground() {
20139        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20140    }
20141
20142    /**
20143     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20144     *
20145     * @param foreground the Drawable to be drawn on top of the children
20146     *
20147     * @attr ref android.R.styleable#View_foreground
20148     */
20149    public void setForeground(Drawable foreground) {
20150        if (mForegroundInfo == null) {
20151            if (foreground == null) {
20152                // Nothing to do.
20153                return;
20154            }
20155            mForegroundInfo = new ForegroundInfo();
20156        }
20157
20158        if (foreground == mForegroundInfo.mDrawable) {
20159            // Nothing to do
20160            return;
20161        }
20162
20163        if (mForegroundInfo.mDrawable != null) {
20164            if (isAttachedToWindow()) {
20165                mForegroundInfo.mDrawable.setVisible(false, false);
20166            }
20167            mForegroundInfo.mDrawable.setCallback(null);
20168            unscheduleDrawable(mForegroundInfo.mDrawable);
20169        }
20170
20171        mForegroundInfo.mDrawable = foreground;
20172        mForegroundInfo.mBoundsChanged = true;
20173        if (foreground != null) {
20174            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20175                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20176            }
20177            foreground.setLayoutDirection(getLayoutDirection());
20178            if (foreground.isStateful()) {
20179                foreground.setState(getDrawableState());
20180            }
20181            applyForegroundTint();
20182            if (isAttachedToWindow()) {
20183                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20184            }
20185            // Set callback last, since the view may still be initializing.
20186            foreground.setCallback(this);
20187        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20188                && (mDefaultFocusHighlight == null)) {
20189            mPrivateFlags |= PFLAG_SKIP_DRAW;
20190        }
20191        requestLayout();
20192        invalidate();
20193    }
20194
20195    /**
20196     * Magic bit used to support features of framework-internal window decor implementation details.
20197     * This used to live exclusively in FrameLayout.
20198     *
20199     * @return true if the foreground should draw inside the padding region or false
20200     *         if it should draw inset by the view's padding
20201     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20202     */
20203    public boolean isForegroundInsidePadding() {
20204        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20205    }
20206
20207    /**
20208     * Describes how the foreground is positioned.
20209     *
20210     * @return foreground gravity.
20211     *
20212     * @see #setForegroundGravity(int)
20213     *
20214     * @attr ref android.R.styleable#View_foregroundGravity
20215     */
20216    public int getForegroundGravity() {
20217        return mForegroundInfo != null ? mForegroundInfo.mGravity
20218                : Gravity.START | Gravity.TOP;
20219    }
20220
20221    /**
20222     * Describes how the foreground is positioned. Defaults to START and TOP.
20223     *
20224     * @param gravity see {@link android.view.Gravity}
20225     *
20226     * @see #getForegroundGravity()
20227     *
20228     * @attr ref android.R.styleable#View_foregroundGravity
20229     */
20230    public void setForegroundGravity(int gravity) {
20231        if (mForegroundInfo == null) {
20232            mForegroundInfo = new ForegroundInfo();
20233        }
20234
20235        if (mForegroundInfo.mGravity != gravity) {
20236            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20237                gravity |= Gravity.START;
20238            }
20239
20240            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20241                gravity |= Gravity.TOP;
20242            }
20243
20244            mForegroundInfo.mGravity = gravity;
20245            requestLayout();
20246        }
20247    }
20248
20249    /**
20250     * Applies a tint to the foreground drawable. Does not modify the current tint
20251     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20252     * <p>
20253     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20254     * mutate the drawable and apply the specified tint and tint mode using
20255     * {@link Drawable#setTintList(ColorStateList)}.
20256     *
20257     * @param tint the tint to apply, may be {@code null} to clear tint
20258     *
20259     * @attr ref android.R.styleable#View_foregroundTint
20260     * @see #getForegroundTintList()
20261     * @see Drawable#setTintList(ColorStateList)
20262     */
20263    public void setForegroundTintList(@Nullable ColorStateList tint) {
20264        if (mForegroundInfo == null) {
20265            mForegroundInfo = new ForegroundInfo();
20266        }
20267        if (mForegroundInfo.mTintInfo == null) {
20268            mForegroundInfo.mTintInfo = new TintInfo();
20269        }
20270        mForegroundInfo.mTintInfo.mTintList = tint;
20271        mForegroundInfo.mTintInfo.mHasTintList = true;
20272
20273        applyForegroundTint();
20274    }
20275
20276    /**
20277     * Return the tint applied to the foreground drawable, if specified.
20278     *
20279     * @return the tint applied to the foreground drawable
20280     * @attr ref android.R.styleable#View_foregroundTint
20281     * @see #setForegroundTintList(ColorStateList)
20282     */
20283    @Nullable
20284    public ColorStateList getForegroundTintList() {
20285        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20286                ? mForegroundInfo.mTintInfo.mTintList : null;
20287    }
20288
20289    /**
20290     * Specifies the blending mode used to apply the tint specified by
20291     * {@link #setForegroundTintList(ColorStateList)}} to the background
20292     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20293     *
20294     * @param tintMode the blending mode used to apply the tint, may be
20295     *                 {@code null} to clear tint
20296     * @attr ref android.R.styleable#View_foregroundTintMode
20297     * @see #getForegroundTintMode()
20298     * @see Drawable#setTintMode(PorterDuff.Mode)
20299     */
20300    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20301        if (mForegroundInfo == null) {
20302            mForegroundInfo = new ForegroundInfo();
20303        }
20304        if (mForegroundInfo.mTintInfo == null) {
20305            mForegroundInfo.mTintInfo = new TintInfo();
20306        }
20307        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20308        mForegroundInfo.mTintInfo.mHasTintMode = true;
20309
20310        applyForegroundTint();
20311    }
20312
20313    /**
20314     * Return the blending mode used to apply the tint to the foreground
20315     * drawable, if specified.
20316     *
20317     * @return the blending mode used to apply the tint to the foreground
20318     *         drawable
20319     * @attr ref android.R.styleable#View_foregroundTintMode
20320     * @see #setForegroundTintMode(PorterDuff.Mode)
20321     */
20322    @Nullable
20323    public PorterDuff.Mode getForegroundTintMode() {
20324        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20325                ? mForegroundInfo.mTintInfo.mTintMode : null;
20326    }
20327
20328    private void applyForegroundTint() {
20329        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20330                && mForegroundInfo.mTintInfo != null) {
20331            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20332            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20333                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20334
20335                if (tintInfo.mHasTintList) {
20336                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20337                }
20338
20339                if (tintInfo.mHasTintMode) {
20340                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20341                }
20342
20343                // The drawable (or one of its children) may not have been
20344                // stateful before applying the tint, so let's try again.
20345                if (mForegroundInfo.mDrawable.isStateful()) {
20346                    mForegroundInfo.mDrawable.setState(getDrawableState());
20347                }
20348            }
20349        }
20350    }
20351
20352    /**
20353     * Get the drawable to be overlayed when a view is autofilled
20354     *
20355     * @return The drawable
20356     *
20357     * @throws IllegalStateException if the drawable could not be found.
20358     */
20359    @NonNull private Drawable getAutofilledDrawable() {
20360        // Lazily load the isAutofilled drawable.
20361        if (mAttachInfo.mAutofilledDrawable == null) {
20362            mAttachInfo.mAutofilledDrawable = mContext.getDrawable(R.drawable.autofilled_highlight);
20363
20364            if (mAttachInfo.mAutofilledDrawable == null) {
20365                throw new IllegalStateException(
20366                        "Could not find android:drawable/autofilled_highlight");
20367            }
20368        }
20369
20370        return mAttachInfo.mAutofilledDrawable;
20371    }
20372
20373    /**
20374     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20375     *
20376     * @param canvas The canvas to draw on
20377     */
20378    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20379        if (isAutofilled()) {
20380            Drawable autofilledHighlight = getAutofilledDrawable();
20381
20382            autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20383            autofilledHighlight.draw(canvas);
20384        }
20385    }
20386
20387    /**
20388     * Draw any foreground content for this view.
20389     *
20390     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20391     * drawable or other view-specific decorations. The foreground is drawn on top of the
20392     * primary view content.</p>
20393     *
20394     * @param canvas canvas to draw into
20395     */
20396    public void onDrawForeground(Canvas canvas) {
20397        onDrawScrollIndicators(canvas);
20398        onDrawScrollBars(canvas);
20399
20400        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20401        if (foreground != null) {
20402            if (mForegroundInfo.mBoundsChanged) {
20403                mForegroundInfo.mBoundsChanged = false;
20404                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20405                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20406
20407                if (mForegroundInfo.mInsidePadding) {
20408                    selfBounds.set(0, 0, getWidth(), getHeight());
20409                } else {
20410                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20411                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20412                }
20413
20414                final int ld = getLayoutDirection();
20415                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20416                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20417                foreground.setBounds(overlayBounds);
20418            }
20419
20420            foreground.draw(canvas);
20421        }
20422    }
20423
20424    /**
20425     * Sets the padding. The view may add on the space required to display
20426     * the scrollbars, depending on the style and visibility of the scrollbars.
20427     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20428     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20429     * from the values set in this call.
20430     *
20431     * @attr ref android.R.styleable#View_padding
20432     * @attr ref android.R.styleable#View_paddingBottom
20433     * @attr ref android.R.styleable#View_paddingLeft
20434     * @attr ref android.R.styleable#View_paddingRight
20435     * @attr ref android.R.styleable#View_paddingTop
20436     * @param left the left padding in pixels
20437     * @param top the top padding in pixels
20438     * @param right the right padding in pixels
20439     * @param bottom the bottom padding in pixels
20440     */
20441    public void setPadding(int left, int top, int right, int bottom) {
20442        resetResolvedPaddingInternal();
20443
20444        mUserPaddingStart = UNDEFINED_PADDING;
20445        mUserPaddingEnd = UNDEFINED_PADDING;
20446
20447        mUserPaddingLeftInitial = left;
20448        mUserPaddingRightInitial = right;
20449
20450        mLeftPaddingDefined = true;
20451        mRightPaddingDefined = true;
20452
20453        internalSetPadding(left, top, right, bottom);
20454    }
20455
20456    /**
20457     * @hide
20458     */
20459    protected void internalSetPadding(int left, int top, int right, int bottom) {
20460        mUserPaddingLeft = left;
20461        mUserPaddingRight = right;
20462        mUserPaddingBottom = bottom;
20463
20464        final int viewFlags = mViewFlags;
20465        boolean changed = false;
20466
20467        // Common case is there are no scroll bars.
20468        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20469            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20470                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20471                        ? 0 : getVerticalScrollbarWidth();
20472                switch (mVerticalScrollbarPosition) {
20473                    case SCROLLBAR_POSITION_DEFAULT:
20474                        if (isLayoutRtl()) {
20475                            left += offset;
20476                        } else {
20477                            right += offset;
20478                        }
20479                        break;
20480                    case SCROLLBAR_POSITION_RIGHT:
20481                        right += offset;
20482                        break;
20483                    case SCROLLBAR_POSITION_LEFT:
20484                        left += offset;
20485                        break;
20486                }
20487            }
20488            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20489                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20490                        ? 0 : getHorizontalScrollbarHeight();
20491            }
20492        }
20493
20494        if (mPaddingLeft != left) {
20495            changed = true;
20496            mPaddingLeft = left;
20497        }
20498        if (mPaddingTop != top) {
20499            changed = true;
20500            mPaddingTop = top;
20501        }
20502        if (mPaddingRight != right) {
20503            changed = true;
20504            mPaddingRight = right;
20505        }
20506        if (mPaddingBottom != bottom) {
20507            changed = true;
20508            mPaddingBottom = bottom;
20509        }
20510
20511        if (changed) {
20512            requestLayout();
20513            invalidateOutline();
20514        }
20515    }
20516
20517    /**
20518     * Sets the relative padding. The view may add on the space required to display
20519     * the scrollbars, depending on the style and visibility of the scrollbars.
20520     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20521     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20522     * from the values set in this call.
20523     *
20524     * @attr ref android.R.styleable#View_padding
20525     * @attr ref android.R.styleable#View_paddingBottom
20526     * @attr ref android.R.styleable#View_paddingStart
20527     * @attr ref android.R.styleable#View_paddingEnd
20528     * @attr ref android.R.styleable#View_paddingTop
20529     * @param start the start padding in pixels
20530     * @param top the top padding in pixels
20531     * @param end the end padding in pixels
20532     * @param bottom the bottom padding in pixels
20533     */
20534    public void setPaddingRelative(int start, int top, int end, int bottom) {
20535        resetResolvedPaddingInternal();
20536
20537        mUserPaddingStart = start;
20538        mUserPaddingEnd = end;
20539        mLeftPaddingDefined = true;
20540        mRightPaddingDefined = true;
20541
20542        switch(getLayoutDirection()) {
20543            case LAYOUT_DIRECTION_RTL:
20544                mUserPaddingLeftInitial = end;
20545                mUserPaddingRightInitial = start;
20546                internalSetPadding(end, top, start, bottom);
20547                break;
20548            case LAYOUT_DIRECTION_LTR:
20549            default:
20550                mUserPaddingLeftInitial = start;
20551                mUserPaddingRightInitial = end;
20552                internalSetPadding(start, top, end, bottom);
20553        }
20554    }
20555
20556    /**
20557     * Returns the top padding of this view.
20558     *
20559     * @return the top padding in pixels
20560     */
20561    public int getPaddingTop() {
20562        return mPaddingTop;
20563    }
20564
20565    /**
20566     * Returns the bottom padding of this view. If there are inset and enabled
20567     * scrollbars, this value may include the space required to display the
20568     * scrollbars as well.
20569     *
20570     * @return the bottom padding in pixels
20571     */
20572    public int getPaddingBottom() {
20573        return mPaddingBottom;
20574    }
20575
20576    /**
20577     * Returns the left padding of this view. If there are inset and enabled
20578     * scrollbars, this value may include the space required to display the
20579     * scrollbars as well.
20580     *
20581     * @return the left padding in pixels
20582     */
20583    public int getPaddingLeft() {
20584        if (!isPaddingResolved()) {
20585            resolvePadding();
20586        }
20587        return mPaddingLeft;
20588    }
20589
20590    /**
20591     * Returns the start padding of this view depending on its resolved layout direction.
20592     * If there are inset and enabled scrollbars, this value may include the space
20593     * required to display the scrollbars as well.
20594     *
20595     * @return the start padding in pixels
20596     */
20597    public int getPaddingStart() {
20598        if (!isPaddingResolved()) {
20599            resolvePadding();
20600        }
20601        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20602                mPaddingRight : mPaddingLeft;
20603    }
20604
20605    /**
20606     * Returns the right padding of this view. If there are inset and enabled
20607     * scrollbars, this value may include the space required to display the
20608     * scrollbars as well.
20609     *
20610     * @return the right padding in pixels
20611     */
20612    public int getPaddingRight() {
20613        if (!isPaddingResolved()) {
20614            resolvePadding();
20615        }
20616        return mPaddingRight;
20617    }
20618
20619    /**
20620     * Returns the end padding of this view depending on its resolved layout direction.
20621     * If there are inset and enabled scrollbars, this value may include the space
20622     * required to display the scrollbars as well.
20623     *
20624     * @return the end padding in pixels
20625     */
20626    public int getPaddingEnd() {
20627        if (!isPaddingResolved()) {
20628            resolvePadding();
20629        }
20630        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20631                mPaddingLeft : mPaddingRight;
20632    }
20633
20634    /**
20635     * Return if the padding has been set through relative values
20636     * {@link #setPaddingRelative(int, int, int, int)} or through
20637     * @attr ref android.R.styleable#View_paddingStart or
20638     * @attr ref android.R.styleable#View_paddingEnd
20639     *
20640     * @return true if the padding is relative or false if it is not.
20641     */
20642    public boolean isPaddingRelative() {
20643        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20644    }
20645
20646    Insets computeOpticalInsets() {
20647        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20648    }
20649
20650    /**
20651     * @hide
20652     */
20653    public void resetPaddingToInitialValues() {
20654        if (isRtlCompatibilityMode()) {
20655            mPaddingLeft = mUserPaddingLeftInitial;
20656            mPaddingRight = mUserPaddingRightInitial;
20657            return;
20658        }
20659        if (isLayoutRtl()) {
20660            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20661            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20662        } else {
20663            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20664            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20665        }
20666    }
20667
20668    /**
20669     * @hide
20670     */
20671    public Insets getOpticalInsets() {
20672        if (mLayoutInsets == null) {
20673            mLayoutInsets = computeOpticalInsets();
20674        }
20675        return mLayoutInsets;
20676    }
20677
20678    /**
20679     * Set this view's optical insets.
20680     *
20681     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20682     * property. Views that compute their own optical insets should call it as part of measurement.
20683     * This method does not request layout. If you are setting optical insets outside of
20684     * measure/layout itself you will want to call requestLayout() yourself.
20685     * </p>
20686     * @hide
20687     */
20688    public void setOpticalInsets(Insets insets) {
20689        mLayoutInsets = insets;
20690    }
20691
20692    /**
20693     * Changes the selection state of this view. A view can be selected or not.
20694     * Note that selection is not the same as focus. Views are typically
20695     * selected in the context of an AdapterView like ListView or GridView;
20696     * the selected view is the view that is highlighted.
20697     *
20698     * @param selected true if the view must be selected, false otherwise
20699     */
20700    public void setSelected(boolean selected) {
20701        //noinspection DoubleNegation
20702        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20703            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20704            if (!selected) resetPressedState();
20705            invalidate(true);
20706            refreshDrawableState();
20707            dispatchSetSelected(selected);
20708            if (selected) {
20709                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20710            } else {
20711                notifyViewAccessibilityStateChangedIfNeeded(
20712                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20713            }
20714        }
20715    }
20716
20717    /**
20718     * Dispatch setSelected to all of this View's children.
20719     *
20720     * @see #setSelected(boolean)
20721     *
20722     * @param selected The new selected state
20723     */
20724    protected void dispatchSetSelected(boolean selected) {
20725    }
20726
20727    /**
20728     * Indicates the selection state of this view.
20729     *
20730     * @return true if the view is selected, false otherwise
20731     */
20732    @ViewDebug.ExportedProperty
20733    public boolean isSelected() {
20734        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20735    }
20736
20737    /**
20738     * Changes the activated state of this view. A view can be activated or not.
20739     * Note that activation is not the same as selection.  Selection is
20740     * a transient property, representing the view (hierarchy) the user is
20741     * currently interacting with.  Activation is a longer-term state that the
20742     * user can move views in and out of.  For example, in a list view with
20743     * single or multiple selection enabled, the views in the current selection
20744     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20745     * here.)  The activated state is propagated down to children of the view it
20746     * is set on.
20747     *
20748     * @param activated true if the view must be activated, false otherwise
20749     */
20750    public void setActivated(boolean activated) {
20751        //noinspection DoubleNegation
20752        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20753            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20754            invalidate(true);
20755            refreshDrawableState();
20756            dispatchSetActivated(activated);
20757        }
20758    }
20759
20760    /**
20761     * Dispatch setActivated to all of this View's children.
20762     *
20763     * @see #setActivated(boolean)
20764     *
20765     * @param activated The new activated state
20766     */
20767    protected void dispatchSetActivated(boolean activated) {
20768    }
20769
20770    /**
20771     * Indicates the activation state of this view.
20772     *
20773     * @return true if the view is activated, false otherwise
20774     */
20775    @ViewDebug.ExportedProperty
20776    public boolean isActivated() {
20777        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20778    }
20779
20780    /**
20781     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20782     * observer can be used to get notifications when global events, like
20783     * layout, happen.
20784     *
20785     * The returned ViewTreeObserver observer is not guaranteed to remain
20786     * valid for the lifetime of this View. If the caller of this method keeps
20787     * a long-lived reference to ViewTreeObserver, it should always check for
20788     * the return value of {@link ViewTreeObserver#isAlive()}.
20789     *
20790     * @return The ViewTreeObserver for this view's hierarchy.
20791     */
20792    public ViewTreeObserver getViewTreeObserver() {
20793        if (mAttachInfo != null) {
20794            return mAttachInfo.mTreeObserver;
20795        }
20796        if (mFloatingTreeObserver == null) {
20797            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20798        }
20799        return mFloatingTreeObserver;
20800    }
20801
20802    /**
20803     * <p>Finds the topmost view in the current view hierarchy.</p>
20804     *
20805     * @return the topmost view containing this view
20806     */
20807    public View getRootView() {
20808        if (mAttachInfo != null) {
20809            final View v = mAttachInfo.mRootView;
20810            if (v != null) {
20811                return v;
20812            }
20813        }
20814
20815        View parent = this;
20816
20817        while (parent.mParent != null && parent.mParent instanceof View) {
20818            parent = (View) parent.mParent;
20819        }
20820
20821        return parent;
20822    }
20823
20824    /**
20825     * Transforms a motion event from view-local coordinates to on-screen
20826     * coordinates.
20827     *
20828     * @param ev the view-local motion event
20829     * @return false if the transformation could not be applied
20830     * @hide
20831     */
20832    public boolean toGlobalMotionEvent(MotionEvent ev) {
20833        final AttachInfo info = mAttachInfo;
20834        if (info == null) {
20835            return false;
20836        }
20837
20838        final Matrix m = info.mTmpMatrix;
20839        m.set(Matrix.IDENTITY_MATRIX);
20840        transformMatrixToGlobal(m);
20841        ev.transform(m);
20842        return true;
20843    }
20844
20845    /**
20846     * Transforms a motion event from on-screen coordinates to view-local
20847     * coordinates.
20848     *
20849     * @param ev the on-screen motion event
20850     * @return false if the transformation could not be applied
20851     * @hide
20852     */
20853    public boolean toLocalMotionEvent(MotionEvent ev) {
20854        final AttachInfo info = mAttachInfo;
20855        if (info == null) {
20856            return false;
20857        }
20858
20859        final Matrix m = info.mTmpMatrix;
20860        m.set(Matrix.IDENTITY_MATRIX);
20861        transformMatrixToLocal(m);
20862        ev.transform(m);
20863        return true;
20864    }
20865
20866    /**
20867     * Modifies the input matrix such that it maps view-local coordinates to
20868     * on-screen coordinates.
20869     *
20870     * @param m input matrix to modify
20871     * @hide
20872     */
20873    public void transformMatrixToGlobal(Matrix m) {
20874        final ViewParent parent = mParent;
20875        if (parent instanceof View) {
20876            final View vp = (View) parent;
20877            vp.transformMatrixToGlobal(m);
20878            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20879        } else if (parent instanceof ViewRootImpl) {
20880            final ViewRootImpl vr = (ViewRootImpl) parent;
20881            vr.transformMatrixToGlobal(m);
20882            m.preTranslate(0, -vr.mCurScrollY);
20883        }
20884
20885        m.preTranslate(mLeft, mTop);
20886
20887        if (!hasIdentityMatrix()) {
20888            m.preConcat(getMatrix());
20889        }
20890    }
20891
20892    /**
20893     * Modifies the input matrix such that it maps on-screen coordinates to
20894     * view-local coordinates.
20895     *
20896     * @param m input matrix to modify
20897     * @hide
20898     */
20899    public void transformMatrixToLocal(Matrix m) {
20900        final ViewParent parent = mParent;
20901        if (parent instanceof View) {
20902            final View vp = (View) parent;
20903            vp.transformMatrixToLocal(m);
20904            m.postTranslate(vp.mScrollX, vp.mScrollY);
20905        } else if (parent instanceof ViewRootImpl) {
20906            final ViewRootImpl vr = (ViewRootImpl) parent;
20907            vr.transformMatrixToLocal(m);
20908            m.postTranslate(0, vr.mCurScrollY);
20909        }
20910
20911        m.postTranslate(-mLeft, -mTop);
20912
20913        if (!hasIdentityMatrix()) {
20914            m.postConcat(getInverseMatrix());
20915        }
20916    }
20917
20918    /**
20919     * @hide
20920     */
20921    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20922            @ViewDebug.IntToString(from = 0, to = "x"),
20923            @ViewDebug.IntToString(from = 1, to = "y")
20924    })
20925    public int[] getLocationOnScreen() {
20926        int[] location = new int[2];
20927        getLocationOnScreen(location);
20928        return location;
20929    }
20930
20931    /**
20932     * <p>Computes the coordinates of this view on the screen. The argument
20933     * must be an array of two integers. After the method returns, the array
20934     * contains the x and y location in that order.</p>
20935     *
20936     * @param outLocation an array of two integers in which to hold the coordinates
20937     */
20938    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20939        getLocationInWindow(outLocation);
20940
20941        final AttachInfo info = mAttachInfo;
20942        if (info != null) {
20943            outLocation[0] += info.mWindowLeft;
20944            outLocation[1] += info.mWindowTop;
20945        }
20946    }
20947
20948    /**
20949     * <p>Computes the coordinates of this view in its window. The argument
20950     * must be an array of two integers. After the method returns, the array
20951     * contains the x and y location in that order.</p>
20952     *
20953     * @param outLocation an array of two integers in which to hold the coordinates
20954     */
20955    public void getLocationInWindow(@Size(2) int[] outLocation) {
20956        if (outLocation == null || outLocation.length < 2) {
20957            throw new IllegalArgumentException("outLocation must be an array of two integers");
20958        }
20959
20960        outLocation[0] = 0;
20961        outLocation[1] = 0;
20962
20963        transformFromViewToWindowSpace(outLocation);
20964    }
20965
20966    /** @hide */
20967    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20968        if (inOutLocation == null || inOutLocation.length < 2) {
20969            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20970        }
20971
20972        if (mAttachInfo == null) {
20973            // When the view is not attached to a window, this method does not make sense
20974            inOutLocation[0] = inOutLocation[1] = 0;
20975            return;
20976        }
20977
20978        float position[] = mAttachInfo.mTmpTransformLocation;
20979        position[0] = inOutLocation[0];
20980        position[1] = inOutLocation[1];
20981
20982        if (!hasIdentityMatrix()) {
20983            getMatrix().mapPoints(position);
20984        }
20985
20986        position[0] += mLeft;
20987        position[1] += mTop;
20988
20989        ViewParent viewParent = mParent;
20990        while (viewParent instanceof View) {
20991            final View view = (View) viewParent;
20992
20993            position[0] -= view.mScrollX;
20994            position[1] -= view.mScrollY;
20995
20996            if (!view.hasIdentityMatrix()) {
20997                view.getMatrix().mapPoints(position);
20998            }
20999
21000            position[0] += view.mLeft;
21001            position[1] += view.mTop;
21002
21003            viewParent = view.mParent;
21004         }
21005
21006        if (viewParent instanceof ViewRootImpl) {
21007            // *cough*
21008            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21009            position[1] -= vr.mCurScrollY;
21010        }
21011
21012        inOutLocation[0] = Math.round(position[0]);
21013        inOutLocation[1] = Math.round(position[1]);
21014    }
21015
21016    /**
21017     * @param id the id of the view to be found
21018     * @return the view of the specified id, null if cannot be found
21019     * @hide
21020     */
21021    protected <T extends View> T findViewTraversal(@IdRes int id) {
21022        if (id == mID) {
21023            return (T) this;
21024        }
21025        return null;
21026    }
21027
21028    /**
21029     * @param tag the tag of the view to be found
21030     * @return the view of specified tag, null if cannot be found
21031     * @hide
21032     */
21033    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21034        if (tag != null && tag.equals(mTag)) {
21035            return (T) this;
21036        }
21037        return null;
21038    }
21039
21040    /**
21041     * @param predicate The predicate to evaluate.
21042     * @param childToSkip If not null, ignores this child during the recursive traversal.
21043     * @return The first view that matches the predicate or null.
21044     * @hide
21045     */
21046    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21047            View childToSkip) {
21048        if (predicate.test(this)) {
21049            return (T) this;
21050        }
21051        return null;
21052    }
21053
21054    /**
21055     * Finds the first descendant view with the given ID, the view itself if
21056     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21057     * (< 0) or there is no matching view in the hierarchy.
21058     * <p>
21059     * <strong>Note:</strong> In most cases -- depending on compiler support --
21060     * the resulting view is automatically cast to the target class type. If
21061     * the target class type is unconstrained, an explicit cast may be
21062     * necessary.
21063     *
21064     * @param id the ID to search for
21065     * @return a view with given ID if found, or {@code null} otherwise
21066     * @see View#findViewById(int)
21067     */
21068    @Nullable
21069    public final <T extends View> T findViewById(@IdRes int id) {
21070        if (id < 0) {
21071            return null;
21072        }
21073        return findViewTraversal(id);
21074    }
21075
21076    /**
21077     * Finds a view by its unuque and stable accessibility id.
21078     *
21079     * @param accessibilityId The searched accessibility id.
21080     * @return The found view.
21081     */
21082    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
21083        if (accessibilityId < 0) {
21084            return null;
21085        }
21086        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21087        if (view != null) {
21088            return view.includeForAccessibility() ? view : null;
21089        }
21090        return null;
21091    }
21092
21093    /**
21094     * Performs the traversal to find a view by its unuque and stable accessibility id.
21095     *
21096     * <strong>Note:</strong>This method does not stop at the root namespace
21097     * boundary since the user can touch the screen at an arbitrary location
21098     * potentially crossing the root namespace bounday which will send an
21099     * accessibility event to accessibility services and they should be able
21100     * to obtain the event source. Also accessibility ids are guaranteed to be
21101     * unique in the window.
21102     *
21103     * @param accessibilityId The accessibility id.
21104     * @return The found view.
21105     * @hide
21106     */
21107    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21108        if (getAccessibilityViewId() == accessibilityId) {
21109            return (T) this;
21110        }
21111        return null;
21112    }
21113
21114    /**
21115     * Look for a child view with the given tag.  If this view has the given
21116     * tag, return this view.
21117     *
21118     * @param tag The tag to search for, using "tag.equals(getTag())".
21119     * @return The View that has the given tag in the hierarchy or null
21120     */
21121    public final <T extends View> T findViewWithTag(Object tag) {
21122        if (tag == null) {
21123            return null;
21124        }
21125        return findViewWithTagTraversal(tag);
21126    }
21127
21128    /**
21129     * Look for a child view that matches the specified predicate.
21130     * If this view matches the predicate, return this view.
21131     *
21132     * @param predicate The predicate to evaluate.
21133     * @return The first view that matches the predicate or null.
21134     * @hide
21135     */
21136    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21137        return findViewByPredicateTraversal(predicate, null);
21138    }
21139
21140    /**
21141     * Look for a child view that matches the specified predicate,
21142     * starting with the specified view and its descendents and then
21143     * recusively searching the ancestors and siblings of that view
21144     * until this view is reached.
21145     *
21146     * This method is useful in cases where the predicate does not match
21147     * a single unique view (perhaps multiple views use the same id)
21148     * and we are trying to find the view that is "closest" in scope to the
21149     * starting view.
21150     *
21151     * @param start The view to start from.
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 findViewByPredicateInsideOut(
21157            View start, Predicate<View> predicate) {
21158        View childToSkip = null;
21159        for (;;) {
21160            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21161            if (view != null || start == this) {
21162                return view;
21163            }
21164
21165            ViewParent parent = start.getParent();
21166            if (parent == null || !(parent instanceof View)) {
21167                return null;
21168            }
21169
21170            childToSkip = start;
21171            start = (View) parent;
21172        }
21173    }
21174
21175    /**
21176     * Sets the identifier for this view. The identifier does not have to be
21177     * unique in this view's hierarchy. The identifier should be a positive
21178     * number.
21179     *
21180     * @see #NO_ID
21181     * @see #getId()
21182     * @see #findViewById(int)
21183     *
21184     * @param id a number used to identify the view
21185     *
21186     * @attr ref android.R.styleable#View_id
21187     */
21188    public void setId(@IdRes int id) {
21189        mID = id;
21190        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21191            mID = generateViewId();
21192        }
21193    }
21194
21195    /**
21196     * {@hide}
21197     *
21198     * @param isRoot true if the view belongs to the root namespace, false
21199     *        otherwise
21200     */
21201    public void setIsRootNamespace(boolean isRoot) {
21202        if (isRoot) {
21203            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21204        } else {
21205            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21206        }
21207    }
21208
21209    /**
21210     * {@hide}
21211     *
21212     * @return true if the view belongs to the root namespace, false otherwise
21213     */
21214    public boolean isRootNamespace() {
21215        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21216    }
21217
21218    /**
21219     * Returns this view's identifier.
21220     *
21221     * @return a positive integer used to identify the view or {@link #NO_ID}
21222     *         if the view has no ID
21223     *
21224     * @see #setId(int)
21225     * @see #findViewById(int)
21226     * @attr ref android.R.styleable#View_id
21227     */
21228    @IdRes
21229    @ViewDebug.CapturedViewProperty
21230    public int getId() {
21231        return mID;
21232    }
21233
21234    /**
21235     * Returns this view's tag.
21236     *
21237     * @return the Object stored in this view as a tag, or {@code null} if not
21238     *         set
21239     *
21240     * @see #setTag(Object)
21241     * @see #getTag(int)
21242     */
21243    @ViewDebug.ExportedProperty
21244    public Object getTag() {
21245        return mTag;
21246    }
21247
21248    /**
21249     * Sets the tag associated with this view. A tag can be used to mark
21250     * a view in its hierarchy and does not have to be unique within the
21251     * hierarchy. Tags can also be used to store data within a view without
21252     * resorting to another data structure.
21253     *
21254     * @param tag an Object to tag the view with
21255     *
21256     * @see #getTag()
21257     * @see #setTag(int, Object)
21258     */
21259    public void setTag(final Object tag) {
21260        mTag = tag;
21261    }
21262
21263    /**
21264     * Returns the tag associated with this view and the specified key.
21265     *
21266     * @param key The key identifying the tag
21267     *
21268     * @return the Object stored in this view as a tag, or {@code null} if not
21269     *         set
21270     *
21271     * @see #setTag(int, Object)
21272     * @see #getTag()
21273     */
21274    public Object getTag(int key) {
21275        if (mKeyedTags != null) return mKeyedTags.get(key);
21276        return null;
21277    }
21278
21279    /**
21280     * Sets a tag associated with this view and a key. A tag can be used
21281     * to mark a view in its hierarchy and does not have to be unique within
21282     * the hierarchy. Tags can also be used to store data within a view
21283     * without resorting to another data structure.
21284     *
21285     * The specified key should be an id declared in the resources of the
21286     * application to ensure it is unique (see the <a
21287     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21288     * Keys identified as belonging to
21289     * the Android framework or not associated with any package will cause
21290     * an {@link IllegalArgumentException} to be thrown.
21291     *
21292     * @param key The key identifying the tag
21293     * @param tag An Object to tag the view with
21294     *
21295     * @throws IllegalArgumentException If they specified key is not valid
21296     *
21297     * @see #setTag(Object)
21298     * @see #getTag(int)
21299     */
21300    public void setTag(int key, final Object tag) {
21301        // If the package id is 0x00 or 0x01, it's either an undefined package
21302        // or a framework id
21303        if ((key >>> 24) < 2) {
21304            throw new IllegalArgumentException("The key must be an application-specific "
21305                    + "resource id.");
21306        }
21307
21308        setKeyedTag(key, tag);
21309    }
21310
21311    /**
21312     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21313     * framework id.
21314     *
21315     * @hide
21316     */
21317    public void setTagInternal(int key, Object tag) {
21318        if ((key >>> 24) != 0x1) {
21319            throw new IllegalArgumentException("The key must be a framework-specific "
21320                    + "resource id.");
21321        }
21322
21323        setKeyedTag(key, tag);
21324    }
21325
21326    private void setKeyedTag(int key, Object tag) {
21327        if (mKeyedTags == null) {
21328            mKeyedTags = new SparseArray<Object>(2);
21329        }
21330
21331        mKeyedTags.put(key, tag);
21332    }
21333
21334    /**
21335     * Prints information about this view in the log output, with the tag
21336     * {@link #VIEW_LOG_TAG}.
21337     *
21338     * @hide
21339     */
21340    public void debug() {
21341        debug(0);
21342    }
21343
21344    /**
21345     * Prints information about this view in the log output, with the tag
21346     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21347     * indentation defined by the <code>depth</code>.
21348     *
21349     * @param depth the indentation level
21350     *
21351     * @hide
21352     */
21353    protected void debug(int depth) {
21354        String output = debugIndent(depth - 1);
21355
21356        output += "+ " + this;
21357        int id = getId();
21358        if (id != -1) {
21359            output += " (id=" + id + ")";
21360        }
21361        Object tag = getTag();
21362        if (tag != null) {
21363            output += " (tag=" + tag + ")";
21364        }
21365        Log.d(VIEW_LOG_TAG, output);
21366
21367        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21368            output = debugIndent(depth) + " FOCUSED";
21369            Log.d(VIEW_LOG_TAG, output);
21370        }
21371
21372        output = debugIndent(depth);
21373        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21374                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21375                + "} ";
21376        Log.d(VIEW_LOG_TAG, output);
21377
21378        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21379                || mPaddingBottom != 0) {
21380            output = debugIndent(depth);
21381            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21382                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21383            Log.d(VIEW_LOG_TAG, output);
21384        }
21385
21386        output = debugIndent(depth);
21387        output += "mMeasureWidth=" + mMeasuredWidth +
21388                " mMeasureHeight=" + mMeasuredHeight;
21389        Log.d(VIEW_LOG_TAG, output);
21390
21391        output = debugIndent(depth);
21392        if (mLayoutParams == null) {
21393            output += "BAD! no layout params";
21394        } else {
21395            output = mLayoutParams.debug(output);
21396        }
21397        Log.d(VIEW_LOG_TAG, output);
21398
21399        output = debugIndent(depth);
21400        output += "flags={";
21401        output += View.printFlags(mViewFlags);
21402        output += "}";
21403        Log.d(VIEW_LOG_TAG, output);
21404
21405        output = debugIndent(depth);
21406        output += "privateFlags={";
21407        output += View.printPrivateFlags(mPrivateFlags);
21408        output += "}";
21409        Log.d(VIEW_LOG_TAG, output);
21410    }
21411
21412    /**
21413     * Creates a string of whitespaces used for indentation.
21414     *
21415     * @param depth the indentation level
21416     * @return a String containing (depth * 2 + 3) * 2 white spaces
21417     *
21418     * @hide
21419     */
21420    protected static String debugIndent(int depth) {
21421        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21422        for (int i = 0; i < (depth * 2) + 3; i++) {
21423            spaces.append(' ').append(' ');
21424        }
21425        return spaces.toString();
21426    }
21427
21428    /**
21429     * <p>Return the offset of the widget's text baseline from the widget's top
21430     * boundary. If this widget does not support baseline alignment, this
21431     * method returns -1. </p>
21432     *
21433     * @return the offset of the baseline within the widget's bounds or -1
21434     *         if baseline alignment is not supported
21435     */
21436    @ViewDebug.ExportedProperty(category = "layout")
21437    public int getBaseline() {
21438        return -1;
21439    }
21440
21441    /**
21442     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21443     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21444     * a layout pass.
21445     *
21446     * @return whether the view hierarchy is currently undergoing a layout pass
21447     */
21448    public boolean isInLayout() {
21449        ViewRootImpl viewRoot = getViewRootImpl();
21450        return (viewRoot != null && viewRoot.isInLayout());
21451    }
21452
21453    /**
21454     * Call this when something has changed which has invalidated the
21455     * layout of this view. This will schedule a layout pass of the view
21456     * tree. This should not be called while the view hierarchy is currently in a layout
21457     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21458     * end of the current layout pass (and then layout will run again) or after the current
21459     * frame is drawn and the next layout occurs.
21460     *
21461     * <p>Subclasses which override this method should call the superclass method to
21462     * handle possible request-during-layout errors correctly.</p>
21463     */
21464    @CallSuper
21465    public void requestLayout() {
21466        if (mMeasureCache != null) mMeasureCache.clear();
21467
21468        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21469            // Only trigger request-during-layout logic if this is the view requesting it,
21470            // not the views in its parent hierarchy
21471            ViewRootImpl viewRoot = getViewRootImpl();
21472            if (viewRoot != null && viewRoot.isInLayout()) {
21473                if (!viewRoot.requestLayoutDuringLayout(this)) {
21474                    return;
21475                }
21476            }
21477            mAttachInfo.mViewRequestingLayout = this;
21478        }
21479
21480        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21481        mPrivateFlags |= PFLAG_INVALIDATED;
21482
21483        if (mParent != null && !mParent.isLayoutRequested()) {
21484            mParent.requestLayout();
21485        }
21486        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21487            mAttachInfo.mViewRequestingLayout = null;
21488        }
21489    }
21490
21491    /**
21492     * Forces this view to be laid out during the next layout pass.
21493     * This method does not call requestLayout() or forceLayout()
21494     * on the parent.
21495     */
21496    public void forceLayout() {
21497        if (mMeasureCache != null) mMeasureCache.clear();
21498
21499        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21500        mPrivateFlags |= PFLAG_INVALIDATED;
21501    }
21502
21503    /**
21504     * <p>
21505     * This is called to find out how big a view should be. The parent
21506     * supplies constraint information in the width and height parameters.
21507     * </p>
21508     *
21509     * <p>
21510     * The actual measurement work of a view is performed in
21511     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21512     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21513     * </p>
21514     *
21515     *
21516     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21517     *        parent
21518     * @param heightMeasureSpec Vertical space requirements as imposed by the
21519     *        parent
21520     *
21521     * @see #onMeasure(int, int)
21522     */
21523    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21524        boolean optical = isLayoutModeOptical(this);
21525        if (optical != isLayoutModeOptical(mParent)) {
21526            Insets insets = getOpticalInsets();
21527            int oWidth  = insets.left + insets.right;
21528            int oHeight = insets.top  + insets.bottom;
21529            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21530            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21531        }
21532
21533        // Suppress sign extension for the low bytes
21534        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21535        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21536
21537        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21538
21539        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21540        // already measured as the correct size. In API 23 and below, this
21541        // extra pass is required to make LinearLayout re-distribute weight.
21542        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21543                || heightMeasureSpec != mOldHeightMeasureSpec;
21544        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21545                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21546        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21547                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21548        final boolean needsLayout = specChanged
21549                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21550
21551        if (forceLayout || needsLayout) {
21552            // first clears the measured dimension flag
21553            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21554
21555            resolveRtlPropertiesIfNeeded();
21556
21557            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21558            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21559                // measure ourselves, this should set the measured dimension flag back
21560                onMeasure(widthMeasureSpec, heightMeasureSpec);
21561                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21562            } else {
21563                long value = mMeasureCache.valueAt(cacheIndex);
21564                // Casting a long to int drops the high 32 bits, no mask needed
21565                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21566                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21567            }
21568
21569            // flag not set, setMeasuredDimension() was not invoked, we raise
21570            // an exception to warn the developer
21571            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21572                throw new IllegalStateException("View with id " + getId() + ": "
21573                        + getClass().getName() + "#onMeasure() did not set the"
21574                        + " measured dimension by calling"
21575                        + " setMeasuredDimension()");
21576            }
21577
21578            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21579        }
21580
21581        mOldWidthMeasureSpec = widthMeasureSpec;
21582        mOldHeightMeasureSpec = heightMeasureSpec;
21583
21584        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21585                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21586    }
21587
21588    /**
21589     * <p>
21590     * Measure the view and its content to determine the measured width and the
21591     * measured height. This method is invoked by {@link #measure(int, int)} and
21592     * should be overridden by subclasses to provide accurate and efficient
21593     * measurement of their contents.
21594     * </p>
21595     *
21596     * <p>
21597     * <strong>CONTRACT:</strong> When overriding this method, you
21598     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21599     * measured width and height of this view. Failure to do so will trigger an
21600     * <code>IllegalStateException</code>, thrown by
21601     * {@link #measure(int, int)}. Calling the superclass'
21602     * {@link #onMeasure(int, int)} is a valid use.
21603     * </p>
21604     *
21605     * <p>
21606     * The base class implementation of measure defaults to the background size,
21607     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21608     * override {@link #onMeasure(int, int)} to provide better measurements of
21609     * their content.
21610     * </p>
21611     *
21612     * <p>
21613     * If this method is overridden, it is the subclass's responsibility to make
21614     * sure the measured height and width are at least the view's minimum height
21615     * and width ({@link #getSuggestedMinimumHeight()} and
21616     * {@link #getSuggestedMinimumWidth()}).
21617     * </p>
21618     *
21619     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21620     *                         The requirements are encoded with
21621     *                         {@link android.view.View.MeasureSpec}.
21622     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21623     *                         The requirements are encoded with
21624     *                         {@link android.view.View.MeasureSpec}.
21625     *
21626     * @see #getMeasuredWidth()
21627     * @see #getMeasuredHeight()
21628     * @see #setMeasuredDimension(int, int)
21629     * @see #getSuggestedMinimumHeight()
21630     * @see #getSuggestedMinimumWidth()
21631     * @see android.view.View.MeasureSpec#getMode(int)
21632     * @see android.view.View.MeasureSpec#getSize(int)
21633     */
21634    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21635        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21636                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21637    }
21638
21639    /**
21640     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21641     * measured width and measured height. Failing to do so will trigger an
21642     * exception at measurement time.</p>
21643     *
21644     * @param measuredWidth The measured width of this view.  May be a complex
21645     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21646     * {@link #MEASURED_STATE_TOO_SMALL}.
21647     * @param measuredHeight The measured height of this view.  May be a complex
21648     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21649     * {@link #MEASURED_STATE_TOO_SMALL}.
21650     */
21651    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21652        boolean optical = isLayoutModeOptical(this);
21653        if (optical != isLayoutModeOptical(mParent)) {
21654            Insets insets = getOpticalInsets();
21655            int opticalWidth  = insets.left + insets.right;
21656            int opticalHeight = insets.top  + insets.bottom;
21657
21658            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21659            measuredHeight += optical ? opticalHeight : -opticalHeight;
21660        }
21661        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21662    }
21663
21664    /**
21665     * Sets the measured dimension without extra processing for things like optical bounds.
21666     * Useful for reapplying consistent values that have already been cooked with adjustments
21667     * for optical bounds, etc. such as those from the measurement cache.
21668     *
21669     * @param measuredWidth The measured width of this view.  May be a complex
21670     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21671     * {@link #MEASURED_STATE_TOO_SMALL}.
21672     * @param measuredHeight The measured height of this view.  May be a complex
21673     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21674     * {@link #MEASURED_STATE_TOO_SMALL}.
21675     */
21676    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21677        mMeasuredWidth = measuredWidth;
21678        mMeasuredHeight = measuredHeight;
21679
21680        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21681    }
21682
21683    /**
21684     * Merge two states as returned by {@link #getMeasuredState()}.
21685     * @param curState The current state as returned from a view or the result
21686     * of combining multiple views.
21687     * @param newState The new view state to combine.
21688     * @return Returns a new integer reflecting the combination of the two
21689     * states.
21690     */
21691    public static int combineMeasuredStates(int curState, int newState) {
21692        return curState | newState;
21693    }
21694
21695    /**
21696     * Version of {@link #resolveSizeAndState(int, int, int)}
21697     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21698     */
21699    public static int resolveSize(int size, int measureSpec) {
21700        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21701    }
21702
21703    /**
21704     * Utility to reconcile a desired size and state, with constraints imposed
21705     * by a MeasureSpec. Will take the desired size, unless a different size
21706     * is imposed by the constraints. The returned value is a compound integer,
21707     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21708     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21709     * resulting size is smaller than the size the view wants to be.
21710     *
21711     * @param size How big the view wants to be.
21712     * @param measureSpec Constraints imposed by the parent.
21713     * @param childMeasuredState Size information bit mask for the view's
21714     *                           children.
21715     * @return Size information bit mask as defined by
21716     *         {@link #MEASURED_SIZE_MASK} and
21717     *         {@link #MEASURED_STATE_TOO_SMALL}.
21718     */
21719    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21720        final int specMode = MeasureSpec.getMode(measureSpec);
21721        final int specSize = MeasureSpec.getSize(measureSpec);
21722        final int result;
21723        switch (specMode) {
21724            case MeasureSpec.AT_MOST:
21725                if (specSize < size) {
21726                    result = specSize | MEASURED_STATE_TOO_SMALL;
21727                } else {
21728                    result = size;
21729                }
21730                break;
21731            case MeasureSpec.EXACTLY:
21732                result = specSize;
21733                break;
21734            case MeasureSpec.UNSPECIFIED:
21735            default:
21736                result = size;
21737        }
21738        return result | (childMeasuredState & MEASURED_STATE_MASK);
21739    }
21740
21741    /**
21742     * Utility to return a default size. Uses the supplied size if the
21743     * MeasureSpec imposed no constraints. Will get larger if allowed
21744     * by the MeasureSpec.
21745     *
21746     * @param size Default size for this view
21747     * @param measureSpec Constraints imposed by the parent
21748     * @return The size this view should be.
21749     */
21750    public static int getDefaultSize(int size, int measureSpec) {
21751        int result = size;
21752        int specMode = MeasureSpec.getMode(measureSpec);
21753        int specSize = MeasureSpec.getSize(measureSpec);
21754
21755        switch (specMode) {
21756        case MeasureSpec.UNSPECIFIED:
21757            result = size;
21758            break;
21759        case MeasureSpec.AT_MOST:
21760        case MeasureSpec.EXACTLY:
21761            result = specSize;
21762            break;
21763        }
21764        return result;
21765    }
21766
21767    /**
21768     * Returns the suggested minimum height that the view should use. This
21769     * returns the maximum of the view's minimum height
21770     * and the background's minimum height
21771     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21772     * <p>
21773     * When being used in {@link #onMeasure(int, int)}, the caller should still
21774     * ensure the returned height is within the requirements of the parent.
21775     *
21776     * @return The suggested minimum height of the view.
21777     */
21778    protected int getSuggestedMinimumHeight() {
21779        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21780
21781    }
21782
21783    /**
21784     * Returns the suggested minimum width that the view should use. This
21785     * returns the maximum of the view's minimum width
21786     * and the background's minimum width
21787     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21788     * <p>
21789     * When being used in {@link #onMeasure(int, int)}, the caller should still
21790     * ensure the returned width is within the requirements of the parent.
21791     *
21792     * @return The suggested minimum width of the view.
21793     */
21794    protected int getSuggestedMinimumWidth() {
21795        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21796    }
21797
21798    /**
21799     * Returns the minimum height of the view.
21800     *
21801     * @return the minimum height the view will try to be, in pixels
21802     *
21803     * @see #setMinimumHeight(int)
21804     *
21805     * @attr ref android.R.styleable#View_minHeight
21806     */
21807    public int getMinimumHeight() {
21808        return mMinHeight;
21809    }
21810
21811    /**
21812     * Sets the minimum height of the view. It is not guaranteed the view will
21813     * be able to achieve this minimum height (for example, if its parent layout
21814     * constrains it with less available height).
21815     *
21816     * @param minHeight The minimum height the view will try to be, in pixels
21817     *
21818     * @see #getMinimumHeight()
21819     *
21820     * @attr ref android.R.styleable#View_minHeight
21821     */
21822    @RemotableViewMethod
21823    public void setMinimumHeight(int minHeight) {
21824        mMinHeight = minHeight;
21825        requestLayout();
21826    }
21827
21828    /**
21829     * Returns the minimum width of the view.
21830     *
21831     * @return the minimum width the view will try to be, in pixels
21832     *
21833     * @see #setMinimumWidth(int)
21834     *
21835     * @attr ref android.R.styleable#View_minWidth
21836     */
21837    public int getMinimumWidth() {
21838        return mMinWidth;
21839    }
21840
21841    /**
21842     * Sets the minimum width of the view. It is not guaranteed the view will
21843     * be able to achieve this minimum width (for example, if its parent layout
21844     * constrains it with less available width).
21845     *
21846     * @param minWidth The minimum width the view will try to be, in pixels
21847     *
21848     * @see #getMinimumWidth()
21849     *
21850     * @attr ref android.R.styleable#View_minWidth
21851     */
21852    public void setMinimumWidth(int minWidth) {
21853        mMinWidth = minWidth;
21854        requestLayout();
21855
21856    }
21857
21858    /**
21859     * Get the animation currently associated with this view.
21860     *
21861     * @return The animation that is currently playing or
21862     *         scheduled to play for this view.
21863     */
21864    public Animation getAnimation() {
21865        return mCurrentAnimation;
21866    }
21867
21868    /**
21869     * Start the specified animation now.
21870     *
21871     * @param animation the animation to start now
21872     */
21873    public void startAnimation(Animation animation) {
21874        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21875        setAnimation(animation);
21876        invalidateParentCaches();
21877        invalidate(true);
21878    }
21879
21880    /**
21881     * Cancels any animations for this view.
21882     */
21883    public void clearAnimation() {
21884        if (mCurrentAnimation != null) {
21885            mCurrentAnimation.detach();
21886        }
21887        mCurrentAnimation = null;
21888        invalidateParentIfNeeded();
21889    }
21890
21891    /**
21892     * Sets the next animation to play for this view.
21893     * If you want the animation to play immediately, use
21894     * {@link #startAnimation(android.view.animation.Animation)} instead.
21895     * This method provides allows fine-grained
21896     * control over the start time and invalidation, but you
21897     * must make sure that 1) the animation has a start time set, and
21898     * 2) the view's parent (which controls animations on its children)
21899     * will be invalidated when the animation is supposed to
21900     * start.
21901     *
21902     * @param animation The next animation, or null.
21903     */
21904    public void setAnimation(Animation animation) {
21905        mCurrentAnimation = animation;
21906
21907        if (animation != null) {
21908            // If the screen is off assume the animation start time is now instead of
21909            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21910            // would cause the animation to start when the screen turns back on
21911            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21912                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21913                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21914            }
21915            animation.reset();
21916        }
21917    }
21918
21919    /**
21920     * Invoked by a parent ViewGroup to notify the start of the animation
21921     * currently associated with this view. If you override this method,
21922     * always call super.onAnimationStart();
21923     *
21924     * @see #setAnimation(android.view.animation.Animation)
21925     * @see #getAnimation()
21926     */
21927    @CallSuper
21928    protected void onAnimationStart() {
21929        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21930    }
21931
21932    /**
21933     * Invoked by a parent ViewGroup to notify the end of the animation
21934     * currently associated with this view. If you override this method,
21935     * always call super.onAnimationEnd();
21936     *
21937     * @see #setAnimation(android.view.animation.Animation)
21938     * @see #getAnimation()
21939     */
21940    @CallSuper
21941    protected void onAnimationEnd() {
21942        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21943    }
21944
21945    /**
21946     * Invoked if there is a Transform that involves alpha. Subclass that can
21947     * draw themselves with the specified alpha should return true, and then
21948     * respect that alpha when their onDraw() is called. If this returns false
21949     * then the view may be redirected to draw into an offscreen buffer to
21950     * fulfill the request, which will look fine, but may be slower than if the
21951     * subclass handles it internally. The default implementation returns false.
21952     *
21953     * @param alpha The alpha (0..255) to apply to the view's drawing
21954     * @return true if the view can draw with the specified alpha.
21955     */
21956    protected boolean onSetAlpha(int alpha) {
21957        return false;
21958    }
21959
21960    /**
21961     * This is used by the RootView to perform an optimization when
21962     * the view hierarchy contains one or several SurfaceView.
21963     * SurfaceView is always considered transparent, but its children are not,
21964     * therefore all View objects remove themselves from the global transparent
21965     * region (passed as a parameter to this function).
21966     *
21967     * @param region The transparent region for this ViewAncestor (window).
21968     *
21969     * @return Returns true if the effective visibility of the view at this
21970     * point is opaque, regardless of the transparent region; returns false
21971     * if it is possible for underlying windows to be seen behind the view.
21972     *
21973     * {@hide}
21974     */
21975    public boolean gatherTransparentRegion(Region region) {
21976        final AttachInfo attachInfo = mAttachInfo;
21977        if (region != null && attachInfo != null) {
21978            final int pflags = mPrivateFlags;
21979            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
21980                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
21981                // remove it from the transparent region.
21982                final int[] location = attachInfo.mTransparentLocation;
21983                getLocationInWindow(location);
21984                // When a view has Z value, then it will be better to leave some area below the view
21985                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
21986                // the bottom part needs more offset than the left, top and right parts due to the
21987                // spot light effects.
21988                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
21989                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
21990                        location[0] + mRight - mLeft + shadowOffset,
21991                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
21992            } else {
21993                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
21994                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
21995                    // the background drawable's non-transparent parts from this transparent region.
21996                    applyDrawableToTransparentRegion(mBackground, region);
21997                }
21998                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
21999                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22000                    // Similarly, we remove the foreground drawable's non-transparent parts.
22001                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22002                }
22003                if (mDefaultFocusHighlight != null
22004                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22005                    // Similarly, we remove the default focus highlight's non-transparent parts.
22006                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22007                }
22008            }
22009        }
22010        return true;
22011    }
22012
22013    /**
22014     * Play a sound effect for this view.
22015     *
22016     * <p>The framework will play sound effects for some built in actions, such as
22017     * clicking, but you may wish to play these effects in your widget,
22018     * for instance, for internal navigation.
22019     *
22020     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22021     * {@link #isSoundEffectsEnabled()} is true.
22022     *
22023     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22024     */
22025    public void playSoundEffect(int soundConstant) {
22026        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22027            return;
22028        }
22029        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22030    }
22031
22032    /**
22033     * BZZZTT!!1!
22034     *
22035     * <p>Provide haptic feedback to the user for this view.
22036     *
22037     * <p>The framework will provide haptic feedback for some built in actions,
22038     * such as long presses, but you may wish to provide feedback for your
22039     * own widget.
22040     *
22041     * <p>The feedback will only be performed if
22042     * {@link #isHapticFeedbackEnabled()} is true.
22043     *
22044     * @param feedbackConstant One of the constants defined in
22045     * {@link HapticFeedbackConstants}
22046     */
22047    public boolean performHapticFeedback(int feedbackConstant) {
22048        return performHapticFeedback(feedbackConstant, 0);
22049    }
22050
22051    /**
22052     * BZZZTT!!1!
22053     *
22054     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22055     *
22056     * @param feedbackConstant One of the constants defined in
22057     * {@link HapticFeedbackConstants}
22058     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22059     */
22060    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22061        if (mAttachInfo == null) {
22062            return false;
22063        }
22064        //noinspection SimplifiableIfStatement
22065        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22066                && !isHapticFeedbackEnabled()) {
22067            return false;
22068        }
22069        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22070                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22071    }
22072
22073    /**
22074     * Request that the visibility of the status bar or other screen/window
22075     * decorations be changed.
22076     *
22077     * <p>This method is used to put the over device UI into temporary modes
22078     * where the user's attention is focused more on the application content,
22079     * by dimming or hiding surrounding system affordances.  This is typically
22080     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22081     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22082     * to be placed behind the action bar (and with these flags other system
22083     * affordances) so that smooth transitions between hiding and showing them
22084     * can be done.
22085     *
22086     * <p>Two representative examples of the use of system UI visibility is
22087     * implementing a content browsing application (like a magazine reader)
22088     * and a video playing application.
22089     *
22090     * <p>The first code shows a typical implementation of a View in a content
22091     * browsing application.  In this implementation, the application goes
22092     * into a content-oriented mode by hiding the status bar and action bar,
22093     * and putting the navigation elements into lights out mode.  The user can
22094     * then interact with content while in this mode.  Such an application should
22095     * provide an easy way for the user to toggle out of the mode (such as to
22096     * check information in the status bar or access notifications).  In the
22097     * implementation here, this is done simply by tapping on the content.
22098     *
22099     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22100     *      content}
22101     *
22102     * <p>This second code sample shows a typical implementation of a View
22103     * in a video playing application.  In this situation, while the video is
22104     * playing the application would like to go into a complete full-screen mode,
22105     * to use as much of the display as possible for the video.  When in this state
22106     * the user can not interact with the application; the system intercepts
22107     * touching on the screen to pop the UI out of full screen mode.  See
22108     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22109     *
22110     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22111     *      content}
22112     *
22113     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22114     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22115     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22116     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22117     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22118     */
22119    public void setSystemUiVisibility(int visibility) {
22120        if (visibility != mSystemUiVisibility) {
22121            mSystemUiVisibility = visibility;
22122            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22123                mParent.recomputeViewAttributes(this);
22124            }
22125        }
22126    }
22127
22128    /**
22129     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22130     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22131     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22132     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22133     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22134     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22135     */
22136    public int getSystemUiVisibility() {
22137        return mSystemUiVisibility;
22138    }
22139
22140    /**
22141     * Returns the current system UI visibility that is currently set for
22142     * the entire window.  This is the combination of the
22143     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22144     * views in the window.
22145     */
22146    public int getWindowSystemUiVisibility() {
22147        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22148    }
22149
22150    /**
22151     * Override to find out when the window's requested system UI visibility
22152     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22153     * This is different from the callbacks received through
22154     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22155     * in that this is only telling you about the local request of the window,
22156     * not the actual values applied by the system.
22157     */
22158    public void onWindowSystemUiVisibilityChanged(int visible) {
22159    }
22160
22161    /**
22162     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22163     * the view hierarchy.
22164     */
22165    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22166        onWindowSystemUiVisibilityChanged(visible);
22167    }
22168
22169    /**
22170     * Set a listener to receive callbacks when the visibility of the system bar changes.
22171     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22172     */
22173    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22174        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22175        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22176            mParent.recomputeViewAttributes(this);
22177        }
22178    }
22179
22180    /**
22181     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22182     * the view hierarchy.
22183     */
22184    public void dispatchSystemUiVisibilityChanged(int visibility) {
22185        ListenerInfo li = mListenerInfo;
22186        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22187            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22188                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22189        }
22190    }
22191
22192    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22193        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22194        if (val != mSystemUiVisibility) {
22195            setSystemUiVisibility(val);
22196            return true;
22197        }
22198        return false;
22199    }
22200
22201    /** @hide */
22202    public void setDisabledSystemUiVisibility(int flags) {
22203        if (mAttachInfo != null) {
22204            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22205                mAttachInfo.mDisabledSystemUiVisibility = flags;
22206                if (mParent != null) {
22207                    mParent.recomputeViewAttributes(this);
22208                }
22209            }
22210        }
22211    }
22212
22213    /**
22214     * Creates an image that the system displays during the drag and drop
22215     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22216     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22217     * appearance as the given View. The default also positions the center of the drag shadow
22218     * directly under the touch point. If no View is provided (the constructor with no parameters
22219     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22220     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22221     * default is an invisible drag shadow.
22222     * <p>
22223     * You are not required to use the View you provide to the constructor as the basis of the
22224     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22225     * anything you want as the drag shadow.
22226     * </p>
22227     * <p>
22228     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22229     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22230     *  size and position of the drag shadow. It uses this data to construct a
22231     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22232     *  so that your application can draw the shadow image in the Canvas.
22233     * </p>
22234     *
22235     * <div class="special reference">
22236     * <h3>Developer Guides</h3>
22237     * <p>For a guide to implementing drag and drop features, read the
22238     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22239     * </div>
22240     */
22241    public static class DragShadowBuilder {
22242        private final WeakReference<View> mView;
22243
22244        /**
22245         * Constructs a shadow image builder based on a View. By default, the resulting drag
22246         * shadow will have the same appearance and dimensions as the View, with the touch point
22247         * over the center of the View.
22248         * @param view A View. Any View in scope can be used.
22249         */
22250        public DragShadowBuilder(View view) {
22251            mView = new WeakReference<View>(view);
22252        }
22253
22254        /**
22255         * Construct a shadow builder object with no associated View.  This
22256         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22257         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22258         * to supply the drag shadow's dimensions and appearance without
22259         * reference to any View object. If they are not overridden, then the result is an
22260         * invisible drag shadow.
22261         */
22262        public DragShadowBuilder() {
22263            mView = new WeakReference<View>(null);
22264        }
22265
22266        /**
22267         * Returns the View object that had been passed to the
22268         * {@link #View.DragShadowBuilder(View)}
22269         * constructor.  If that View parameter was {@code null} or if the
22270         * {@link #View.DragShadowBuilder()}
22271         * constructor was used to instantiate the builder object, this method will return
22272         * null.
22273         *
22274         * @return The View object associate with this builder object.
22275         */
22276        @SuppressWarnings({"JavadocReference"})
22277        final public View getView() {
22278            return mView.get();
22279        }
22280
22281        /**
22282         * Provides the metrics for the shadow image. These include the dimensions of
22283         * the shadow image, and the point within that shadow that should
22284         * be centered under the touch location while dragging.
22285         * <p>
22286         * The default implementation sets the dimensions of the shadow to be the
22287         * same as the dimensions of the View itself and centers the shadow under
22288         * the touch point.
22289         * </p>
22290         *
22291         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22292         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22293         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22294         * image.
22295         *
22296         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22297         * shadow image that should be underneath the touch point during the drag and drop
22298         * operation. Your application must set {@link android.graphics.Point#x} to the
22299         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22300         */
22301        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22302            final View view = mView.get();
22303            if (view != null) {
22304                outShadowSize.set(view.getWidth(), view.getHeight());
22305                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22306            } else {
22307                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22308            }
22309        }
22310
22311        /**
22312         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22313         * based on the dimensions it received from the
22314         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22315         *
22316         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22317         */
22318        public void onDrawShadow(Canvas canvas) {
22319            final View view = mView.get();
22320            if (view != null) {
22321                view.draw(canvas);
22322            } else {
22323                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22324            }
22325        }
22326    }
22327
22328    /**
22329     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22330     * startDragAndDrop()} for newer platform versions.
22331     */
22332    @Deprecated
22333    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22334                                   Object myLocalState, int flags) {
22335        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22336    }
22337
22338    /**
22339     * Starts a drag and drop operation. When your application calls this method, it passes a
22340     * {@link android.view.View.DragShadowBuilder} object to the system. The
22341     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22342     * to get metrics for the drag shadow, and then calls the object's
22343     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22344     * <p>
22345     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22346     *  drag events to all the View objects in your application that are currently visible. It does
22347     *  this either by calling the View object's drag listener (an implementation of
22348     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22349     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22350     *  Both are passed a {@link android.view.DragEvent} object that has a
22351     *  {@link android.view.DragEvent#getAction()} value of
22352     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22353     * </p>
22354     * <p>
22355     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22356     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22357     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22358     * to the View the user selected for dragging.
22359     * </p>
22360     * @param data A {@link android.content.ClipData} object pointing to the data to be
22361     * transferred by the drag and drop operation.
22362     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22363     * drag shadow.
22364     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22365     * drop operation. When dispatching drag events to views in the same activity this object
22366     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22367     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22368     * will return null).
22369     * <p>
22370     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22371     * to the target Views. For example, it can contain flags that differentiate between a
22372     * a copy operation and a move operation.
22373     * </p>
22374     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22375     * flags, or any combination of the following:
22376     *     <ul>
22377     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22378     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22379     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22380     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22381     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22382     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22383     *     </ul>
22384     * @return {@code true} if the method completes successfully, or
22385     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22386     * do a drag, and so no drag operation is in progress.
22387     */
22388    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22389            Object myLocalState, int flags) {
22390        if (ViewDebug.DEBUG_DRAG) {
22391            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22392        }
22393        if (mAttachInfo == null) {
22394            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22395            return false;
22396        }
22397
22398        if (data != null) {
22399            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22400        }
22401
22402        boolean okay = false;
22403
22404        Point shadowSize = new Point();
22405        Point shadowTouchPoint = new Point();
22406        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22407
22408        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22409                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22410            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22411        }
22412
22413        if (ViewDebug.DEBUG_DRAG) {
22414            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22415                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22416        }
22417        if (mAttachInfo.mDragSurface != null) {
22418            mAttachInfo.mDragSurface.release();
22419        }
22420        mAttachInfo.mDragSurface = new Surface();
22421        try {
22422            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22423                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22424            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22425                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22426            if (mAttachInfo.mDragToken != null) {
22427                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22428                try {
22429                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22430                    shadowBuilder.onDrawShadow(canvas);
22431                } finally {
22432                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22433                }
22434
22435                final ViewRootImpl root = getViewRootImpl();
22436
22437                // Cache the local state object for delivery with DragEvents
22438                root.setLocalDragState(myLocalState);
22439
22440                // repurpose 'shadowSize' for the last touch point
22441                root.getLastTouchPoint(shadowSize);
22442
22443                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22444                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22445                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22446                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22447            }
22448        } catch (Exception e) {
22449            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22450            mAttachInfo.mDragSurface.destroy();
22451            mAttachInfo.mDragSurface = null;
22452        }
22453
22454        return okay;
22455    }
22456
22457    /**
22458     * Cancels an ongoing drag and drop operation.
22459     * <p>
22460     * A {@link android.view.DragEvent} object with
22461     * {@link android.view.DragEvent#getAction()} value of
22462     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22463     * {@link android.view.DragEvent#getResult()} value of {@code false}
22464     * will be sent to every
22465     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22466     * even if they are not currently visible.
22467     * </p>
22468     * <p>
22469     * This method can be called on any View in the same window as the View on which
22470     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22471     * was called.
22472     * </p>
22473     */
22474    public final void cancelDragAndDrop() {
22475        if (ViewDebug.DEBUG_DRAG) {
22476            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22477        }
22478        if (mAttachInfo == null) {
22479            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22480            return;
22481        }
22482        if (mAttachInfo.mDragToken != null) {
22483            try {
22484                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22485            } catch (Exception e) {
22486                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22487            }
22488            mAttachInfo.mDragToken = null;
22489        } else {
22490            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22491        }
22492    }
22493
22494    /**
22495     * Updates the drag shadow for the ongoing drag and drop operation.
22496     *
22497     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22498     * new drag shadow.
22499     */
22500    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22501        if (ViewDebug.DEBUG_DRAG) {
22502            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22503        }
22504        if (mAttachInfo == null) {
22505            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22506            return;
22507        }
22508        if (mAttachInfo.mDragToken != null) {
22509            try {
22510                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22511                try {
22512                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22513                    shadowBuilder.onDrawShadow(canvas);
22514                } finally {
22515                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22516                }
22517            } catch (Exception e) {
22518                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22519            }
22520        } else {
22521            Log.e(VIEW_LOG_TAG, "No active drag");
22522        }
22523    }
22524
22525    /**
22526     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22527     * between {startX, startY} and the new cursor positon.
22528     * @param startX horizontal coordinate where the move started.
22529     * @param startY vertical coordinate where the move started.
22530     * @return whether moving was started successfully.
22531     * @hide
22532     */
22533    public final boolean startMovingTask(float startX, float startY) {
22534        if (ViewDebug.DEBUG_POSITIONING) {
22535            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22536        }
22537        try {
22538            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22539        } catch (RemoteException e) {
22540            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22541        }
22542        return false;
22543    }
22544
22545    /**
22546     * Handles drag events sent by the system following a call to
22547     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22548     * startDragAndDrop()}.
22549     *<p>
22550     * When the system calls this method, it passes a
22551     * {@link android.view.DragEvent} object. A call to
22552     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22553     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22554     * operation.
22555     * @param event The {@link android.view.DragEvent} sent by the system.
22556     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22557     * in DragEvent, indicating the type of drag event represented by this object.
22558     * @return {@code true} if the method was successful, otherwise {@code false}.
22559     * <p>
22560     *  The method should return {@code true} in response to an action type of
22561     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22562     *  operation.
22563     * </p>
22564     * <p>
22565     *  The method should also return {@code true} in response to an action type of
22566     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22567     *  {@code false} if it didn't.
22568     * </p>
22569     * <p>
22570     *  For all other events, the return value is ignored.
22571     * </p>
22572     */
22573    public boolean onDragEvent(DragEvent event) {
22574        return false;
22575    }
22576
22577    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22578    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22579        return callDragEventHandler(event);
22580    }
22581
22582    /**
22583     * Detects if this View is enabled and has a drag event listener.
22584     * If both are true, then it calls the drag event listener with the
22585     * {@link android.view.DragEvent} it received. If the drag event listener returns
22586     * {@code true}, then dispatchDragEvent() returns {@code true}.
22587     * <p>
22588     * For all other cases, the method calls the
22589     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22590     * method and returns its result.
22591     * </p>
22592     * <p>
22593     * This ensures that a drag event is always consumed, even if the View does not have a drag
22594     * event listener. However, if the View has a listener and the listener returns true, then
22595     * onDragEvent() is not called.
22596     * </p>
22597     */
22598    public boolean dispatchDragEvent(DragEvent event) {
22599        event.mEventHandlerWasCalled = true;
22600        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22601            event.mAction == DragEvent.ACTION_DROP) {
22602            // About to deliver an event with coordinates to this view. Notify that now this view
22603            // has drag focus. This will send exit/enter events as needed.
22604            getViewRootImpl().setDragFocus(this, event);
22605        }
22606        return callDragEventHandler(event);
22607    }
22608
22609    final boolean callDragEventHandler(DragEvent event) {
22610        final boolean result;
22611
22612        ListenerInfo li = mListenerInfo;
22613        //noinspection SimplifiableIfStatement
22614        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22615                && li.mOnDragListener.onDrag(this, event)) {
22616            result = true;
22617        } else {
22618            result = onDragEvent(event);
22619        }
22620
22621        switch (event.mAction) {
22622            case DragEvent.ACTION_DRAG_ENTERED: {
22623                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22624                refreshDrawableState();
22625            } break;
22626            case DragEvent.ACTION_DRAG_EXITED: {
22627                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22628                refreshDrawableState();
22629            } break;
22630            case DragEvent.ACTION_DRAG_ENDED: {
22631                mPrivateFlags2 &= ~View.DRAG_MASK;
22632                refreshDrawableState();
22633            } break;
22634        }
22635
22636        return result;
22637    }
22638
22639    boolean canAcceptDrag() {
22640        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22641    }
22642
22643    /**
22644     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22645     * it is ever exposed at all.
22646     * @hide
22647     */
22648    public void onCloseSystemDialogs(String reason) {
22649    }
22650
22651    /**
22652     * Given a Drawable whose bounds have been set to draw into this view,
22653     * update a Region being computed for
22654     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22655     * that any non-transparent parts of the Drawable are removed from the
22656     * given transparent region.
22657     *
22658     * @param dr The Drawable whose transparency is to be applied to the region.
22659     * @param region A Region holding the current transparency information,
22660     * where any parts of the region that are set are considered to be
22661     * transparent.  On return, this region will be modified to have the
22662     * transparency information reduced by the corresponding parts of the
22663     * Drawable that are not transparent.
22664     * {@hide}
22665     */
22666    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22667        if (DBG) {
22668            Log.i("View", "Getting transparent region for: " + this);
22669        }
22670        final Region r = dr.getTransparentRegion();
22671        final Rect db = dr.getBounds();
22672        final AttachInfo attachInfo = mAttachInfo;
22673        if (r != null && attachInfo != null) {
22674            final int w = getRight()-getLeft();
22675            final int h = getBottom()-getTop();
22676            if (db.left > 0) {
22677                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22678                r.op(0, 0, db.left, h, Region.Op.UNION);
22679            }
22680            if (db.right < w) {
22681                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22682                r.op(db.right, 0, w, h, Region.Op.UNION);
22683            }
22684            if (db.top > 0) {
22685                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22686                r.op(0, 0, w, db.top, Region.Op.UNION);
22687            }
22688            if (db.bottom < h) {
22689                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22690                r.op(0, db.bottom, w, h, Region.Op.UNION);
22691            }
22692            final int[] location = attachInfo.mTransparentLocation;
22693            getLocationInWindow(location);
22694            r.translate(location[0], location[1]);
22695            region.op(r, Region.Op.INTERSECT);
22696        } else {
22697            region.op(db, Region.Op.DIFFERENCE);
22698        }
22699    }
22700
22701    private void checkForLongClick(int delayOffset, float x, float y) {
22702        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22703            mHasPerformedLongPress = false;
22704
22705            if (mPendingCheckForLongPress == null) {
22706                mPendingCheckForLongPress = new CheckForLongPress();
22707            }
22708            mPendingCheckForLongPress.setAnchor(x, y);
22709            mPendingCheckForLongPress.rememberWindowAttachCount();
22710            mPendingCheckForLongPress.rememberPressedState();
22711            postDelayed(mPendingCheckForLongPress,
22712                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22713        }
22714    }
22715
22716    /**
22717     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22718     * LayoutInflater} class, which provides a full range of options for view inflation.
22719     *
22720     * @param context The Context object for your activity or application.
22721     * @param resource The resource ID to inflate
22722     * @param root A view group that will be the parent.  Used to properly inflate the
22723     * layout_* parameters.
22724     * @see LayoutInflater
22725     */
22726    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22727        LayoutInflater factory = LayoutInflater.from(context);
22728        return factory.inflate(resource, root);
22729    }
22730
22731    /**
22732     * Scroll the view with standard behavior for scrolling beyond the normal
22733     * content boundaries. Views that call this method should override
22734     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22735     * results of an over-scroll operation.
22736     *
22737     * Views can use this method to handle any touch or fling-based scrolling.
22738     *
22739     * @param deltaX Change in X in pixels
22740     * @param deltaY Change in Y in pixels
22741     * @param scrollX Current X scroll value in pixels before applying deltaX
22742     * @param scrollY Current Y scroll value in pixels before applying deltaY
22743     * @param scrollRangeX Maximum content scroll range along the X axis
22744     * @param scrollRangeY Maximum content scroll range along the Y axis
22745     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22746     *          along the X axis.
22747     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22748     *          along the Y axis.
22749     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22750     * @return true if scrolling was clamped to an over-scroll boundary along either
22751     *          axis, false otherwise.
22752     */
22753    @SuppressWarnings({"UnusedParameters"})
22754    protected boolean overScrollBy(int deltaX, int deltaY,
22755            int scrollX, int scrollY,
22756            int scrollRangeX, int scrollRangeY,
22757            int maxOverScrollX, int maxOverScrollY,
22758            boolean isTouchEvent) {
22759        final int overScrollMode = mOverScrollMode;
22760        final boolean canScrollHorizontal =
22761                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22762        final boolean canScrollVertical =
22763                computeVerticalScrollRange() > computeVerticalScrollExtent();
22764        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22765                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22766        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22767                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22768
22769        int newScrollX = scrollX + deltaX;
22770        if (!overScrollHorizontal) {
22771            maxOverScrollX = 0;
22772        }
22773
22774        int newScrollY = scrollY + deltaY;
22775        if (!overScrollVertical) {
22776            maxOverScrollY = 0;
22777        }
22778
22779        // Clamp values if at the limits and record
22780        final int left = -maxOverScrollX;
22781        final int right = maxOverScrollX + scrollRangeX;
22782        final int top = -maxOverScrollY;
22783        final int bottom = maxOverScrollY + scrollRangeY;
22784
22785        boolean clampedX = false;
22786        if (newScrollX > right) {
22787            newScrollX = right;
22788            clampedX = true;
22789        } else if (newScrollX < left) {
22790            newScrollX = left;
22791            clampedX = true;
22792        }
22793
22794        boolean clampedY = false;
22795        if (newScrollY > bottom) {
22796            newScrollY = bottom;
22797            clampedY = true;
22798        } else if (newScrollY < top) {
22799            newScrollY = top;
22800            clampedY = true;
22801        }
22802
22803        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22804
22805        return clampedX || clampedY;
22806    }
22807
22808    /**
22809     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22810     * respond to the results of an over-scroll operation.
22811     *
22812     * @param scrollX New X scroll value in pixels
22813     * @param scrollY New Y scroll value in pixels
22814     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22815     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22816     */
22817    protected void onOverScrolled(int scrollX, int scrollY,
22818            boolean clampedX, boolean clampedY) {
22819        // Intentionally empty.
22820    }
22821
22822    /**
22823     * Returns the over-scroll mode for this view. The result will be
22824     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22825     * (allow over-scrolling only if the view content is larger than the container),
22826     * or {@link #OVER_SCROLL_NEVER}.
22827     *
22828     * @return This view's over-scroll mode.
22829     */
22830    public int getOverScrollMode() {
22831        return mOverScrollMode;
22832    }
22833
22834    /**
22835     * Set the over-scroll mode for this view. Valid over-scroll modes are
22836     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22837     * (allow over-scrolling only if the view content is larger than the container),
22838     * or {@link #OVER_SCROLL_NEVER}.
22839     *
22840     * Setting the over-scroll mode of a view will have an effect only if the
22841     * view is capable of scrolling.
22842     *
22843     * @param overScrollMode The new over-scroll mode for this view.
22844     */
22845    public void setOverScrollMode(int overScrollMode) {
22846        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22847                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22848                overScrollMode != OVER_SCROLL_NEVER) {
22849            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22850        }
22851        mOverScrollMode = overScrollMode;
22852    }
22853
22854    /**
22855     * Enable or disable nested scrolling for this view.
22856     *
22857     * <p>If this property is set to true the view will be permitted to initiate nested
22858     * scrolling operations with a compatible parent view in the current hierarchy. If this
22859     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22860     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22861     * the nested scroll.</p>
22862     *
22863     * @param enabled true to enable nested scrolling, false to disable
22864     *
22865     * @see #isNestedScrollingEnabled()
22866     */
22867    public void setNestedScrollingEnabled(boolean enabled) {
22868        if (enabled) {
22869            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22870        } else {
22871            stopNestedScroll();
22872            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22873        }
22874    }
22875
22876    /**
22877     * Returns true if nested scrolling is enabled for this view.
22878     *
22879     * <p>If nested scrolling is enabled and this View class implementation supports it,
22880     * this view will act as a nested scrolling child view when applicable, forwarding data
22881     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22882     * parent.</p>
22883     *
22884     * @return true if nested scrolling is enabled
22885     *
22886     * @see #setNestedScrollingEnabled(boolean)
22887     */
22888    public boolean isNestedScrollingEnabled() {
22889        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22890                PFLAG3_NESTED_SCROLLING_ENABLED;
22891    }
22892
22893    /**
22894     * Begin a nestable scroll operation along the given axes.
22895     *
22896     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22897     *
22898     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22899     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22900     * In the case of touch scrolling the nested scroll will be terminated automatically in
22901     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22902     * In the event of programmatic scrolling the caller must explicitly call
22903     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22904     *
22905     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22906     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22907     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22908     *
22909     * <p>At each incremental step of the scroll the caller should invoke
22910     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22911     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22912     * parent at least partially consumed the scroll and the caller should adjust the amount it
22913     * scrolls by.</p>
22914     *
22915     * <p>After applying the remainder of the scroll delta the caller should invoke
22916     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22917     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22918     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22919     * </p>
22920     *
22921     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22922     *             {@link #SCROLL_AXIS_VERTICAL}.
22923     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22924     *         the current gesture.
22925     *
22926     * @see #stopNestedScroll()
22927     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22928     * @see #dispatchNestedScroll(int, int, int, int, int[])
22929     */
22930    public boolean startNestedScroll(int axes) {
22931        if (hasNestedScrollingParent()) {
22932            // Already in progress
22933            return true;
22934        }
22935        if (isNestedScrollingEnabled()) {
22936            ViewParent p = getParent();
22937            View child = this;
22938            while (p != null) {
22939                try {
22940                    if (p.onStartNestedScroll(child, this, axes)) {
22941                        mNestedScrollingParent = p;
22942                        p.onNestedScrollAccepted(child, this, axes);
22943                        return true;
22944                    }
22945                } catch (AbstractMethodError e) {
22946                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22947                            "method onStartNestedScroll", e);
22948                    // Allow the search upward to continue
22949                }
22950                if (p instanceof View) {
22951                    child = (View) p;
22952                }
22953                p = p.getParent();
22954            }
22955        }
22956        return false;
22957    }
22958
22959    /**
22960     * Stop a nested scroll in progress.
22961     *
22962     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22963     *
22964     * @see #startNestedScroll(int)
22965     */
22966    public void stopNestedScroll() {
22967        if (mNestedScrollingParent != null) {
22968            mNestedScrollingParent.onStopNestedScroll(this);
22969            mNestedScrollingParent = null;
22970        }
22971    }
22972
22973    /**
22974     * Returns true if this view has a nested scrolling parent.
22975     *
22976     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22977     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22978     *
22979     * @return whether this view has a nested scrolling parent
22980     */
22981    public boolean hasNestedScrollingParent() {
22982        return mNestedScrollingParent != null;
22983    }
22984
22985    /**
22986     * Dispatch one step of a nested scroll in progress.
22987     *
22988     * <p>Implementations of views that support nested scrolling should call this to report
22989     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
22990     * is not currently in progress or nested scrolling is not
22991     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
22992     *
22993     * <p>Compatible View implementations should also call
22994     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
22995     * consuming a component of the scroll event themselves.</p>
22996     *
22997     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
22998     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
22999     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23000     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23001     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23002     *                       in local view coordinates of this view from before this operation
23003     *                       to after it completes. View implementations may use this to adjust
23004     *                       expected input coordinate tracking.
23005     * @return true if the event was dispatched, false if it could not be dispatched.
23006     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23007     */
23008    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23009            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23010        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23011            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23012                int startX = 0;
23013                int startY = 0;
23014                if (offsetInWindow != null) {
23015                    getLocationInWindow(offsetInWindow);
23016                    startX = offsetInWindow[0];
23017                    startY = offsetInWindow[1];
23018                }
23019
23020                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23021                        dxUnconsumed, dyUnconsumed);
23022
23023                if (offsetInWindow != null) {
23024                    getLocationInWindow(offsetInWindow);
23025                    offsetInWindow[0] -= startX;
23026                    offsetInWindow[1] -= startY;
23027                }
23028                return true;
23029            } else if (offsetInWindow != null) {
23030                // No motion, no dispatch. Keep offsetInWindow up to date.
23031                offsetInWindow[0] = 0;
23032                offsetInWindow[1] = 0;
23033            }
23034        }
23035        return false;
23036    }
23037
23038    /**
23039     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23040     *
23041     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23042     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23043     * scrolling operation to consume some or all of the scroll operation before the child view
23044     * consumes it.</p>
23045     *
23046     * @param dx Horizontal scroll distance in pixels
23047     * @param dy Vertical scroll distance in pixels
23048     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23049     *                 and consumed[1] the consumed dy.
23050     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23051     *                       in local view coordinates of this view from before this operation
23052     *                       to after it completes. View implementations may use this to adjust
23053     *                       expected input coordinate tracking.
23054     * @return true if the parent consumed some or all of the scroll delta
23055     * @see #dispatchNestedScroll(int, int, int, int, int[])
23056     */
23057    public boolean dispatchNestedPreScroll(int dx, int dy,
23058            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23059        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23060            if (dx != 0 || dy != 0) {
23061                int startX = 0;
23062                int startY = 0;
23063                if (offsetInWindow != null) {
23064                    getLocationInWindow(offsetInWindow);
23065                    startX = offsetInWindow[0];
23066                    startY = offsetInWindow[1];
23067                }
23068
23069                if (consumed == null) {
23070                    if (mTempNestedScrollConsumed == null) {
23071                        mTempNestedScrollConsumed = new int[2];
23072                    }
23073                    consumed = mTempNestedScrollConsumed;
23074                }
23075                consumed[0] = 0;
23076                consumed[1] = 0;
23077                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23078
23079                if (offsetInWindow != null) {
23080                    getLocationInWindow(offsetInWindow);
23081                    offsetInWindow[0] -= startX;
23082                    offsetInWindow[1] -= startY;
23083                }
23084                return consumed[0] != 0 || consumed[1] != 0;
23085            } else if (offsetInWindow != null) {
23086                offsetInWindow[0] = 0;
23087                offsetInWindow[1] = 0;
23088            }
23089        }
23090        return false;
23091    }
23092
23093    /**
23094     * Dispatch a fling to a nested scrolling parent.
23095     *
23096     * <p>This method should be used to indicate that a nested scrolling child has detected
23097     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23098     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23099     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23100     * along a scrollable axis.</p>
23101     *
23102     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23103     * its own content, it can use this method to delegate the fling to its nested scrolling
23104     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23105     *
23106     * @param velocityX Horizontal fling velocity in pixels per second
23107     * @param velocityY Vertical fling velocity in pixels per second
23108     * @param consumed true if the child consumed the fling, false otherwise
23109     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23110     */
23111    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23112        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23113            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23114        }
23115        return false;
23116    }
23117
23118    /**
23119     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23120     *
23121     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23122     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23123     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23124     * before the child view consumes it. If this method returns <code>true</code>, a nested
23125     * parent view consumed the fling and this view should not scroll as a result.</p>
23126     *
23127     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23128     * the fling at a time. If a parent view consumed the fling this method will return false.
23129     * Custom view implementations should account for this in two ways:</p>
23130     *
23131     * <ul>
23132     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23133     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23134     *     position regardless.</li>
23135     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23136     *     even to settle back to a valid idle position.</li>
23137     * </ul>
23138     *
23139     * <p>Views should also not offer fling velocities to nested parent views along an axis
23140     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23141     * should not offer a horizontal fling velocity to its parents since scrolling along that
23142     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23143     *
23144     * @param velocityX Horizontal fling velocity in pixels per second
23145     * @param velocityY Vertical fling velocity in pixels per second
23146     * @return true if a nested scrolling parent consumed the fling
23147     */
23148    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23149        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23150            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23151        }
23152        return false;
23153    }
23154
23155    /**
23156     * Gets a scale factor that determines the distance the view should scroll
23157     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23158     * @return The vertical scroll scale factor.
23159     * @hide
23160     */
23161    protected float getVerticalScrollFactor() {
23162        if (mVerticalScrollFactor == 0) {
23163            TypedValue outValue = new TypedValue();
23164            if (!mContext.getTheme().resolveAttribute(
23165                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23166                throw new IllegalStateException(
23167                        "Expected theme to define listPreferredItemHeight.");
23168            }
23169            mVerticalScrollFactor = outValue.getDimension(
23170                    mContext.getResources().getDisplayMetrics());
23171        }
23172        return mVerticalScrollFactor;
23173    }
23174
23175    /**
23176     * Gets a scale factor that determines the distance the view should scroll
23177     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23178     * @return The horizontal scroll scale factor.
23179     * @hide
23180     */
23181    protected float getHorizontalScrollFactor() {
23182        // TODO: Should use something else.
23183        return getVerticalScrollFactor();
23184    }
23185
23186    /**
23187     * Return the value specifying the text direction or policy that was set with
23188     * {@link #setTextDirection(int)}.
23189     *
23190     * @return the defined text direction. It can be one of:
23191     *
23192     * {@link #TEXT_DIRECTION_INHERIT},
23193     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23194     * {@link #TEXT_DIRECTION_ANY_RTL},
23195     * {@link #TEXT_DIRECTION_LTR},
23196     * {@link #TEXT_DIRECTION_RTL},
23197     * {@link #TEXT_DIRECTION_LOCALE},
23198     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23199     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23200     *
23201     * @attr ref android.R.styleable#View_textDirection
23202     *
23203     * @hide
23204     */
23205    @ViewDebug.ExportedProperty(category = "text", mapping = {
23206            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23207            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23208            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23209            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23210            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23211            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23212            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23213            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23214    })
23215    public int getRawTextDirection() {
23216        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23217    }
23218
23219    /**
23220     * Set the text direction.
23221     *
23222     * @param textDirection the direction to set. Should be one of:
23223     *
23224     * {@link #TEXT_DIRECTION_INHERIT},
23225     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23226     * {@link #TEXT_DIRECTION_ANY_RTL},
23227     * {@link #TEXT_DIRECTION_LTR},
23228     * {@link #TEXT_DIRECTION_RTL},
23229     * {@link #TEXT_DIRECTION_LOCALE}
23230     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23231     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23232     *
23233     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23234     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23235     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23236     *
23237     * @attr ref android.R.styleable#View_textDirection
23238     */
23239    public void setTextDirection(int textDirection) {
23240        if (getRawTextDirection() != textDirection) {
23241            // Reset the current text direction and the resolved one
23242            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23243            resetResolvedTextDirection();
23244            // Set the new text direction
23245            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23246            // Do resolution
23247            resolveTextDirection();
23248            // Notify change
23249            onRtlPropertiesChanged(getLayoutDirection());
23250            // Refresh
23251            requestLayout();
23252            invalidate(true);
23253        }
23254    }
23255
23256    /**
23257     * Return the resolved text direction.
23258     *
23259     * @return the resolved text direction. Returns one of:
23260     *
23261     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23262     * {@link #TEXT_DIRECTION_ANY_RTL},
23263     * {@link #TEXT_DIRECTION_LTR},
23264     * {@link #TEXT_DIRECTION_RTL},
23265     * {@link #TEXT_DIRECTION_LOCALE},
23266     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23267     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23268     *
23269     * @attr ref android.R.styleable#View_textDirection
23270     */
23271    @ViewDebug.ExportedProperty(category = "text", mapping = {
23272            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23273            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23274            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23275            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23276            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23277            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23278            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23279            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23280    })
23281    public int getTextDirection() {
23282        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23283    }
23284
23285    /**
23286     * Resolve the text direction.
23287     *
23288     * @return true if resolution has been done, false otherwise.
23289     *
23290     * @hide
23291     */
23292    public boolean resolveTextDirection() {
23293        // Reset any previous text direction resolution
23294        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23295
23296        if (hasRtlSupport()) {
23297            // Set resolved text direction flag depending on text direction flag
23298            final int textDirection = getRawTextDirection();
23299            switch(textDirection) {
23300                case TEXT_DIRECTION_INHERIT:
23301                    if (!canResolveTextDirection()) {
23302                        // We cannot do the resolution if there is no parent, so use the default one
23303                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23304                        // Resolution will need to happen again later
23305                        return false;
23306                    }
23307
23308                    // Parent has not yet resolved, so we still return the default
23309                    try {
23310                        if (!mParent.isTextDirectionResolved()) {
23311                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23312                            // Resolution will need to happen again later
23313                            return false;
23314                        }
23315                    } catch (AbstractMethodError e) {
23316                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23317                                " does not fully implement ViewParent", e);
23318                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23319                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23320                        return true;
23321                    }
23322
23323                    // Set current resolved direction to the same value as the parent's one
23324                    int parentResolvedDirection;
23325                    try {
23326                        parentResolvedDirection = mParent.getTextDirection();
23327                    } catch (AbstractMethodError e) {
23328                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23329                                " does not fully implement ViewParent", e);
23330                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23331                    }
23332                    switch (parentResolvedDirection) {
23333                        case TEXT_DIRECTION_FIRST_STRONG:
23334                        case TEXT_DIRECTION_ANY_RTL:
23335                        case TEXT_DIRECTION_LTR:
23336                        case TEXT_DIRECTION_RTL:
23337                        case TEXT_DIRECTION_LOCALE:
23338                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23339                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23340                            mPrivateFlags2 |=
23341                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23342                            break;
23343                        default:
23344                            // Default resolved direction is "first strong" heuristic
23345                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23346                    }
23347                    break;
23348                case TEXT_DIRECTION_FIRST_STRONG:
23349                case TEXT_DIRECTION_ANY_RTL:
23350                case TEXT_DIRECTION_LTR:
23351                case TEXT_DIRECTION_RTL:
23352                case TEXT_DIRECTION_LOCALE:
23353                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23354                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23355                    // Resolved direction is the same as text direction
23356                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23357                    break;
23358                default:
23359                    // Default resolved direction is "first strong" heuristic
23360                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23361            }
23362        } else {
23363            // Default resolved direction is "first strong" heuristic
23364            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23365        }
23366
23367        // Set to resolved
23368        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23369        return true;
23370    }
23371
23372    /**
23373     * Check if text direction resolution can be done.
23374     *
23375     * @return true if text direction resolution can be done otherwise return false.
23376     */
23377    public boolean canResolveTextDirection() {
23378        switch (getRawTextDirection()) {
23379            case TEXT_DIRECTION_INHERIT:
23380                if (mParent != null) {
23381                    try {
23382                        return mParent.canResolveTextDirection();
23383                    } catch (AbstractMethodError e) {
23384                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23385                                " does not fully implement ViewParent", e);
23386                    }
23387                }
23388                return false;
23389
23390            default:
23391                return true;
23392        }
23393    }
23394
23395    /**
23396     * Reset resolved text direction. Text direction will be resolved during a call to
23397     * {@link #onMeasure(int, int)}.
23398     *
23399     * @hide
23400     */
23401    public void resetResolvedTextDirection() {
23402        // Reset any previous text direction resolution
23403        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23404        // Set to default value
23405        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23406    }
23407
23408    /**
23409     * @return true if text direction is inherited.
23410     *
23411     * @hide
23412     */
23413    public boolean isTextDirectionInherited() {
23414        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23415    }
23416
23417    /**
23418     * @return true if text direction is resolved.
23419     */
23420    public boolean isTextDirectionResolved() {
23421        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23422    }
23423
23424    /**
23425     * Return the value specifying the text alignment or policy that was set with
23426     * {@link #setTextAlignment(int)}.
23427     *
23428     * @return the defined text alignment. It can be one of:
23429     *
23430     * {@link #TEXT_ALIGNMENT_INHERIT},
23431     * {@link #TEXT_ALIGNMENT_GRAVITY},
23432     * {@link #TEXT_ALIGNMENT_CENTER},
23433     * {@link #TEXT_ALIGNMENT_TEXT_START},
23434     * {@link #TEXT_ALIGNMENT_TEXT_END},
23435     * {@link #TEXT_ALIGNMENT_VIEW_START},
23436     * {@link #TEXT_ALIGNMENT_VIEW_END}
23437     *
23438     * @attr ref android.R.styleable#View_textAlignment
23439     *
23440     * @hide
23441     */
23442    @ViewDebug.ExportedProperty(category = "text", mapping = {
23443            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23444            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23445            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23446            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23447            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23448            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23449            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23450    })
23451    @TextAlignment
23452    public int getRawTextAlignment() {
23453        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23454    }
23455
23456    /**
23457     * Set the text alignment.
23458     *
23459     * @param textAlignment The text alignment to set. Should be one of
23460     *
23461     * {@link #TEXT_ALIGNMENT_INHERIT},
23462     * {@link #TEXT_ALIGNMENT_GRAVITY},
23463     * {@link #TEXT_ALIGNMENT_CENTER},
23464     * {@link #TEXT_ALIGNMENT_TEXT_START},
23465     * {@link #TEXT_ALIGNMENT_TEXT_END},
23466     * {@link #TEXT_ALIGNMENT_VIEW_START},
23467     * {@link #TEXT_ALIGNMENT_VIEW_END}
23468     *
23469     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23470     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23471     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23472     *
23473     * @attr ref android.R.styleable#View_textAlignment
23474     */
23475    public void setTextAlignment(@TextAlignment int textAlignment) {
23476        if (textAlignment != getRawTextAlignment()) {
23477            // Reset the current and resolved text alignment
23478            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23479            resetResolvedTextAlignment();
23480            // Set the new text alignment
23481            mPrivateFlags2 |=
23482                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23483            // Do resolution
23484            resolveTextAlignment();
23485            // Notify change
23486            onRtlPropertiesChanged(getLayoutDirection());
23487            // Refresh
23488            requestLayout();
23489            invalidate(true);
23490        }
23491    }
23492
23493    /**
23494     * Return the resolved text alignment.
23495     *
23496     * @return the resolved text alignment. Returns one of:
23497     *
23498     * {@link #TEXT_ALIGNMENT_GRAVITY},
23499     * {@link #TEXT_ALIGNMENT_CENTER},
23500     * {@link #TEXT_ALIGNMENT_TEXT_START},
23501     * {@link #TEXT_ALIGNMENT_TEXT_END},
23502     * {@link #TEXT_ALIGNMENT_VIEW_START},
23503     * {@link #TEXT_ALIGNMENT_VIEW_END}
23504     *
23505     * @attr ref android.R.styleable#View_textAlignment
23506     */
23507    @ViewDebug.ExportedProperty(category = "text", mapping = {
23508            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23509            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23510            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23511            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23512            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23513            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23514            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23515    })
23516    @TextAlignment
23517    public int getTextAlignment() {
23518        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23519                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23520    }
23521
23522    /**
23523     * Resolve the text alignment.
23524     *
23525     * @return true if resolution has been done, false otherwise.
23526     *
23527     * @hide
23528     */
23529    public boolean resolveTextAlignment() {
23530        // Reset any previous text alignment resolution
23531        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23532
23533        if (hasRtlSupport()) {
23534            // Set resolved text alignment flag depending on text alignment flag
23535            final int textAlignment = getRawTextAlignment();
23536            switch (textAlignment) {
23537                case TEXT_ALIGNMENT_INHERIT:
23538                    // Check if we can resolve the text alignment
23539                    if (!canResolveTextAlignment()) {
23540                        // We cannot do the resolution if there is no parent so use the default
23541                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23542                        // Resolution will need to happen again later
23543                        return false;
23544                    }
23545
23546                    // Parent has not yet resolved, so we still return the default
23547                    try {
23548                        if (!mParent.isTextAlignmentResolved()) {
23549                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23550                            // Resolution will need to happen again later
23551                            return false;
23552                        }
23553                    } catch (AbstractMethodError e) {
23554                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23555                                " does not fully implement ViewParent", e);
23556                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23557                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23558                        return true;
23559                    }
23560
23561                    int parentResolvedTextAlignment;
23562                    try {
23563                        parentResolvedTextAlignment = mParent.getTextAlignment();
23564                    } catch (AbstractMethodError e) {
23565                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23566                                " does not fully implement ViewParent", e);
23567                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23568                    }
23569                    switch (parentResolvedTextAlignment) {
23570                        case TEXT_ALIGNMENT_GRAVITY:
23571                        case TEXT_ALIGNMENT_TEXT_START:
23572                        case TEXT_ALIGNMENT_TEXT_END:
23573                        case TEXT_ALIGNMENT_CENTER:
23574                        case TEXT_ALIGNMENT_VIEW_START:
23575                        case TEXT_ALIGNMENT_VIEW_END:
23576                            // Resolved text alignment is the same as the parent resolved
23577                            // text alignment
23578                            mPrivateFlags2 |=
23579                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23580                            break;
23581                        default:
23582                            // Use default resolved text alignment
23583                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23584                    }
23585                    break;
23586                case TEXT_ALIGNMENT_GRAVITY:
23587                case TEXT_ALIGNMENT_TEXT_START:
23588                case TEXT_ALIGNMENT_TEXT_END:
23589                case TEXT_ALIGNMENT_CENTER:
23590                case TEXT_ALIGNMENT_VIEW_START:
23591                case TEXT_ALIGNMENT_VIEW_END:
23592                    // Resolved text alignment is the same as text alignment
23593                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23594                    break;
23595                default:
23596                    // Use default resolved text alignment
23597                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23598            }
23599        } else {
23600            // Use default resolved text alignment
23601            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23602        }
23603
23604        // Set the resolved
23605        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23606        return true;
23607    }
23608
23609    /**
23610     * Check if text alignment resolution can be done.
23611     *
23612     * @return true if text alignment resolution can be done otherwise return false.
23613     */
23614    public boolean canResolveTextAlignment() {
23615        switch (getRawTextAlignment()) {
23616            case TEXT_DIRECTION_INHERIT:
23617                if (mParent != null) {
23618                    try {
23619                        return mParent.canResolveTextAlignment();
23620                    } catch (AbstractMethodError e) {
23621                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23622                                " does not fully implement ViewParent", e);
23623                    }
23624                }
23625                return false;
23626
23627            default:
23628                return true;
23629        }
23630    }
23631
23632    /**
23633     * Reset resolved text alignment. Text alignment will be resolved during a call to
23634     * {@link #onMeasure(int, int)}.
23635     *
23636     * @hide
23637     */
23638    public void resetResolvedTextAlignment() {
23639        // Reset any previous text alignment resolution
23640        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23641        // Set to default
23642        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23643    }
23644
23645    /**
23646     * @return true if text alignment is inherited.
23647     *
23648     * @hide
23649     */
23650    public boolean isTextAlignmentInherited() {
23651        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23652    }
23653
23654    /**
23655     * @return true if text alignment is resolved.
23656     */
23657    public boolean isTextAlignmentResolved() {
23658        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23659    }
23660
23661    /**
23662     * Generate a value suitable for use in {@link #setId(int)}.
23663     * This value will not collide with ID values generated at build time by aapt for R.id.
23664     *
23665     * @return a generated ID value
23666     */
23667    public static int generateViewId() {
23668        for (;;) {
23669            final int result = sNextGeneratedId.get();
23670            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23671            int newValue = result + 1;
23672            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23673            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23674                return result;
23675            }
23676        }
23677    }
23678
23679    private static boolean isViewIdGenerated(int id) {
23680        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23681    }
23682
23683    /**
23684     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23685     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23686     *                           a normal View or a ViewGroup with
23687     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23688     * @hide
23689     */
23690    public void captureTransitioningViews(List<View> transitioningViews) {
23691        if (getVisibility() == View.VISIBLE) {
23692            transitioningViews.add(this);
23693        }
23694    }
23695
23696    /**
23697     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23698     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23699     * @hide
23700     */
23701    public void findNamedViews(Map<String, View> namedElements) {
23702        if (getVisibility() == VISIBLE || mGhostView != null) {
23703            String transitionName = getTransitionName();
23704            if (transitionName != null) {
23705                namedElements.put(transitionName, this);
23706            }
23707        }
23708    }
23709
23710    /**
23711     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23712     * The default implementation does not care the location or event types, but some subclasses
23713     * may use it (such as WebViews).
23714     * @param event The MotionEvent from a mouse
23715     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23716     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23717     * @see PointerIcon
23718     */
23719    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23720        final float x = event.getX(pointerIndex);
23721        final float y = event.getY(pointerIndex);
23722        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23723            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23724        }
23725        return mPointerIcon;
23726    }
23727
23728    /**
23729     * Set the pointer icon for the current view.
23730     * Passing {@code null} will restore the pointer icon to its default value.
23731     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23732     */
23733    public void setPointerIcon(PointerIcon pointerIcon) {
23734        mPointerIcon = pointerIcon;
23735        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23736            return;
23737        }
23738        try {
23739            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23740        } catch (RemoteException e) {
23741        }
23742    }
23743
23744    /**
23745     * Gets the pointer icon for the current view.
23746     */
23747    public PointerIcon getPointerIcon() {
23748        return mPointerIcon;
23749    }
23750
23751    /**
23752     * Checks pointer capture status.
23753     *
23754     * @return true if the view has pointer capture.
23755     * @see #requestPointerCapture()
23756     * @see #hasPointerCapture()
23757     */
23758    public boolean hasPointerCapture() {
23759        final ViewRootImpl viewRootImpl = getViewRootImpl();
23760        if (viewRootImpl == null) {
23761            return false;
23762        }
23763        return viewRootImpl.hasPointerCapture();
23764    }
23765
23766    /**
23767     * Requests pointer capture mode.
23768     * <p>
23769     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23770     * change its position. Further mouse will be dispatched with the source
23771     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23772     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23773     * (touchscreens, or stylus) will not be affected.
23774     * <p>
23775     * If the window already has pointer capture, this call does nothing.
23776     * <p>
23777     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23778     * automatically when the window loses focus.
23779     *
23780     * @see #releasePointerCapture()
23781     * @see #hasPointerCapture()
23782     */
23783    public void requestPointerCapture() {
23784        final ViewRootImpl viewRootImpl = getViewRootImpl();
23785        if (viewRootImpl != null) {
23786            viewRootImpl.requestPointerCapture(true);
23787        }
23788    }
23789
23790
23791    /**
23792     * Releases the pointer capture.
23793     * <p>
23794     * If the window does not have pointer capture, this call will do nothing.
23795     * @see #requestPointerCapture()
23796     * @see #hasPointerCapture()
23797     */
23798    public void releasePointerCapture() {
23799        final ViewRootImpl viewRootImpl = getViewRootImpl();
23800        if (viewRootImpl != null) {
23801            viewRootImpl.requestPointerCapture(false);
23802        }
23803    }
23804
23805    /**
23806     * Called when the window has just acquired or lost pointer capture.
23807     *
23808     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23809     */
23810    @CallSuper
23811    public void onPointerCaptureChange(boolean hasCapture) {
23812    }
23813
23814    /**
23815     * @see #onPointerCaptureChange
23816     */
23817    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23818        onPointerCaptureChange(hasCapture);
23819    }
23820
23821    /**
23822     * Implement this method to handle captured pointer events
23823     *
23824     * @param event The captured pointer event.
23825     * @return True if the event was handled, false otherwise.
23826     * @see #requestPointerCapture()
23827     */
23828    public boolean onCapturedPointerEvent(MotionEvent event) {
23829        return false;
23830    }
23831
23832    /**
23833     * Interface definition for a callback to be invoked when a captured pointer event
23834     * is being dispatched this view. The callback will be invoked before the event is
23835     * given to the view.
23836     */
23837    public interface OnCapturedPointerListener {
23838        /**
23839         * Called when a captured pointer event is dispatched to a view.
23840         * @param view The view this event has been dispatched to.
23841         * @param event The captured event.
23842         * @return True if the listener has consumed the event, false otherwise.
23843         */
23844        boolean onCapturedPointer(View view, MotionEvent event);
23845    }
23846
23847    /**
23848     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23849     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23850     */
23851    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23852        getListenerInfo().mOnCapturedPointerListener = l;
23853    }
23854
23855    // Properties
23856    //
23857    /**
23858     * A Property wrapper around the <code>alpha</code> functionality handled by the
23859     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23860     */
23861    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23862        @Override
23863        public void setValue(View object, float value) {
23864            object.setAlpha(value);
23865        }
23866
23867        @Override
23868        public Float get(View object) {
23869            return object.getAlpha();
23870        }
23871    };
23872
23873    /**
23874     * A Property wrapper around the <code>translationX</code> functionality handled by the
23875     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23876     */
23877    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23878        @Override
23879        public void setValue(View object, float value) {
23880            object.setTranslationX(value);
23881        }
23882
23883                @Override
23884        public Float get(View object) {
23885            return object.getTranslationX();
23886        }
23887    };
23888
23889    /**
23890     * A Property wrapper around the <code>translationY</code> functionality handled by the
23891     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23892     */
23893    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23894        @Override
23895        public void setValue(View object, float value) {
23896            object.setTranslationY(value);
23897        }
23898
23899        @Override
23900        public Float get(View object) {
23901            return object.getTranslationY();
23902        }
23903    };
23904
23905    /**
23906     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23907     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23908     */
23909    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23910        @Override
23911        public void setValue(View object, float value) {
23912            object.setTranslationZ(value);
23913        }
23914
23915        @Override
23916        public Float get(View object) {
23917            return object.getTranslationZ();
23918        }
23919    };
23920
23921    /**
23922     * A Property wrapper around the <code>x</code> functionality handled by the
23923     * {@link View#setX(float)} and {@link View#getX()} methods.
23924     */
23925    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23926        @Override
23927        public void setValue(View object, float value) {
23928            object.setX(value);
23929        }
23930
23931        @Override
23932        public Float get(View object) {
23933            return object.getX();
23934        }
23935    };
23936
23937    /**
23938     * A Property wrapper around the <code>y</code> functionality handled by the
23939     * {@link View#setY(float)} and {@link View#getY()} methods.
23940     */
23941    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23942        @Override
23943        public void setValue(View object, float value) {
23944            object.setY(value);
23945        }
23946
23947        @Override
23948        public Float get(View object) {
23949            return object.getY();
23950        }
23951    };
23952
23953    /**
23954     * A Property wrapper around the <code>z</code> functionality handled by the
23955     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23956     */
23957    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23958        @Override
23959        public void setValue(View object, float value) {
23960            object.setZ(value);
23961        }
23962
23963        @Override
23964        public Float get(View object) {
23965            return object.getZ();
23966        }
23967    };
23968
23969    /**
23970     * A Property wrapper around the <code>rotation</code> functionality handled by the
23971     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23972     */
23973    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23974        @Override
23975        public void setValue(View object, float value) {
23976            object.setRotation(value);
23977        }
23978
23979        @Override
23980        public Float get(View object) {
23981            return object.getRotation();
23982        }
23983    };
23984
23985    /**
23986     * A Property wrapper around the <code>rotationX</code> functionality handled by the
23987     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
23988     */
23989    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
23990        @Override
23991        public void setValue(View object, float value) {
23992            object.setRotationX(value);
23993        }
23994
23995        @Override
23996        public Float get(View object) {
23997            return object.getRotationX();
23998        }
23999    };
24000
24001    /**
24002     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24003     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24004     */
24005    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24006        @Override
24007        public void setValue(View object, float value) {
24008            object.setRotationY(value);
24009        }
24010
24011        @Override
24012        public Float get(View object) {
24013            return object.getRotationY();
24014        }
24015    };
24016
24017    /**
24018     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24019     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24020     */
24021    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24022        @Override
24023        public void setValue(View object, float value) {
24024            object.setScaleX(value);
24025        }
24026
24027        @Override
24028        public Float get(View object) {
24029            return object.getScaleX();
24030        }
24031    };
24032
24033    /**
24034     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24035     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24036     */
24037    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24038        @Override
24039        public void setValue(View object, float value) {
24040            object.setScaleY(value);
24041        }
24042
24043        @Override
24044        public Float get(View object) {
24045            return object.getScaleY();
24046        }
24047    };
24048
24049    /**
24050     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24051     * Each MeasureSpec represents a requirement for either the width or the height.
24052     * A MeasureSpec is comprised of a size and a mode. There are three possible
24053     * modes:
24054     * <dl>
24055     * <dt>UNSPECIFIED</dt>
24056     * <dd>
24057     * The parent has not imposed any constraint on the child. It can be whatever size
24058     * it wants.
24059     * </dd>
24060     *
24061     * <dt>EXACTLY</dt>
24062     * <dd>
24063     * The parent has determined an exact size for the child. The child is going to be
24064     * given those bounds regardless of how big it wants to be.
24065     * </dd>
24066     *
24067     * <dt>AT_MOST</dt>
24068     * <dd>
24069     * The child can be as large as it wants up to the specified size.
24070     * </dd>
24071     * </dl>
24072     *
24073     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24074     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24075     */
24076    public static class MeasureSpec {
24077        private static final int MODE_SHIFT = 30;
24078        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24079
24080        /** @hide */
24081        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24082        @Retention(RetentionPolicy.SOURCE)
24083        public @interface MeasureSpecMode {}
24084
24085        /**
24086         * Measure specification mode: The parent has not imposed any constraint
24087         * on the child. It can be whatever size it wants.
24088         */
24089        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24090
24091        /**
24092         * Measure specification mode: The parent has determined an exact size
24093         * for the child. The child is going to be given those bounds regardless
24094         * of how big it wants to be.
24095         */
24096        public static final int EXACTLY     = 1 << MODE_SHIFT;
24097
24098        /**
24099         * Measure specification mode: The child can be as large as it wants up
24100         * to the specified size.
24101         */
24102        public static final int AT_MOST     = 2 << MODE_SHIFT;
24103
24104        /**
24105         * Creates a measure specification based on the supplied size and mode.
24106         *
24107         * The mode must always be one of the following:
24108         * <ul>
24109         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24110         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24111         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24112         * </ul>
24113         *
24114         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24115         * implementation was such that the order of arguments did not matter
24116         * and overflow in either value could impact the resulting MeasureSpec.
24117         * {@link android.widget.RelativeLayout} was affected by this bug.
24118         * Apps targeting API levels greater than 17 will get the fixed, more strict
24119         * behavior.</p>
24120         *
24121         * @param size the size of the measure specification
24122         * @param mode the mode of the measure specification
24123         * @return the measure specification based on size and mode
24124         */
24125        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24126                                          @MeasureSpecMode int mode) {
24127            if (sUseBrokenMakeMeasureSpec) {
24128                return size + mode;
24129            } else {
24130                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24131            }
24132        }
24133
24134        /**
24135         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24136         * will automatically get a size of 0. Older apps expect this.
24137         *
24138         * @hide internal use only for compatibility with system widgets and older apps
24139         */
24140        public static int makeSafeMeasureSpec(int size, int mode) {
24141            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24142                return 0;
24143            }
24144            return makeMeasureSpec(size, mode);
24145        }
24146
24147        /**
24148         * Extracts the mode from the supplied measure specification.
24149         *
24150         * @param measureSpec the measure specification to extract the mode from
24151         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24152         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24153         *         {@link android.view.View.MeasureSpec#EXACTLY}
24154         */
24155        @MeasureSpecMode
24156        public static int getMode(int measureSpec) {
24157            //noinspection ResourceType
24158            return (measureSpec & MODE_MASK);
24159        }
24160
24161        /**
24162         * Extracts the size from the supplied measure specification.
24163         *
24164         * @param measureSpec the measure specification to extract the size from
24165         * @return the size in pixels defined in the supplied measure specification
24166         */
24167        public static int getSize(int measureSpec) {
24168            return (measureSpec & ~MODE_MASK);
24169        }
24170
24171        static int adjust(int measureSpec, int delta) {
24172            final int mode = getMode(measureSpec);
24173            int size = getSize(measureSpec);
24174            if (mode == UNSPECIFIED) {
24175                // No need to adjust size for UNSPECIFIED mode.
24176                return makeMeasureSpec(size, UNSPECIFIED);
24177            }
24178            size += delta;
24179            if (size < 0) {
24180                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24181                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24182                size = 0;
24183            }
24184            return makeMeasureSpec(size, mode);
24185        }
24186
24187        /**
24188         * Returns a String representation of the specified measure
24189         * specification.
24190         *
24191         * @param measureSpec the measure specification to convert to a String
24192         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24193         */
24194        public static String toString(int measureSpec) {
24195            int mode = getMode(measureSpec);
24196            int size = getSize(measureSpec);
24197
24198            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24199
24200            if (mode == UNSPECIFIED)
24201                sb.append("UNSPECIFIED ");
24202            else if (mode == EXACTLY)
24203                sb.append("EXACTLY ");
24204            else if (mode == AT_MOST)
24205                sb.append("AT_MOST ");
24206            else
24207                sb.append(mode).append(" ");
24208
24209            sb.append(size);
24210            return sb.toString();
24211        }
24212    }
24213
24214    private final class CheckForLongPress implements Runnable {
24215        private int mOriginalWindowAttachCount;
24216        private float mX;
24217        private float mY;
24218        private boolean mOriginalPressedState;
24219
24220        @Override
24221        public void run() {
24222            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24223                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24224                if (performLongClick(mX, mY)) {
24225                    mHasPerformedLongPress = true;
24226                }
24227            }
24228        }
24229
24230        public void setAnchor(float x, float y) {
24231            mX = x;
24232            mY = y;
24233        }
24234
24235        public void rememberWindowAttachCount() {
24236            mOriginalWindowAttachCount = mWindowAttachCount;
24237        }
24238
24239        public void rememberPressedState() {
24240            mOriginalPressedState = isPressed();
24241        }
24242    }
24243
24244    private final class CheckForTap implements Runnable {
24245        public float x;
24246        public float y;
24247
24248        @Override
24249        public void run() {
24250            mPrivateFlags &= ~PFLAG_PREPRESSED;
24251            setPressed(true, x, y);
24252            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24253        }
24254    }
24255
24256    private final class PerformClick implements Runnable {
24257        @Override
24258        public void run() {
24259            performClick();
24260        }
24261    }
24262
24263    /**
24264     * This method returns a ViewPropertyAnimator object, which can be used to animate
24265     * specific properties on this View.
24266     *
24267     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24268     */
24269    public ViewPropertyAnimator animate() {
24270        if (mAnimator == null) {
24271            mAnimator = new ViewPropertyAnimator(this);
24272        }
24273        return mAnimator;
24274    }
24275
24276    /**
24277     * Sets the name of the View to be used to identify Views in Transitions.
24278     * Names should be unique in the View hierarchy.
24279     *
24280     * @param transitionName The name of the View to uniquely identify it for Transitions.
24281     */
24282    public final void setTransitionName(String transitionName) {
24283        mTransitionName = transitionName;
24284    }
24285
24286    /**
24287     * Returns the name of the View to be used to identify Views in Transitions.
24288     * Names should be unique in the View hierarchy.
24289     *
24290     * <p>This returns null if the View has not been given a name.</p>
24291     *
24292     * @return The name used of the View to be used to identify Views in Transitions or null
24293     * if no name has been given.
24294     */
24295    @ViewDebug.ExportedProperty
24296    public String getTransitionName() {
24297        return mTransitionName;
24298    }
24299
24300    /**
24301     * @hide
24302     */
24303    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24304        // Do nothing.
24305    }
24306
24307    /**
24308     * Interface definition for a callback to be invoked when a hardware key event is
24309     * dispatched to this view. The callback will be invoked before the key event is
24310     * given to the view. This is only useful for hardware keyboards; a software input
24311     * method has no obligation to trigger this listener.
24312     */
24313    public interface OnKeyListener {
24314        /**
24315         * Called when a hardware key is dispatched to a view. This allows listeners to
24316         * get a chance to respond before the target view.
24317         * <p>Key presses in software keyboards will generally NOT trigger this method,
24318         * although some may elect to do so in some situations. Do not assume a
24319         * software input method has to be key-based; even if it is, it may use key presses
24320         * in a different way than you expect, so there is no way to reliably catch soft
24321         * input key presses.
24322         *
24323         * @param v The view the key has been dispatched to.
24324         * @param keyCode The code for the physical key that was pressed
24325         * @param event The KeyEvent object containing full information about
24326         *        the event.
24327         * @return True if the listener has consumed the event, false otherwise.
24328         */
24329        boolean onKey(View v, int keyCode, KeyEvent event);
24330    }
24331
24332    /**
24333     * Interface definition for a callback to be invoked when a touch event is
24334     * dispatched to this view. The callback will be invoked before the touch
24335     * event is given to the view.
24336     */
24337    public interface OnTouchListener {
24338        /**
24339         * Called when a touch event is dispatched to a view. This allows listeners to
24340         * get a chance to respond before the target view.
24341         *
24342         * @param v The view the touch event has been dispatched to.
24343         * @param event The MotionEvent object containing full information about
24344         *        the event.
24345         * @return True if the listener has consumed the event, false otherwise.
24346         */
24347        boolean onTouch(View v, MotionEvent event);
24348    }
24349
24350    /**
24351     * Interface definition for a callback to be invoked when a hover event is
24352     * dispatched to this view. The callback will be invoked before the hover
24353     * event is given to the view.
24354     */
24355    public interface OnHoverListener {
24356        /**
24357         * Called when a hover event is dispatched to a view. This allows listeners to
24358         * get a chance to respond before the target view.
24359         *
24360         * @param v The view the hover event has been dispatched to.
24361         * @param event The MotionEvent object containing full information about
24362         *        the event.
24363         * @return True if the listener has consumed the event, false otherwise.
24364         */
24365        boolean onHover(View v, MotionEvent event);
24366    }
24367
24368    /**
24369     * Interface definition for a callback to be invoked when a generic motion event is
24370     * dispatched to this view. The callback will be invoked before the generic motion
24371     * event is given to the view.
24372     */
24373    public interface OnGenericMotionListener {
24374        /**
24375         * Called when a generic motion event is dispatched to a view. This allows listeners to
24376         * get a chance to respond before the target view.
24377         *
24378         * @param v The view the generic motion event has been dispatched to.
24379         * @param event The MotionEvent object containing full information about
24380         *        the event.
24381         * @return True if the listener has consumed the event, false otherwise.
24382         */
24383        boolean onGenericMotion(View v, MotionEvent event);
24384    }
24385
24386    /**
24387     * Interface definition for a callback to be invoked when a view has been clicked and held.
24388     */
24389    public interface OnLongClickListener {
24390        /**
24391         * Called when a view has been clicked and held.
24392         *
24393         * @param v The view that was clicked and held.
24394         *
24395         * @return true if the callback consumed the long click, false otherwise.
24396         */
24397        boolean onLongClick(View v);
24398    }
24399
24400    /**
24401     * Interface definition for a callback to be invoked when a drag is being dispatched
24402     * to this view.  The callback will be invoked before the hosting view's own
24403     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24404     * onDrag(event) behavior, it should return 'false' from this callback.
24405     *
24406     * <div class="special reference">
24407     * <h3>Developer Guides</h3>
24408     * <p>For a guide to implementing drag and drop features, read the
24409     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24410     * </div>
24411     */
24412    public interface OnDragListener {
24413        /**
24414         * Called when a drag event is dispatched to a view. This allows listeners
24415         * to get a chance to override base View behavior.
24416         *
24417         * @param v The View that received the drag event.
24418         * @param event The {@link android.view.DragEvent} object for the drag event.
24419         * @return {@code true} if the drag event was handled successfully, or {@code false}
24420         * if the drag event was not handled. Note that {@code false} will trigger the View
24421         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24422         */
24423        boolean onDrag(View v, DragEvent event);
24424    }
24425
24426    /**
24427     * Interface definition for a callback to be invoked when the focus state of
24428     * a view changed.
24429     */
24430    public interface OnFocusChangeListener {
24431        /**
24432         * Called when the focus state of a view has changed.
24433         *
24434         * @param v The view whose state has changed.
24435         * @param hasFocus The new focus state of v.
24436         */
24437        void onFocusChange(View v, boolean hasFocus);
24438    }
24439
24440    /**
24441     * Interface definition for a callback to be invoked when a view is clicked.
24442     */
24443    public interface OnClickListener {
24444        /**
24445         * Called when a view has been clicked.
24446         *
24447         * @param v The view that was clicked.
24448         */
24449        void onClick(View v);
24450    }
24451
24452    /**
24453     * Interface definition for a callback to be invoked when a view is context clicked.
24454     */
24455    public interface OnContextClickListener {
24456        /**
24457         * Called when a view is context clicked.
24458         *
24459         * @param v The view that has been context clicked.
24460         * @return true if the callback consumed the context click, false otherwise.
24461         */
24462        boolean onContextClick(View v);
24463    }
24464
24465    /**
24466     * Interface definition for a callback to be invoked when the context menu
24467     * for this view is being built.
24468     */
24469    public interface OnCreateContextMenuListener {
24470        /**
24471         * Called when the context menu for this view is being built. It is not
24472         * safe to hold onto the menu after this method returns.
24473         *
24474         * @param menu The context menu that is being built
24475         * @param v The view for which the context menu is being built
24476         * @param menuInfo Extra information about the item for which the
24477         *            context menu should be shown. This information will vary
24478         *            depending on the class of v.
24479         */
24480        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24481    }
24482
24483    /**
24484     * Interface definition for a callback to be invoked when the status bar changes
24485     * visibility.  This reports <strong>global</strong> changes to the system UI
24486     * state, not what the application is requesting.
24487     *
24488     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24489     */
24490    public interface OnSystemUiVisibilityChangeListener {
24491        /**
24492         * Called when the status bar changes visibility because of a call to
24493         * {@link View#setSystemUiVisibility(int)}.
24494         *
24495         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24496         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24497         * This tells you the <strong>global</strong> state of these UI visibility
24498         * flags, not what your app is currently applying.
24499         */
24500        public void onSystemUiVisibilityChange(int visibility);
24501    }
24502
24503    /**
24504     * Interface definition for a callback to be invoked when this view is attached
24505     * or detached from its window.
24506     */
24507    public interface OnAttachStateChangeListener {
24508        /**
24509         * Called when the view is attached to a window.
24510         * @param v The view that was attached
24511         */
24512        public void onViewAttachedToWindow(View v);
24513        /**
24514         * Called when the view is detached from a window.
24515         * @param v The view that was detached
24516         */
24517        public void onViewDetachedFromWindow(View v);
24518    }
24519
24520    /**
24521     * Listener for applying window insets on a view in a custom way.
24522     *
24523     * <p>Apps may choose to implement this interface if they want to apply custom policy
24524     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24525     * is set, its
24526     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24527     * method will be called instead of the View's own
24528     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24529     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24530     * the View's normal behavior as part of its own.</p>
24531     */
24532    public interface OnApplyWindowInsetsListener {
24533        /**
24534         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24535         * on a View, this listener method will be called instead of the view's own
24536         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24537         *
24538         * @param v The view applying window insets
24539         * @param insets The insets to apply
24540         * @return The insets supplied, minus any insets that were consumed
24541         */
24542        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24543    }
24544
24545    private final class UnsetPressedState implements Runnable {
24546        @Override
24547        public void run() {
24548            setPressed(false);
24549        }
24550    }
24551
24552    /**
24553     * When a view becomes invisible checks if autofill considers the view invisible too. This
24554     * happens after the regular removal operation to make sure the operation is finished by the
24555     * time this is called.
24556     */
24557    private static class VisibilityChangeForAutofillHandler extends Handler {
24558        private final AutofillManager mAfm;
24559        private final View mView;
24560
24561        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
24562                @NonNull View view) {
24563            mAfm = afm;
24564            mView = view;
24565        }
24566
24567        @Override
24568        public void handleMessage(Message msg) {
24569            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
24570        }
24571    }
24572
24573    /**
24574     * Base class for derived classes that want to save and restore their own
24575     * state in {@link android.view.View#onSaveInstanceState()}.
24576     */
24577    public static class BaseSavedState extends AbsSavedState {
24578        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24579        static final int IS_AUTOFILLED = 0b10;
24580        static final int ACCESSIBILITY_ID = 0b100;
24581
24582        // Flags that describe what data in this state is valid
24583        int mSavedData;
24584        String mStartActivityRequestWhoSaved;
24585        boolean mIsAutofilled;
24586        int mAccessibilityViewId;
24587
24588        /**
24589         * Constructor used when reading from a parcel. Reads the state of the superclass.
24590         *
24591         * @param source parcel to read from
24592         */
24593        public BaseSavedState(Parcel source) {
24594            this(source, null);
24595        }
24596
24597        /**
24598         * Constructor used when reading from a parcel using a given class loader.
24599         * Reads the state of the superclass.
24600         *
24601         * @param source parcel to read from
24602         * @param loader ClassLoader to use for reading
24603         */
24604        public BaseSavedState(Parcel source, ClassLoader loader) {
24605            super(source, loader);
24606            mSavedData = source.readInt();
24607            mStartActivityRequestWhoSaved = source.readString();
24608            mIsAutofilled = source.readBoolean();
24609            mAccessibilityViewId = source.readInt();
24610        }
24611
24612        /**
24613         * Constructor called by derived classes when creating their SavedState objects
24614         *
24615         * @param superState The state of the superclass of this view
24616         */
24617        public BaseSavedState(Parcelable superState) {
24618            super(superState);
24619        }
24620
24621        @Override
24622        public void writeToParcel(Parcel out, int flags) {
24623            super.writeToParcel(out, flags);
24624
24625            out.writeInt(mSavedData);
24626            out.writeString(mStartActivityRequestWhoSaved);
24627            out.writeBoolean(mIsAutofilled);
24628            out.writeInt(mAccessibilityViewId);
24629        }
24630
24631        public static final Parcelable.Creator<BaseSavedState> CREATOR
24632                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24633            @Override
24634            public BaseSavedState createFromParcel(Parcel in) {
24635                return new BaseSavedState(in);
24636            }
24637
24638            @Override
24639            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24640                return new BaseSavedState(in, loader);
24641            }
24642
24643            @Override
24644            public BaseSavedState[] newArray(int size) {
24645                return new BaseSavedState[size];
24646            }
24647        };
24648    }
24649
24650    /**
24651     * A set of information given to a view when it is attached to its parent
24652     * window.
24653     */
24654    final static class AttachInfo {
24655        interface Callbacks {
24656            void playSoundEffect(int effectId);
24657            boolean performHapticFeedback(int effectId, boolean always);
24658        }
24659
24660        /**
24661         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24662         * to a Handler. This class contains the target (View) to invalidate and
24663         * the coordinates of the dirty rectangle.
24664         *
24665         * For performance purposes, this class also implements a pool of up to
24666         * POOL_LIMIT objects that get reused. This reduces memory allocations
24667         * whenever possible.
24668         */
24669        static class InvalidateInfo {
24670            private static final int POOL_LIMIT = 10;
24671
24672            private static final SynchronizedPool<InvalidateInfo> sPool =
24673                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24674
24675            View target;
24676
24677            int left;
24678            int top;
24679            int right;
24680            int bottom;
24681
24682            public static InvalidateInfo obtain() {
24683                InvalidateInfo instance = sPool.acquire();
24684                return (instance != null) ? instance : new InvalidateInfo();
24685            }
24686
24687            public void recycle() {
24688                target = null;
24689                sPool.release(this);
24690            }
24691        }
24692
24693        final IWindowSession mSession;
24694
24695        final IWindow mWindow;
24696
24697        final IBinder mWindowToken;
24698
24699        Display mDisplay;
24700
24701        final Callbacks mRootCallbacks;
24702
24703        IWindowId mIWindowId;
24704        WindowId mWindowId;
24705
24706        /**
24707         * The top view of the hierarchy.
24708         */
24709        View mRootView;
24710
24711        IBinder mPanelParentWindowToken;
24712
24713        boolean mHardwareAccelerated;
24714        boolean mHardwareAccelerationRequested;
24715        ThreadedRenderer mThreadedRenderer;
24716        List<RenderNode> mPendingAnimatingRenderNodes;
24717
24718        /**
24719         * The state of the display to which the window is attached, as reported
24720         * by {@link Display#getState()}.  Note that the display state constants
24721         * declared by {@link Display} do not exactly line up with the screen state
24722         * constants declared by {@link View} (there are more display states than
24723         * screen states).
24724         */
24725        int mDisplayState = Display.STATE_UNKNOWN;
24726
24727        /**
24728         * Scale factor used by the compatibility mode
24729         */
24730        float mApplicationScale;
24731
24732        /**
24733         * Indicates whether the application is in compatibility mode
24734         */
24735        boolean mScalingRequired;
24736
24737        /**
24738         * Left position of this view's window
24739         */
24740        int mWindowLeft;
24741
24742        /**
24743         * Top position of this view's window
24744         */
24745        int mWindowTop;
24746
24747        /**
24748         * Indicates whether views need to use 32-bit drawing caches
24749         */
24750        boolean mUse32BitDrawingCache;
24751
24752        /**
24753         * For windows that are full-screen but using insets to layout inside
24754         * of the screen areas, these are the current insets to appear inside
24755         * the overscan area of the display.
24756         */
24757        final Rect mOverscanInsets = new Rect();
24758
24759        /**
24760         * For windows that are full-screen but using insets to layout inside
24761         * of the screen decorations, these are the current insets for the
24762         * content of the window.
24763         */
24764        final Rect mContentInsets = new Rect();
24765
24766        /**
24767         * For windows that are full-screen but using insets to layout inside
24768         * of the screen decorations, these are the current insets for the
24769         * actual visible parts of the window.
24770         */
24771        final Rect mVisibleInsets = new Rect();
24772
24773        /**
24774         * For windows that are full-screen but using insets to layout inside
24775         * of the screen decorations, these are the current insets for the
24776         * stable system windows.
24777         */
24778        final Rect mStableInsets = new Rect();
24779
24780        /**
24781         * For windows that include areas that are not covered by real surface these are the outsets
24782         * for real surface.
24783         */
24784        final Rect mOutsets = new Rect();
24785
24786        /**
24787         * In multi-window we force show the navigation bar. Because we don't want that the surface
24788         * size changes in this mode, we instead have a flag whether the navigation bar size should
24789         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24790         */
24791        boolean mAlwaysConsumeNavBar;
24792
24793        /**
24794         * The internal insets given by this window.  This value is
24795         * supplied by the client (through
24796         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24797         * be given to the window manager when changed to be used in laying
24798         * out windows behind it.
24799         */
24800        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24801                = new ViewTreeObserver.InternalInsetsInfo();
24802
24803        /**
24804         * Set to true when mGivenInternalInsets is non-empty.
24805         */
24806        boolean mHasNonEmptyGivenInternalInsets;
24807
24808        /**
24809         * All views in the window's hierarchy that serve as scroll containers,
24810         * used to determine if the window can be resized or must be panned
24811         * to adjust for a soft input area.
24812         */
24813        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24814
24815        final KeyEvent.DispatcherState mKeyDispatchState
24816                = new KeyEvent.DispatcherState();
24817
24818        /**
24819         * Indicates whether the view's window currently has the focus.
24820         */
24821        boolean mHasWindowFocus;
24822
24823        /**
24824         * The current visibility of the window.
24825         */
24826        int mWindowVisibility;
24827
24828        /**
24829         * Indicates the time at which drawing started to occur.
24830         */
24831        long mDrawingTime;
24832
24833        /**
24834         * Indicates whether or not ignoring the DIRTY_MASK flags.
24835         */
24836        boolean mIgnoreDirtyState;
24837
24838        /**
24839         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24840         * to avoid clearing that flag prematurely.
24841         */
24842        boolean mSetIgnoreDirtyState = false;
24843
24844        /**
24845         * Indicates whether the view's window is currently in touch mode.
24846         */
24847        boolean mInTouchMode;
24848
24849        /**
24850         * Indicates whether the view has requested unbuffered input dispatching for the current
24851         * event stream.
24852         */
24853        boolean mUnbufferedDispatchRequested;
24854
24855        /**
24856         * Indicates that ViewAncestor should trigger a global layout change
24857         * the next time it performs a traversal
24858         */
24859        boolean mRecomputeGlobalAttributes;
24860
24861        /**
24862         * Always report new attributes at next traversal.
24863         */
24864        boolean mForceReportNewAttributes;
24865
24866        /**
24867         * Set during a traveral if any views want to keep the screen on.
24868         */
24869        boolean mKeepScreenOn;
24870
24871        /**
24872         * Set during a traveral if the light center needs to be updated.
24873         */
24874        boolean mNeedsUpdateLightCenter;
24875
24876        /**
24877         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24878         */
24879        int mSystemUiVisibility;
24880
24881        /**
24882         * Hack to force certain system UI visibility flags to be cleared.
24883         */
24884        int mDisabledSystemUiVisibility;
24885
24886        /**
24887         * Last global system UI visibility reported by the window manager.
24888         */
24889        int mGlobalSystemUiVisibility = -1;
24890
24891        /**
24892         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24893         * attached.
24894         */
24895        boolean mHasSystemUiListeners;
24896
24897        /**
24898         * Set if the window has requested to extend into the overscan region
24899         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24900         */
24901        boolean mOverscanRequested;
24902
24903        /**
24904         * Set if the visibility of any views has changed.
24905         */
24906        boolean mViewVisibilityChanged;
24907
24908        /**
24909         * Set to true if a view has been scrolled.
24910         */
24911        boolean mViewScrollChanged;
24912
24913        /**
24914         * Set to true if high contrast mode enabled
24915         */
24916        boolean mHighContrastText;
24917
24918        /**
24919         * Set to true if a pointer event is currently being handled.
24920         */
24921        boolean mHandlingPointerEvent;
24922
24923        /**
24924         * Global to the view hierarchy used as a temporary for dealing with
24925         * x/y points in the transparent region computations.
24926         */
24927        final int[] mTransparentLocation = new int[2];
24928
24929        /**
24930         * Global to the view hierarchy used as a temporary for dealing with
24931         * x/y points in the ViewGroup.invalidateChild implementation.
24932         */
24933        final int[] mInvalidateChildLocation = new int[2];
24934
24935        /**
24936         * Global to the view hierarchy used as a temporary for dealing with
24937         * computing absolute on-screen location.
24938         */
24939        final int[] mTmpLocation = new int[2];
24940
24941        /**
24942         * Global to the view hierarchy used as a temporary for dealing with
24943         * x/y location when view is transformed.
24944         */
24945        final float[] mTmpTransformLocation = new float[2];
24946
24947        /**
24948         * The view tree observer used to dispatch global events like
24949         * layout, pre-draw, touch mode change, etc.
24950         */
24951        final ViewTreeObserver mTreeObserver;
24952
24953        /**
24954         * A Canvas used by the view hierarchy to perform bitmap caching.
24955         */
24956        Canvas mCanvas;
24957
24958        /**
24959         * The view root impl.
24960         */
24961        final ViewRootImpl mViewRootImpl;
24962
24963        /**
24964         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24965         * handler can be used to pump events in the UI events queue.
24966         */
24967        final Handler mHandler;
24968
24969        /**
24970         * Temporary for use in computing invalidate rectangles while
24971         * calling up the hierarchy.
24972         */
24973        final Rect mTmpInvalRect = new Rect();
24974
24975        /**
24976         * Temporary for use in computing hit areas with transformed views
24977         */
24978        final RectF mTmpTransformRect = new RectF();
24979
24980        /**
24981         * Temporary for use in computing hit areas with transformed views
24982         */
24983        final RectF mTmpTransformRect1 = new RectF();
24984
24985        /**
24986         * Temporary list of rectanges.
24987         */
24988        final List<RectF> mTmpRectList = new ArrayList<>();
24989
24990        /**
24991         * Temporary for use in transforming invalidation rect
24992         */
24993        final Matrix mTmpMatrix = new Matrix();
24994
24995        /**
24996         * Temporary for use in transforming invalidation rect
24997         */
24998        final Transformation mTmpTransformation = new Transformation();
24999
25000        /**
25001         * Temporary for use in querying outlines from OutlineProviders
25002         */
25003        final Outline mTmpOutline = new Outline();
25004
25005        /**
25006         * Temporary list for use in collecting focusable descendents of a view.
25007         */
25008        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25009
25010        /**
25011         * The id of the window for accessibility purposes.
25012         */
25013        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25014
25015        /**
25016         * Flags related to accessibility processing.
25017         *
25018         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25019         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25020         */
25021        int mAccessibilityFetchFlags;
25022
25023        /**
25024         * The drawable for highlighting accessibility focus.
25025         */
25026        Drawable mAccessibilityFocusDrawable;
25027
25028        /**
25029         * The drawable for highlighting autofilled views.
25030         *
25031         * @see #isAutofilled()
25032         */
25033        Drawable mAutofilledDrawable;
25034
25035        /**
25036         * Show where the margins, bounds and layout bounds are for each view.
25037         */
25038        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25039
25040        /**
25041         * Point used to compute visible regions.
25042         */
25043        final Point mPoint = new Point();
25044
25045        /**
25046         * Used to track which View originated a requestLayout() call, used when
25047         * requestLayout() is called during layout.
25048         */
25049        View mViewRequestingLayout;
25050
25051        /**
25052         * Used to track views that need (at least) a partial relayout at their current size
25053         * during the next traversal.
25054         */
25055        List<View> mPartialLayoutViews = new ArrayList<>();
25056
25057        /**
25058         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25059         * modification. Lazily assigned during ViewRootImpl layout.
25060         */
25061        List<View> mEmptyPartialLayoutViews;
25062
25063        /**
25064         * Used to track the identity of the current drag operation.
25065         */
25066        IBinder mDragToken;
25067
25068        /**
25069         * The drag shadow surface for the current drag operation.
25070         */
25071        public Surface mDragSurface;
25072
25073
25074        /**
25075         * The view that currently has a tooltip displayed.
25076         */
25077        View mTooltipHost;
25078
25079        /**
25080         * Creates a new set of attachment information with the specified
25081         * events handler and thread.
25082         *
25083         * @param handler the events handler the view must use
25084         */
25085        AttachInfo(IWindowSession session, IWindow window, Display display,
25086                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25087                Context context) {
25088            mSession = session;
25089            mWindow = window;
25090            mWindowToken = window.asBinder();
25091            mDisplay = display;
25092            mViewRootImpl = viewRootImpl;
25093            mHandler = handler;
25094            mRootCallbacks = effectPlayer;
25095            mTreeObserver = new ViewTreeObserver(context);
25096        }
25097    }
25098
25099    /**
25100     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25101     * is supported. This avoids keeping too many unused fields in most
25102     * instances of View.</p>
25103     */
25104    private static class ScrollabilityCache implements Runnable {
25105
25106        /**
25107         * Scrollbars are not visible
25108         */
25109        public static final int OFF = 0;
25110
25111        /**
25112         * Scrollbars are visible
25113         */
25114        public static final int ON = 1;
25115
25116        /**
25117         * Scrollbars are fading away
25118         */
25119        public static final int FADING = 2;
25120
25121        public boolean fadeScrollBars;
25122
25123        public int fadingEdgeLength;
25124        public int scrollBarDefaultDelayBeforeFade;
25125        public int scrollBarFadeDuration;
25126
25127        public int scrollBarSize;
25128        public int scrollBarMinTouchTarget;
25129        public ScrollBarDrawable scrollBar;
25130        public float[] interpolatorValues;
25131        public View host;
25132
25133        public final Paint paint;
25134        public final Matrix matrix;
25135        public Shader shader;
25136
25137        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25138
25139        private static final float[] OPAQUE = { 255 };
25140        private static final float[] TRANSPARENT = { 0.0f };
25141
25142        /**
25143         * When fading should start. This time moves into the future every time
25144         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25145         */
25146        public long fadeStartTime;
25147
25148
25149        /**
25150         * The current state of the scrollbars: ON, OFF, or FADING
25151         */
25152        public int state = OFF;
25153
25154        private int mLastColor;
25155
25156        public final Rect mScrollBarBounds = new Rect();
25157        public final Rect mScrollBarTouchBounds = new Rect();
25158
25159        public static final int NOT_DRAGGING = 0;
25160        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25161        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25162        public int mScrollBarDraggingState = NOT_DRAGGING;
25163
25164        public float mScrollBarDraggingPos = 0;
25165
25166        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25167            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25168            scrollBarSize = configuration.getScaledScrollBarSize();
25169            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25170            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25171            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25172
25173            paint = new Paint();
25174            matrix = new Matrix();
25175            // use use a height of 1, and then wack the matrix each time we
25176            // actually use it.
25177            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25178            paint.setShader(shader);
25179            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25180
25181            this.host = host;
25182        }
25183
25184        public void setFadeColor(int color) {
25185            if (color != mLastColor) {
25186                mLastColor = color;
25187
25188                if (color != 0) {
25189                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25190                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25191                    paint.setShader(shader);
25192                    // Restore the default transfer mode (src_over)
25193                    paint.setXfermode(null);
25194                } else {
25195                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25196                    paint.setShader(shader);
25197                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25198                }
25199            }
25200        }
25201
25202        public void run() {
25203            long now = AnimationUtils.currentAnimationTimeMillis();
25204            if (now >= fadeStartTime) {
25205
25206                // the animation fades the scrollbars out by changing
25207                // the opacity (alpha) from fully opaque to fully
25208                // transparent
25209                int nextFrame = (int) now;
25210                int framesCount = 0;
25211
25212                Interpolator interpolator = scrollBarInterpolator;
25213
25214                // Start opaque
25215                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25216
25217                // End transparent
25218                nextFrame += scrollBarFadeDuration;
25219                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25220
25221                state = FADING;
25222
25223                // Kick off the fade animation
25224                host.invalidate(true);
25225            }
25226        }
25227    }
25228
25229    /**
25230     * Resuable callback for sending
25231     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25232     */
25233    private class SendViewScrolledAccessibilityEvent implements Runnable {
25234        public volatile boolean mIsPending;
25235
25236        public void run() {
25237            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25238            mIsPending = false;
25239        }
25240    }
25241
25242    /**
25243     * <p>
25244     * This class represents a delegate that can be registered in a {@link View}
25245     * to enhance accessibility support via composition rather via inheritance.
25246     * It is specifically targeted to widget developers that extend basic View
25247     * classes i.e. classes in package android.view, that would like their
25248     * applications to be backwards compatible.
25249     * </p>
25250     * <div class="special reference">
25251     * <h3>Developer Guides</h3>
25252     * <p>For more information about making applications accessible, read the
25253     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25254     * developer guide.</p>
25255     * </div>
25256     * <p>
25257     * A scenario in which a developer would like to use an accessibility delegate
25258     * is overriding a method introduced in a later API version than the minimal API
25259     * version supported by the application. For example, the method
25260     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25261     * in API version 4 when the accessibility APIs were first introduced. If a
25262     * developer would like his application to run on API version 4 devices (assuming
25263     * all other APIs used by the application are version 4 or lower) and take advantage
25264     * of this method, instead of overriding the method which would break the application's
25265     * backwards compatibility, he can override the corresponding method in this
25266     * delegate and register the delegate in the target View if the API version of
25267     * the system is high enough, i.e. the API version is the same as or higher than the API
25268     * version that introduced
25269     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25270     * </p>
25271     * <p>
25272     * Here is an example implementation:
25273     * </p>
25274     * <code><pre><p>
25275     * if (Build.VERSION.SDK_INT >= 14) {
25276     *     // If the API version is equal of higher than the version in
25277     *     // which onInitializeAccessibilityNodeInfo was introduced we
25278     *     // register a delegate with a customized implementation.
25279     *     View view = findViewById(R.id.view_id);
25280     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25281     *         public void onInitializeAccessibilityNodeInfo(View host,
25282     *                 AccessibilityNodeInfo info) {
25283     *             // Let the default implementation populate the info.
25284     *             super.onInitializeAccessibilityNodeInfo(host, info);
25285     *             // Set some other information.
25286     *             info.setEnabled(host.isEnabled());
25287     *         }
25288     *     });
25289     * }
25290     * </code></pre></p>
25291     * <p>
25292     * This delegate contains methods that correspond to the accessibility methods
25293     * in View. If a delegate has been specified the implementation in View hands
25294     * off handling to the corresponding method in this delegate. The default
25295     * implementation the delegate methods behaves exactly as the corresponding
25296     * method in View for the case of no accessibility delegate been set. Hence,
25297     * to customize the behavior of a View method, clients can override only the
25298     * corresponding delegate method without altering the behavior of the rest
25299     * accessibility related methods of the host view.
25300     * </p>
25301     * <p>
25302     * <strong>Note:</strong> On platform versions prior to
25303     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25304     * views in the {@code android.widget.*} package are called <i>before</i>
25305     * host methods. This prevents certain properties such as class name from
25306     * being modified by overriding
25307     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25308     * as any changes will be overwritten by the host class.
25309     * <p>
25310     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25311     * methods are called <i>after</i> host methods, which all properties to be
25312     * modified without being overwritten by the host class.
25313     */
25314    public static class AccessibilityDelegate {
25315
25316        /**
25317         * Sends an accessibility event of the given type. If accessibility is not
25318         * enabled this method has no effect.
25319         * <p>
25320         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25321         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25322         * been set.
25323         * </p>
25324         *
25325         * @param host The View hosting the delegate.
25326         * @param eventType The type of the event to send.
25327         *
25328         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25329         */
25330        public void sendAccessibilityEvent(View host, int eventType) {
25331            host.sendAccessibilityEventInternal(eventType);
25332        }
25333
25334        /**
25335         * Performs the specified accessibility action on the view. For
25336         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25337         * <p>
25338         * The default implementation behaves as
25339         * {@link View#performAccessibilityAction(int, Bundle)
25340         *  View#performAccessibilityAction(int, Bundle)} for the case of
25341         *  no accessibility delegate been set.
25342         * </p>
25343         *
25344         * @param action The action to perform.
25345         * @return Whether the action was performed.
25346         *
25347         * @see View#performAccessibilityAction(int, Bundle)
25348         *      View#performAccessibilityAction(int, Bundle)
25349         */
25350        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25351            return host.performAccessibilityActionInternal(action, args);
25352        }
25353
25354        /**
25355         * Sends an accessibility event. This method behaves exactly as
25356         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25357         * empty {@link AccessibilityEvent} and does not perform a check whether
25358         * accessibility is enabled.
25359         * <p>
25360         * The default implementation behaves as
25361         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25362         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25363         * the case of no accessibility delegate been set.
25364         * </p>
25365         *
25366         * @param host The View hosting the delegate.
25367         * @param event The event to send.
25368         *
25369         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25370         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25371         */
25372        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25373            host.sendAccessibilityEventUncheckedInternal(event);
25374        }
25375
25376        /**
25377         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25378         * to its children for adding their text content to the event.
25379         * <p>
25380         * The default implementation behaves as
25381         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25382         *  View#dispatchPopulateAccessibilityEvent(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.
25388         * @return True if the event population was completed.
25389         *
25390         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25391         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25392         */
25393        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25394            return host.dispatchPopulateAccessibilityEventInternal(event);
25395        }
25396
25397        /**
25398         * Gives a chance to the host View to populate the accessibility event with its
25399         * text content.
25400         * <p>
25401         * The default implementation behaves as
25402         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25403         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25404         * the case of no accessibility delegate been set.
25405         * </p>
25406         *
25407         * @param host The View hosting the delegate.
25408         * @param event The accessibility event which to populate.
25409         *
25410         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25411         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25412         */
25413        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25414            host.onPopulateAccessibilityEventInternal(event);
25415        }
25416
25417        /**
25418         * Initializes an {@link AccessibilityEvent} with information about the
25419         * the host View which is the event source.
25420         * <p>
25421         * The default implementation behaves as
25422         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25423         *  View#onInitializeAccessibilityEvent(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 event to initialize.
25429         *
25430         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25431         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25432         */
25433        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25434            host.onInitializeAccessibilityEventInternal(event);
25435        }
25436
25437        /**
25438         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25439         * <p>
25440         * The default implementation behaves as
25441         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25442         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25443         * the case of no accessibility delegate been set.
25444         * </p>
25445         *
25446         * @param host The View hosting the delegate.
25447         * @param info The instance to initialize.
25448         *
25449         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25450         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25451         */
25452        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25453            host.onInitializeAccessibilityNodeInfoInternal(info);
25454        }
25455
25456        /**
25457         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25458         * additional data.
25459         * <p>
25460         * This method only needs to be implemented if the View offers to provide additional data.
25461         * </p>
25462         * <p>
25463         * The default implementation behaves as
25464         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25465         * the case where no accessibility delegate is set.
25466         * </p>
25467         *
25468         * @param host The View hosting the delegate. Never {@code null}.
25469         * @param info The info to which to add the extra data. Never {@code null}.
25470         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25471         *                     extra data should be added to the {@link Bundle} returned by
25472         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25473         *                     {@code null}.
25474         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25475         *                  May be {@code null} if the if the service provided no arguments.
25476         *
25477         * @see AccessibilityNodeInfo#setExtraAvailableData
25478         */
25479        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25480                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25481                @Nullable Bundle arguments) {
25482            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25483        }
25484
25485        /**
25486         * Called when a child of the host View has requested sending an
25487         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25488         * to augment the event.
25489         * <p>
25490         * The default implementation behaves as
25491         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25492         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25493         * the case of no accessibility delegate been set.
25494         * </p>
25495         *
25496         * @param host The View hosting the delegate.
25497         * @param child The child which requests sending the event.
25498         * @param event The event to be sent.
25499         * @return True if the event should be sent
25500         *
25501         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25502         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25503         */
25504        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25505                AccessibilityEvent event) {
25506            return host.onRequestSendAccessibilityEventInternal(child, event);
25507        }
25508
25509        /**
25510         * Gets the provider for managing a virtual view hierarchy rooted at this View
25511         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25512         * that explore the window content.
25513         * <p>
25514         * The default implementation behaves as
25515         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25516         * the case of no accessibility delegate been set.
25517         * </p>
25518         *
25519         * @return The provider.
25520         *
25521         * @see AccessibilityNodeProvider
25522         */
25523        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25524            return null;
25525        }
25526
25527        /**
25528         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25529         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25530         * This method is responsible for obtaining an accessibility node info from a
25531         * pool of reusable instances and calling
25532         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25533         * view to initialize the former.
25534         * <p>
25535         * <strong>Note:</strong> The client is responsible for recycling the obtained
25536         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25537         * creation.
25538         * </p>
25539         * <p>
25540         * The default implementation behaves as
25541         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25542         * the case of no accessibility delegate been set.
25543         * </p>
25544         * @return A populated {@link AccessibilityNodeInfo}.
25545         *
25546         * @see AccessibilityNodeInfo
25547         *
25548         * @hide
25549         */
25550        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25551            return host.createAccessibilityNodeInfoInternal();
25552        }
25553    }
25554
25555    private static class MatchIdPredicate implements Predicate<View> {
25556        public int mId;
25557
25558        @Override
25559        public boolean test(View view) {
25560            return (view.mID == mId);
25561        }
25562    }
25563
25564    private static class MatchLabelForPredicate implements Predicate<View> {
25565        private int mLabeledId;
25566
25567        @Override
25568        public boolean test(View view) {
25569            return (view.mLabelForId == mLabeledId);
25570        }
25571    }
25572
25573    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25574        private int mChangeTypes = 0;
25575        private boolean mPosted;
25576        private boolean mPostedWithDelay;
25577        private long mLastEventTimeMillis;
25578
25579        @Override
25580        public void run() {
25581            mPosted = false;
25582            mPostedWithDelay = false;
25583            mLastEventTimeMillis = SystemClock.uptimeMillis();
25584            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25585                final AccessibilityEvent event = AccessibilityEvent.obtain();
25586                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25587                event.setContentChangeTypes(mChangeTypes);
25588                sendAccessibilityEventUnchecked(event);
25589            }
25590            mChangeTypes = 0;
25591        }
25592
25593        public void runOrPost(int changeType) {
25594            mChangeTypes |= changeType;
25595
25596            // If this is a live region or the child of a live region, collect
25597            // all events from this frame and send them on the next frame.
25598            if (inLiveRegion()) {
25599                // If we're already posted with a delay, remove that.
25600                if (mPostedWithDelay) {
25601                    removeCallbacks(this);
25602                    mPostedWithDelay = false;
25603                }
25604                // Only post if we're not already posted.
25605                if (!mPosted) {
25606                    post(this);
25607                    mPosted = true;
25608                }
25609                return;
25610            }
25611
25612            if (mPosted) {
25613                return;
25614            }
25615
25616            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25617            final long minEventIntevalMillis =
25618                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25619            if (timeSinceLastMillis >= minEventIntevalMillis) {
25620                removeCallbacks(this);
25621                run();
25622            } else {
25623                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25624                mPostedWithDelay = true;
25625            }
25626        }
25627    }
25628
25629    private boolean inLiveRegion() {
25630        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25631            return true;
25632        }
25633
25634        ViewParent parent = getParent();
25635        while (parent instanceof View) {
25636            if (((View) parent).getAccessibilityLiveRegion()
25637                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25638                return true;
25639            }
25640            parent = parent.getParent();
25641        }
25642
25643        return false;
25644    }
25645
25646    /**
25647     * Dump all private flags in readable format, useful for documentation and
25648     * sanity checking.
25649     */
25650    private static void dumpFlags() {
25651        final HashMap<String, String> found = Maps.newHashMap();
25652        try {
25653            for (Field field : View.class.getDeclaredFields()) {
25654                final int modifiers = field.getModifiers();
25655                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25656                    if (field.getType().equals(int.class)) {
25657                        final int value = field.getInt(null);
25658                        dumpFlag(found, field.getName(), value);
25659                    } else if (field.getType().equals(int[].class)) {
25660                        final int[] values = (int[]) field.get(null);
25661                        for (int i = 0; i < values.length; i++) {
25662                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25663                        }
25664                    }
25665                }
25666            }
25667        } catch (IllegalAccessException e) {
25668            throw new RuntimeException(e);
25669        }
25670
25671        final ArrayList<String> keys = Lists.newArrayList();
25672        keys.addAll(found.keySet());
25673        Collections.sort(keys);
25674        for (String key : keys) {
25675            Log.d(VIEW_LOG_TAG, found.get(key));
25676        }
25677    }
25678
25679    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25680        // Sort flags by prefix, then by bits, always keeping unique keys
25681        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25682        final int prefix = name.indexOf('_');
25683        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25684        final String output = bits + " " + name;
25685        found.put(key, output);
25686    }
25687
25688    /** {@hide} */
25689    public void encode(@NonNull ViewHierarchyEncoder stream) {
25690        stream.beginObject(this);
25691        encodeProperties(stream);
25692        stream.endObject();
25693    }
25694
25695    /** {@hide} */
25696    @CallSuper
25697    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25698        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25699        if (resolveId instanceof String) {
25700            stream.addProperty("id", (String) resolveId);
25701        } else {
25702            stream.addProperty("id", mID);
25703        }
25704
25705        stream.addProperty("misc:transformation.alpha",
25706                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25707        stream.addProperty("misc:transitionName", getTransitionName());
25708
25709        // layout
25710        stream.addProperty("layout:left", mLeft);
25711        stream.addProperty("layout:right", mRight);
25712        stream.addProperty("layout:top", mTop);
25713        stream.addProperty("layout:bottom", mBottom);
25714        stream.addProperty("layout:width", getWidth());
25715        stream.addProperty("layout:height", getHeight());
25716        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25717        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25718        stream.addProperty("layout:hasTransientState", hasTransientState());
25719        stream.addProperty("layout:baseline", getBaseline());
25720
25721        // layout params
25722        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25723        if (layoutParams != null) {
25724            stream.addPropertyKey("layoutParams");
25725            layoutParams.encode(stream);
25726        }
25727
25728        // scrolling
25729        stream.addProperty("scrolling:scrollX", mScrollX);
25730        stream.addProperty("scrolling:scrollY", mScrollY);
25731
25732        // padding
25733        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25734        stream.addProperty("padding:paddingRight", mPaddingRight);
25735        stream.addProperty("padding:paddingTop", mPaddingTop);
25736        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25737        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25738        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25739        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25740        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25741        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25742
25743        // measurement
25744        stream.addProperty("measurement:minHeight", mMinHeight);
25745        stream.addProperty("measurement:minWidth", mMinWidth);
25746        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25747        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25748
25749        // drawing
25750        stream.addProperty("drawing:elevation", getElevation());
25751        stream.addProperty("drawing:translationX", getTranslationX());
25752        stream.addProperty("drawing:translationY", getTranslationY());
25753        stream.addProperty("drawing:translationZ", getTranslationZ());
25754        stream.addProperty("drawing:rotation", getRotation());
25755        stream.addProperty("drawing:rotationX", getRotationX());
25756        stream.addProperty("drawing:rotationY", getRotationY());
25757        stream.addProperty("drawing:scaleX", getScaleX());
25758        stream.addProperty("drawing:scaleY", getScaleY());
25759        stream.addProperty("drawing:pivotX", getPivotX());
25760        stream.addProperty("drawing:pivotY", getPivotY());
25761        stream.addProperty("drawing:opaque", isOpaque());
25762        stream.addProperty("drawing:alpha", getAlpha());
25763        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25764        stream.addProperty("drawing:shadow", hasShadow());
25765        stream.addProperty("drawing:solidColor", getSolidColor());
25766        stream.addProperty("drawing:layerType", mLayerType);
25767        stream.addProperty("drawing:willNotDraw", willNotDraw());
25768        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25769        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25770        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25771        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25772
25773        // focus
25774        stream.addProperty("focus:hasFocus", hasFocus());
25775        stream.addProperty("focus:isFocused", isFocused());
25776        stream.addProperty("focus:focusable", getFocusable());
25777        stream.addProperty("focus:isFocusable", isFocusable());
25778        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25779
25780        stream.addProperty("misc:clickable", isClickable());
25781        stream.addProperty("misc:pressed", isPressed());
25782        stream.addProperty("misc:selected", isSelected());
25783        stream.addProperty("misc:touchMode", isInTouchMode());
25784        stream.addProperty("misc:hovered", isHovered());
25785        stream.addProperty("misc:activated", isActivated());
25786
25787        stream.addProperty("misc:visibility", getVisibility());
25788        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25789        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25790
25791        stream.addProperty("misc:enabled", isEnabled());
25792        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25793        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25794
25795        // theme attributes
25796        Resources.Theme theme = getContext().getTheme();
25797        if (theme != null) {
25798            stream.addPropertyKey("theme");
25799            theme.encode(stream);
25800        }
25801
25802        // view attribute information
25803        int n = mAttributes != null ? mAttributes.length : 0;
25804        stream.addProperty("meta:__attrCount__", n/2);
25805        for (int i = 0; i < n; i += 2) {
25806            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25807        }
25808
25809        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25810
25811        // text
25812        stream.addProperty("text:textDirection", getTextDirection());
25813        stream.addProperty("text:textAlignment", getTextAlignment());
25814
25815        // accessibility
25816        CharSequence contentDescription = getContentDescription();
25817        stream.addProperty("accessibility:contentDescription",
25818                contentDescription == null ? "" : contentDescription.toString());
25819        stream.addProperty("accessibility:labelFor", getLabelFor());
25820        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25821    }
25822
25823    /**
25824     * Determine if this view is rendered on a round wearable device and is the main view
25825     * on the screen.
25826     */
25827    boolean shouldDrawRoundScrollbar() {
25828        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25829            return false;
25830        }
25831
25832        final View rootView = getRootView();
25833        final WindowInsets insets = getRootWindowInsets();
25834
25835        int height = getHeight();
25836        int width = getWidth();
25837        int displayHeight = rootView.getHeight();
25838        int displayWidth = rootView.getWidth();
25839
25840        if (height != displayHeight || width != displayWidth) {
25841            return false;
25842        }
25843
25844        getLocationInWindow(mAttachInfo.mTmpLocation);
25845        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25846                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25847    }
25848
25849    /**
25850     * Sets the tooltip text which will be displayed in a small popup next to the view.
25851     * <p>
25852     * The tooltip will be displayed:
25853     * <ul>
25854     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
25855     * menu). </li>
25856     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25857     * </ul>
25858     * <p>
25859     * <strong>Note:</strong> Do not override this method, as it will have no
25860     * effect on the text displayed in the tooltip.
25861     *
25862     * @param tooltipText the tooltip text, or null if no tooltip is required
25863     * @see #getTooltipText()
25864     * @attr ref android.R.styleable#View_tooltipText
25865     */
25866    public void setTooltipText(@Nullable CharSequence tooltipText) {
25867        if (TextUtils.isEmpty(tooltipText)) {
25868            setFlags(0, TOOLTIP);
25869            hideTooltip();
25870            mTooltipInfo = null;
25871        } else {
25872            setFlags(TOOLTIP, TOOLTIP);
25873            if (mTooltipInfo == null) {
25874                mTooltipInfo = new TooltipInfo();
25875                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25876                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25877            }
25878            mTooltipInfo.mTooltipText = tooltipText;
25879            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25880                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25881            }
25882        }
25883    }
25884
25885    /**
25886     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25887     */
25888    public void setTooltip(@Nullable CharSequence tooltipText) {
25889        setTooltipText(tooltipText);
25890    }
25891
25892    /**
25893     * Returns the view's tooltip text.
25894     *
25895     * <strong>Note:</strong> Do not override this method, as it will have no
25896     * effect on the text displayed in the tooltip. You must call
25897     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25898     *
25899     * @return the tooltip text
25900     * @see #setTooltipText(CharSequence)
25901     * @attr ref android.R.styleable#View_tooltipText
25902     */
25903    @Nullable
25904    public CharSequence getTooltipText() {
25905        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25906    }
25907
25908    /**
25909     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25910     */
25911    @Nullable
25912    public CharSequence getTooltip() {
25913        return getTooltipText();
25914    }
25915
25916    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25917        if (mAttachInfo == null || mTooltipInfo == null) {
25918            return false;
25919        }
25920        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25921            return false;
25922        }
25923        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25924            return false;
25925        }
25926        hideTooltip();
25927        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25928        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25929        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25930        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25931        mAttachInfo.mTooltipHost = this;
25932        return true;
25933    }
25934
25935    void hideTooltip() {
25936        if (mTooltipInfo == null) {
25937            return;
25938        }
25939        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25940        if (mTooltipInfo.mTooltipPopup == null) {
25941            return;
25942        }
25943        mTooltipInfo.mTooltipPopup.hide();
25944        mTooltipInfo.mTooltipPopup = null;
25945        mTooltipInfo.mTooltipFromLongClick = false;
25946        if (mAttachInfo != null) {
25947            mAttachInfo.mTooltipHost = null;
25948        }
25949    }
25950
25951    private boolean showLongClickTooltip(int x, int y) {
25952        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25953        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25954        return showTooltip(x, y, true);
25955    }
25956
25957    private void showHoverTooltip() {
25958        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25959    }
25960
25961    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25962        if (mTooltipInfo == null) {
25963            return false;
25964        }
25965        switch(event.getAction()) {
25966            case MotionEvent.ACTION_HOVER_MOVE:
25967                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25968                    break;
25969                }
25970                if (!mTooltipInfo.mTooltipFromLongClick) {
25971                    if (mTooltipInfo.mTooltipPopup == null) {
25972                        // Schedule showing the tooltip after a timeout.
25973                        mTooltipInfo.mAnchorX = (int) event.getX();
25974                        mTooltipInfo.mAnchorY = (int) event.getY();
25975                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25976                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25977                                ViewConfiguration.getHoverTooltipShowTimeout());
25978                    }
25979
25980                    // Hide hover-triggered tooltip after a period of inactivity.
25981                    // Match the timeout used by NativeInputManager to hide the mouse pointer
25982                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
25983                    final int timeout;
25984                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
25985                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
25986                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
25987                    } else {
25988                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
25989                    }
25990                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25991                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
25992                }
25993                return true;
25994
25995            case MotionEvent.ACTION_HOVER_EXIT:
25996                if (!mTooltipInfo.mTooltipFromLongClick) {
25997                    hideTooltip();
25998                }
25999                break;
26000        }
26001        return false;
26002    }
26003
26004    void handleTooltipKey(KeyEvent event) {
26005        switch (event.getAction()) {
26006            case KeyEvent.ACTION_DOWN:
26007                if (event.getRepeatCount() == 0) {
26008                    hideTooltip();
26009                }
26010                break;
26011
26012            case KeyEvent.ACTION_UP:
26013                handleTooltipUp();
26014                break;
26015        }
26016    }
26017
26018    private void handleTooltipUp() {
26019        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26020            return;
26021        }
26022        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26023        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26024                ViewConfiguration.getLongPressTooltipHideTimeout());
26025    }
26026
26027    private int getFocusableAttribute(TypedArray attributes) {
26028        TypedValue val = new TypedValue();
26029        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26030            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26031                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26032            } else {
26033                return val.data;
26034            }
26035        } else {
26036            return FOCUSABLE_AUTO;
26037        }
26038    }
26039
26040    /**
26041     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26042     * is not showing.
26043     * @hide
26044     */
26045    @TestApi
26046    public View getTooltipView() {
26047        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26048            return null;
26049        }
26050        return mTooltipInfo.mTooltipPopup.getContentView();
26051    }
26052}
26053