View.java revision af00cb406ca62897e0d0ebbfabf86f146a148a17
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import static java.lang.Math.max;
20
21import android.animation.AnimatorInflater;
22import android.animation.StateListAnimator;
23import android.annotation.CallSuper;
24import android.annotation.ColorInt;
25import android.annotation.DrawableRes;
26import android.annotation.FloatRange;
27import android.annotation.IdRes;
28import android.annotation.IntDef;
29import android.annotation.IntRange;
30import android.annotation.LayoutRes;
31import android.annotation.NonNull;
32import android.annotation.Nullable;
33import android.annotation.Size;
34import android.annotation.TestApi;
35import android.annotation.UiThread;
36import android.content.ClipData;
37import android.content.Context;
38import android.content.ContextWrapper;
39import android.content.Intent;
40import android.content.res.ColorStateList;
41import android.content.res.Configuration;
42import android.content.res.Resources;
43import android.content.res.TypedArray;
44import android.graphics.Bitmap;
45import android.graphics.Canvas;
46import android.graphics.Color;
47import android.graphics.Insets;
48import android.graphics.Interpolator;
49import android.graphics.LinearGradient;
50import android.graphics.Matrix;
51import android.graphics.Outline;
52import android.graphics.Paint;
53import android.graphics.PixelFormat;
54import android.graphics.Point;
55import android.graphics.PorterDuff;
56import android.graphics.PorterDuffXfermode;
57import android.graphics.Rect;
58import android.graphics.RectF;
59import android.graphics.Region;
60import android.graphics.Shader;
61import android.graphics.drawable.ColorDrawable;
62import android.graphics.drawable.Drawable;
63import android.hardware.display.DisplayManagerGlobal;
64import android.net.Uri;
65import android.os.Build;
66import android.os.Bundle;
67import android.os.Handler;
68import android.os.IBinder;
69import android.os.Message;
70import android.os.Parcel;
71import android.os.Parcelable;
72import android.os.RemoteException;
73import android.os.SystemClock;
74import android.os.SystemProperties;
75import android.os.Trace;
76import android.text.TextUtils;
77import android.util.AttributeSet;
78import android.util.FloatProperty;
79import android.util.LayoutDirection;
80import android.util.Log;
81import android.util.LongSparseLongArray;
82import android.util.Pools.SynchronizedPool;
83import android.util.Property;
84import android.util.SparseArray;
85import android.util.StateSet;
86import android.util.SuperNotCalledException;
87import android.util.TypedValue;
88import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
89import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
90import android.view.AccessibilityIterators.TextSegmentIterator;
91import android.view.AccessibilityIterators.WordTextSegmentIterator;
92import android.view.ContextMenu.ContextMenuInfo;
93import android.view.accessibility.AccessibilityEvent;
94import android.view.accessibility.AccessibilityEventSource;
95import android.view.accessibility.AccessibilityManager;
96import android.view.accessibility.AccessibilityNodeInfo;
97import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
98import android.view.accessibility.AccessibilityNodeProvider;
99import android.view.accessibility.AccessibilityWindowInfo;
100import android.view.animation.Animation;
101import android.view.animation.AnimationUtils;
102import android.view.animation.Transformation;
103import android.view.autofill.AutofillId;
104import android.view.autofill.AutofillManager;
105import android.view.autofill.AutofillValue;
106import android.view.inputmethod.EditorInfo;
107import android.view.inputmethod.InputConnection;
108import android.view.inputmethod.InputMethodManager;
109import android.widget.Checkable;
110import android.widget.FrameLayout;
111import android.widget.ScrollBarDrawable;
112
113import com.android.internal.R;
114import com.android.internal.view.TooltipPopup;
115import com.android.internal.view.menu.MenuBuilder;
116import com.android.internal.widget.ScrollBarUtils;
117
118import com.google.android.collect.Lists;
119import com.google.android.collect.Maps;
120
121import java.lang.annotation.Retention;
122import java.lang.annotation.RetentionPolicy;
123import java.lang.ref.WeakReference;
124import java.lang.reflect.Field;
125import java.lang.reflect.InvocationTargetException;
126import java.lang.reflect.Method;
127import java.lang.reflect.Modifier;
128import java.util.ArrayList;
129import java.util.Arrays;
130import java.util.Collection;
131import java.util.Collections;
132import java.util.HashMap;
133import java.util.List;
134import java.util.Locale;
135import java.util.Map;
136import java.util.concurrent.CopyOnWriteArrayList;
137import java.util.concurrent.atomic.AtomicInteger;
138import java.util.function.Predicate;
139
140/**
141 * <p>
142 * This class represents the basic building block for user interface components. A View
143 * occupies a rectangular area on the screen and is responsible for drawing and
144 * event handling. View is the base class for <em>widgets</em>, which are
145 * used to create interactive UI components (buttons, text fields, etc.). The
146 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
147 * are invisible containers that hold other Views (or other ViewGroups) and define
148 * their layout properties.
149 * </p>
150 *
151 * <div class="special reference">
152 * <h3>Developer Guides</h3>
153 * <p>For information about using this class to develop your application's user interface,
154 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
155 * </div>
156 *
157 * <a name="Using"></a>
158 * <h3>Using Views</h3>
159 * <p>
160 * All of the views in a window are arranged in a single tree. You can add views
161 * either from code or by specifying a tree of views in one or more XML layout
162 * files. There are many specialized subclasses of views that act as controls or
163 * are capable of displaying text, images, or other content.
164 * </p>
165 * <p>
166 * Once you have created a tree of views, there are typically a few types of
167 * common operations you may wish to perform:
168 * <ul>
169 * <li><strong>Set properties:</strong> for example setting the text of a
170 * {@link android.widget.TextView}. The available properties and the methods
171 * that set them will vary among the different subclasses of views. Note that
172 * properties that are known at build time can be set in the XML layout
173 * files.</li>
174 * <li><strong>Set focus:</strong> The framework will handle moving focus in
175 * response to user input. To force focus to a specific view, call
176 * {@link #requestFocus}.</li>
177 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
178 * that will be notified when something interesting happens to the view. For
179 * example, all views will let you set a listener to be notified when the view
180 * gains or loses focus. You can register such a listener using
181 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
182 * Other view subclasses offer more specialized listeners. For example, a Button
183 * exposes a listener to notify clients when the button is clicked.</li>
184 * <li><strong>Set visibility:</strong> You can hide or show views using
185 * {@link #setVisibility(int)}.</li>
186 * </ul>
187 * </p>
188 * <p><em>
189 * Note: The Android framework is responsible for measuring, laying out and
190 * drawing views. You should not call methods that perform these actions on
191 * views yourself unless you are actually implementing a
192 * {@link android.view.ViewGroup}.
193 * </em></p>
194 *
195 * <a name="Lifecycle"></a>
196 * <h3>Implementing a Custom View</h3>
197 *
198 * <p>
199 * To implement a custom view, you will usually begin by providing overrides for
200 * some of the standard methods that the framework calls on all views. You do
201 * not need to override all of these methods. In fact, you can start by just
202 * overriding {@link #onDraw(android.graphics.Canvas)}.
203 * <table border="2" width="85%" align="center" cellpadding="5">
204 *     <thead>
205 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
206 *     </thead>
207 *
208 *     <tbody>
209 *     <tr>
210 *         <td rowspan="2">Creation</td>
211 *         <td>Constructors</td>
212 *         <td>There is a form of the constructor that are called when the view
213 *         is created from code and a form that is called when the view is
214 *         inflated from a layout file. The second form should parse and apply
215 *         any attributes defined in the layout file.
216 *         </td>
217 *     </tr>
218 *     <tr>
219 *         <td><code>{@link #onFinishInflate()}</code></td>
220 *         <td>Called after a view and all of its children has been inflated
221 *         from XML.</td>
222 *     </tr>
223 *
224 *     <tr>
225 *         <td rowspan="3">Layout</td>
226 *         <td><code>{@link #onMeasure(int, int)}</code></td>
227 *         <td>Called to determine the size requirements for this view and all
228 *         of its children.
229 *         </td>
230 *     </tr>
231 *     <tr>
232 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
233 *         <td>Called when this view should assign a size and position to all
234 *         of its children.
235 *         </td>
236 *     </tr>
237 *     <tr>
238 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
239 *         <td>Called when the size of this view has changed.
240 *         </td>
241 *     </tr>
242 *
243 *     <tr>
244 *         <td>Drawing</td>
245 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
246 *         <td>Called when the view should render its content.
247 *         </td>
248 *     </tr>
249 *
250 *     <tr>
251 *         <td rowspan="4">Event processing</td>
252 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
253 *         <td>Called when a new hardware key event occurs.
254 *         </td>
255 *     </tr>
256 *     <tr>
257 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
258 *         <td>Called when a hardware key up event occurs.
259 *         </td>
260 *     </tr>
261 *     <tr>
262 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
263 *         <td>Called when a trackball motion event occurs.
264 *         </td>
265 *     </tr>
266 *     <tr>
267 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
268 *         <td>Called when a touch screen motion event occurs.
269 *         </td>
270 *     </tr>
271 *
272 *     <tr>
273 *         <td rowspan="2">Focus</td>
274 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
275 *         <td>Called when the view gains or loses focus.
276 *         </td>
277 *     </tr>
278 *
279 *     <tr>
280 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
281 *         <td>Called when the window containing the view gains or loses focus.
282 *         </td>
283 *     </tr>
284 *
285 *     <tr>
286 *         <td rowspan="3">Attaching</td>
287 *         <td><code>{@link #onAttachedToWindow()}</code></td>
288 *         <td>Called when the view is attached to a window.
289 *         </td>
290 *     </tr>
291 *
292 *     <tr>
293 *         <td><code>{@link #onDetachedFromWindow}</code></td>
294 *         <td>Called when the view is detached from its window.
295 *         </td>
296 *     </tr>
297 *
298 *     <tr>
299 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
300 *         <td>Called when the visibility of the window containing the view
301 *         has changed.
302 *         </td>
303 *     </tr>
304 *     </tbody>
305 *
306 * </table>
307 * </p>
308 *
309 * <a name="IDs"></a>
310 * <h3>IDs</h3>
311 * Views may have an integer id associated with them. These ids are typically
312 * assigned in the layout XML files, and are used to find specific views within
313 * the view tree. A common pattern is to:
314 * <ul>
315 * <li>Define a Button in the layout file and assign it a unique ID.
316 * <pre>
317 * &lt;Button
318 *     android:id="@+id/my_button"
319 *     android:layout_width="wrap_content"
320 *     android:layout_height="wrap_content"
321 *     android:text="@string/my_button_text"/&gt;
322 * </pre></li>
323 * <li>From the onCreate method of an Activity, find the Button
324 * <pre class="prettyprint">
325 *      Button myButton = findViewById(R.id.my_button);
326 * </pre></li>
327 * </ul>
328 * <p>
329 * View IDs need not be unique throughout the tree, but it is good practice to
330 * ensure that they are at least unique within the part of the tree you are
331 * searching.
332 * </p>
333 *
334 * <a name="Position"></a>
335 * <h3>Position</h3>
336 * <p>
337 * The geometry of a view is that of a rectangle. A view has a location,
338 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
339 * two dimensions, expressed as a width and a height. The unit for location
340 * and dimensions is the pixel.
341 * </p>
342 *
343 * <p>
344 * It is possible to retrieve the location of a view by invoking the methods
345 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
346 * coordinate of the rectangle representing the view. The latter returns the
347 * top, or Y, coordinate of the rectangle representing the view. These methods
348 * both return the location of the view relative to its parent. For instance,
349 * when getLeft() returns 20, that means the view is located 20 pixels to the
350 * right of the left edge of its direct parent.
351 * </p>
352 *
353 * <p>
354 * In addition, several convenience methods are offered to avoid unnecessary
355 * computations, namely {@link #getRight()} and {@link #getBottom()}.
356 * These methods return the coordinates of the right and bottom edges of the
357 * rectangle representing the view. For instance, calling {@link #getRight()}
358 * is similar to the following computation: <code>getLeft() + getWidth()</code>
359 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
360 * </p>
361 *
362 * <a name="SizePaddingMargins"></a>
363 * <h3>Size, padding and margins</h3>
364 * <p>
365 * The size of a view is expressed with a width and a height. A view actually
366 * possess two pairs of width and height values.
367 * </p>
368 *
369 * <p>
370 * The first pair is known as <em>measured width</em> and
371 * <em>measured height</em>. These dimensions define how big a view wants to be
372 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
373 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
374 * and {@link #getMeasuredHeight()}.
375 * </p>
376 *
377 * <p>
378 * The second pair is simply known as <em>width</em> and <em>height</em>, or
379 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
380 * dimensions define the actual size of the view on screen, at drawing time and
381 * after layout. These values may, but do not have to, be different from the
382 * measured width and height. The width and height can be obtained by calling
383 * {@link #getWidth()} and {@link #getHeight()}.
384 * </p>
385 *
386 * <p>
387 * To measure its dimensions, a view takes into account its padding. The padding
388 * is expressed in pixels for the left, top, right and bottom parts of the view.
389 * Padding can be used to offset the content of the view by a specific amount of
390 * pixels. For instance, a left padding of 2 will push the view's content by
391 * 2 pixels to the right of the left edge. Padding can be set using the
392 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
393 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
394 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
395 * {@link #getPaddingEnd()}.
396 * </p>
397 *
398 * <p>
399 * Even though a view can define a padding, it does not provide any support for
400 * margins. However, view groups provide such a support. Refer to
401 * {@link android.view.ViewGroup} and
402 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
403 * </p>
404 *
405 * <a name="Layout"></a>
406 * <h3>Layout</h3>
407 * <p>
408 * Layout is a two pass process: a measure pass and a layout pass. The measuring
409 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
410 * of the view tree. Each view pushes dimension specifications down the tree
411 * during the recursion. At the end of the measure pass, every view has stored
412 * its measurements. The second pass happens in
413 * {@link #layout(int,int,int,int)} and is also top-down. During
414 * this pass each parent is responsible for positioning all of its children
415 * using the sizes computed in the measure pass.
416 * </p>
417 *
418 * <p>
419 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
420 * {@link #getMeasuredHeight()} values must be set, along with those for all of
421 * that view's descendants. A view's measured width and measured height values
422 * must respect the constraints imposed by the view's parents. This guarantees
423 * that at the end of the measure pass, all parents accept all of their
424 * children's measurements. A parent view may call measure() more than once on
425 * its children. For example, the parent may measure each child once with
426 * unspecified dimensions to find out how big they want to be, then call
427 * measure() on them again with actual numbers if the sum of all the children's
428 * unconstrained sizes is too big or too small.
429 * </p>
430 *
431 * <p>
432 * The measure pass uses two classes to communicate dimensions. The
433 * {@link MeasureSpec} class is used by views to tell their parents how they
434 * want to be measured and positioned. The base LayoutParams class just
435 * describes how big the view wants to be for both width and height. For each
436 * dimension, it can specify one of:
437 * <ul>
438 * <li> an exact number
439 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
440 * (minus padding)
441 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
442 * enclose its content (plus padding).
443 * </ul>
444 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
445 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
446 * an X and Y value.
447 * </p>
448 *
449 * <p>
450 * MeasureSpecs are used to push requirements down the tree from parent to
451 * child. A MeasureSpec can be in one of three modes:
452 * <ul>
453 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
454 * of a child view. For example, a LinearLayout may call measure() on its child
455 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
456 * tall the child view wants to be given a width of 240 pixels.
457 * <li>EXACTLY: This is used by the parent to impose an exact size on the
458 * child. The child must use this size, and guarantee that all of its
459 * descendants will fit within this size.
460 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
461 * child. The child must guarantee that it and all of its descendants will fit
462 * within this size.
463 * </ul>
464 * </p>
465 *
466 * <p>
467 * To initiate a layout, call {@link #requestLayout}. This method is typically
468 * called by a view on itself when it believes that is can no longer fit within
469 * its current bounds.
470 * </p>
471 *
472 * <a name="Drawing"></a>
473 * <h3>Drawing</h3>
474 * <p>
475 * Drawing is handled by walking the tree and recording the drawing commands of
476 * any View that needs to update. After this, the drawing commands of the
477 * entire tree are issued to screen, clipped to the newly damaged area.
478 * </p>
479 *
480 * <p>
481 * The tree is largely recorded and drawn in order, with parents drawn before
482 * (i.e., behind) their children, with siblings drawn in the order they appear
483 * in the tree. If you set a background drawable for a View, then the View will
484 * draw it before calling back to its <code>onDraw()</code> method. The child
485 * drawing order can be overridden with
486 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
487 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
488 * </p>
489 *
490 * <p>
491 * To force a view to draw, call {@link #invalidate()}.
492 * </p>
493 *
494 * <a name="EventHandlingThreading"></a>
495 * <h3>Event Handling and Threading</h3>
496 * <p>
497 * The basic cycle of a view is as follows:
498 * <ol>
499 * <li>An event comes in and is dispatched to the appropriate view. The view
500 * handles the event and notifies any listeners.</li>
501 * <li>If in the course of processing the event, the view's bounds may need
502 * to be changed, the view will call {@link #requestLayout()}.</li>
503 * <li>Similarly, if in the course of processing the event the view's appearance
504 * may need to be changed, the view will call {@link #invalidate()}.</li>
505 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
506 * the framework will take care of measuring, laying out, and drawing the tree
507 * as appropriate.</li>
508 * </ol>
509 * </p>
510 *
511 * <p><em>Note: The entire view tree is single threaded. You must always be on
512 * the UI thread when calling any method on any view.</em>
513 * If you are doing work on other threads and want to update the state of a view
514 * from that thread, you should use a {@link Handler}.
515 * </p>
516 *
517 * <a name="FocusHandling"></a>
518 * <h3>Focus Handling</h3>
519 * <p>
520 * The framework will handle routine focus movement in response to user input.
521 * This includes changing the focus as views are removed or hidden, or as new
522 * views become available. Views indicate their willingness to take focus
523 * through the {@link #isFocusable} method. To change whether a view can take
524 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
525 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
526 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
527 * </p>
528 * <p>
529 * Focus movement is based on an algorithm which finds the nearest neighbor in a
530 * given direction. In rare cases, the default algorithm may not match the
531 * intended behavior of the developer. In these situations, you can provide
532 * explicit overrides by using these XML attributes in the layout file:
533 * <pre>
534 * nextFocusDown
535 * nextFocusLeft
536 * nextFocusRight
537 * nextFocusUp
538 * </pre>
539 * </p>
540 *
541 *
542 * <p>
543 * To get a particular view to take focus, call {@link #requestFocus()}.
544 * </p>
545 *
546 * <a name="TouchMode"></a>
547 * <h3>Touch Mode</h3>
548 * <p>
549 * When a user is navigating a user interface via directional keys such as a D-pad, it is
550 * necessary to give focus to actionable items such as buttons so the user can see
551 * what will take input.  If the device has touch capabilities, however, and the user
552 * begins interacting with the interface by touching it, it is no longer necessary to
553 * always highlight, or give focus to, a particular view.  This motivates a mode
554 * for interaction named 'touch mode'.
555 * </p>
556 * <p>
557 * For a touch capable device, once the user touches the screen, the device
558 * will enter touch mode.  From this point onward, only views for which
559 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
560 * Other views that are touchable, like buttons, will not take focus when touched; they will
561 * only fire the on click listeners.
562 * </p>
563 * <p>
564 * Any time a user hits a directional key, such as a D-pad direction, the view device will
565 * exit touch mode, and find a view to take focus, so that the user may resume interacting
566 * with the user interface without touching the screen again.
567 * </p>
568 * <p>
569 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
570 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
571 * </p>
572 *
573 * <a name="Scrolling"></a>
574 * <h3>Scrolling</h3>
575 * <p>
576 * The framework provides basic support for views that wish to internally
577 * scroll their content. This includes keeping track of the X and Y scroll
578 * offset as well as mechanisms for drawing scrollbars. See
579 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
580 * {@link #awakenScrollBars()} for more details.
581 * </p>
582 *
583 * <a name="Tags"></a>
584 * <h3>Tags</h3>
585 * <p>
586 * Unlike IDs, tags are not used to identify views. Tags are essentially an
587 * extra piece of information that can be associated with a view. They are most
588 * often used as a convenience to store data related to views in the views
589 * themselves rather than by putting them in a separate structure.
590 * </p>
591 * <p>
592 * Tags may be specified with character sequence values in layout XML as either
593 * a single tag using the {@link android.R.styleable#View_tag android:tag}
594 * attribute or multiple tags using the {@code <tag>} child element:
595 * <pre>
596 *     &ltView ...
597 *           android:tag="@string/mytag_value" /&gt;
598 *     &ltView ...&gt;
599 *         &lttag android:id="@+id/mytag"
600 *              android:value="@string/mytag_value" /&gt;
601 *     &lt/View>
602 * </pre>
603 * </p>
604 * <p>
605 * Tags may also be specified with arbitrary objects from code using
606 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
607 * </p>
608 *
609 * <a name="Themes"></a>
610 * <h3>Themes</h3>
611 * <p>
612 * By default, Views are created using the theme of the Context object supplied
613 * to their constructor; however, a different theme may be specified by using
614 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
615 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
616 * code.
617 * </p>
618 * <p>
619 * When the {@link android.R.styleable#View_theme android:theme} attribute is
620 * used in XML, the specified theme is applied on top of the inflation
621 * context's theme (see {@link LayoutInflater}) and used for the view itself as
622 * well as any child elements.
623 * </p>
624 * <p>
625 * In the following example, both views will be created using the Material dark
626 * color scheme; however, because an overlay theme is used which only defines a
627 * subset of attributes, the value of
628 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
629 * the inflation context's theme (e.g. the Activity theme) will be preserved.
630 * <pre>
631 *     &ltLinearLayout
632 *             ...
633 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
634 *         &ltView ...&gt;
635 *     &lt/LinearLayout&gt;
636 * </pre>
637 * </p>
638 *
639 * <a name="Properties"></a>
640 * <h3>Properties</h3>
641 * <p>
642 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
643 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
644 * available both in the {@link Property} form as well as in similarly-named setter/getter
645 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
646 * be used to set persistent state associated with these rendering-related properties on the view.
647 * The properties and methods can also be used in conjunction with
648 * {@link android.animation.Animator Animator}-based animations, described more in the
649 * <a href="#Animation">Animation</a> section.
650 * </p>
651 *
652 * <a name="Animation"></a>
653 * <h3>Animation</h3>
654 * <p>
655 * Starting with Android 3.0, the preferred way of animating views is to use the
656 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
657 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
658 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
659 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
660 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
661 * makes animating these View properties particularly easy and efficient.
662 * </p>
663 * <p>
664 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
665 * You can attach an {@link Animation} object to a view using
666 * {@link #setAnimation(Animation)} or
667 * {@link #startAnimation(Animation)}. The animation can alter the scale,
668 * rotation, translation and alpha of a view over time. If the animation is
669 * attached to a view that has children, the animation will affect the entire
670 * subtree rooted by that node. When an animation is started, the framework will
671 * take care of redrawing the appropriate views until the animation completes.
672 * </p>
673 *
674 * <a name="Security"></a>
675 * <h3>Security</h3>
676 * <p>
677 * Sometimes it is essential that an application be able to verify that an action
678 * is being performed with the full knowledge and consent of the user, such as
679 * granting a permission request, making a purchase or clicking on an advertisement.
680 * Unfortunately, a malicious application could try to spoof the user into
681 * performing these actions, unaware, by concealing the intended purpose of the view.
682 * As a remedy, the framework offers a touch filtering mechanism that can be used to
683 * improve the security of views that provide access to sensitive functionality.
684 * </p><p>
685 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
686 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
687 * will discard touches that are received whenever the view's window is obscured by
688 * another visible window.  As a result, the view will not receive touches whenever a
689 * toast, dialog or other window appears above the view's window.
690 * </p><p>
691 * For more fine-grained control over security, consider overriding the
692 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
693 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
694 * </p>
695 *
696 * @attr ref android.R.styleable#View_alpha
697 * @attr ref android.R.styleable#View_background
698 * @attr ref android.R.styleable#View_clickable
699 * @attr ref android.R.styleable#View_contentDescription
700 * @attr ref android.R.styleable#View_drawingCacheQuality
701 * @attr ref android.R.styleable#View_duplicateParentState
702 * @attr ref android.R.styleable#View_id
703 * @attr ref android.R.styleable#View_requiresFadingEdge
704 * @attr ref android.R.styleable#View_fadeScrollbars
705 * @attr ref android.R.styleable#View_fadingEdgeLength
706 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
707 * @attr ref android.R.styleable#View_fitsSystemWindows
708 * @attr ref android.R.styleable#View_isScrollContainer
709 * @attr ref android.R.styleable#View_focusable
710 * @attr ref android.R.styleable#View_focusableInTouchMode
711 * @attr ref android.R.styleable#View_focusedByDefault
712 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
713 * @attr ref android.R.styleable#View_keepScreenOn
714 * @attr ref android.R.styleable#View_keyboardNavigationCluster
715 * @attr ref android.R.styleable#View_layerType
716 * @attr ref android.R.styleable#View_layoutDirection
717 * @attr ref android.R.styleable#View_longClickable
718 * @attr ref android.R.styleable#View_minHeight
719 * @attr ref android.R.styleable#View_minWidth
720 * @attr ref android.R.styleable#View_nextClusterForward
721 * @attr ref android.R.styleable#View_nextFocusDown
722 * @attr ref android.R.styleable#View_nextFocusLeft
723 * @attr ref android.R.styleable#View_nextFocusRight
724 * @attr ref android.R.styleable#View_nextFocusUp
725 * @attr ref android.R.styleable#View_onClick
726 * @attr ref android.R.styleable#View_padding
727 * @attr ref android.R.styleable#View_paddingBottom
728 * @attr ref android.R.styleable#View_paddingLeft
729 * @attr ref android.R.styleable#View_paddingRight
730 * @attr ref android.R.styleable#View_paddingTop
731 * @attr ref android.R.styleable#View_paddingStart
732 * @attr ref android.R.styleable#View_paddingEnd
733 * @attr ref android.R.styleable#View_saveEnabled
734 * @attr ref android.R.styleable#View_rotation
735 * @attr ref android.R.styleable#View_rotationX
736 * @attr ref android.R.styleable#View_rotationY
737 * @attr ref android.R.styleable#View_scaleX
738 * @attr ref android.R.styleable#View_scaleY
739 * @attr ref android.R.styleable#View_scrollX
740 * @attr ref android.R.styleable#View_scrollY
741 * @attr ref android.R.styleable#View_scrollbarSize
742 * @attr ref android.R.styleable#View_scrollbarStyle
743 * @attr ref android.R.styleable#View_scrollbars
744 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
745 * @attr ref android.R.styleable#View_scrollbarFadeDuration
746 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
747 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
748 * @attr ref android.R.styleable#View_scrollbarThumbVertical
749 * @attr ref android.R.styleable#View_scrollbarTrackVertical
750 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
751 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
752 * @attr ref android.R.styleable#View_stateListAnimator
753 * @attr ref android.R.styleable#View_transitionName
754 * @attr ref android.R.styleable#View_soundEffectsEnabled
755 * @attr ref android.R.styleable#View_tag
756 * @attr ref android.R.styleable#View_textAlignment
757 * @attr ref android.R.styleable#View_textDirection
758 * @attr ref android.R.styleable#View_transformPivotX
759 * @attr ref android.R.styleable#View_transformPivotY
760 * @attr ref android.R.styleable#View_translationX
761 * @attr ref android.R.styleable#View_translationY
762 * @attr ref android.R.styleable#View_translationZ
763 * @attr ref android.R.styleable#View_visibility
764 * @attr ref android.R.styleable#View_theme
765 *
766 * @see android.view.ViewGroup
767 */
768@UiThread
769public class View implements Drawable.Callback, KeyEvent.Callback,
770        AccessibilityEventSource {
771    private static final boolean DBG = false;
772
773    /** @hide */
774    public static boolean DEBUG_DRAW = false;
775
776    /**
777     * The logging tag used by this class with android.util.Log.
778     */
779    protected static final String VIEW_LOG_TAG = "View";
780
781    /**
782     * When set to true, apps will draw debugging information about their layouts.
783     *
784     * @hide
785     */
786    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
787
788    /**
789     * When set to true, this view will save its attribute data.
790     *
791     * @hide
792     */
793    public static boolean mDebugViewAttributes = false;
794
795    /**
796     * Used to mark a View that has no ID.
797     */
798    public static final int NO_ID = -1;
799
800    /**
801     * Last ID that is given to Views that are no part of activities.
802     *
803     * {@hide}
804     */
805    public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
806
807    /**
808     * Attribute to find the autofilled highlight
809     *
810     * @see #getAutofilledDrawable()
811     */
812    private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
813            new int[]{android.R.attr.autofilledHighlight};
814
815    /**
816     * Signals that compatibility booleans have been initialized according to
817     * target SDK versions.
818     */
819    private static boolean sCompatibilityDone = false;
820
821    /**
822     * Use the old (broken) way of building MeasureSpecs.
823     */
824    private static boolean sUseBrokenMakeMeasureSpec = false;
825
826    /**
827     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
828     */
829    static boolean sUseZeroUnspecifiedMeasureSpec = false;
830
831    /**
832     * Ignore any optimizations using the measure cache.
833     */
834    private static boolean sIgnoreMeasureCache = false;
835
836    /**
837     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
838     */
839    private static boolean sAlwaysRemeasureExactly = false;
840
841    /**
842     * Relax constraints around whether setLayoutParams() must be called after
843     * modifying the layout params.
844     */
845    private static boolean sLayoutParamsAlwaysChanged = false;
846
847    /**
848     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
849     * without throwing
850     */
851    static boolean sTextureViewIgnoresDrawableSetters = false;
852
853    /**
854     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
855     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
856     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
857     * check is implemented for backwards compatibility.
858     *
859     * {@hide}
860     */
861    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
862
863    /**
864     * Prior to N, when drag enters into child of a view that has already received an
865     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
866     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
867     * false from its event handler for these events.
868     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
869     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
870     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
871     */
872    static boolean sCascadedDragDrop;
873
874    /**
875     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
876     * to determine things like whether or not to permit item click events. We can't break
877     * apps that do this just because more things (clickable things) are now auto-focusable
878     * and they would get different results, so give old behavior to old apps.
879     */
880    static boolean sHasFocusableExcludeAutoFocusable;
881
882    /**
883     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
884     * made focusable by default. As a result, apps could (incorrectly) change the clickable
885     * setting of views off the UI thread. Now that clickable can effect the focusable state,
886     * changing the clickable attribute off the UI thread will cause an exception (since changing
887     * the focusable state checks). In order to prevent apps from crashing, we will handle this
888     * specific case and just not notify parents on new focusables resulting from marking views
889     * clickable from outside the UI thread.
890     */
891    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
892
893    /** @hide */
894    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
895    @Retention(RetentionPolicy.SOURCE)
896    public @interface Focusable {}
897
898    /**
899     * This view does not want keystrokes.
900     * <p>
901     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
902     * android:focusable}.
903     */
904    public static final int NOT_FOCUSABLE = 0x00000000;
905
906    /**
907     * This view wants keystrokes.
908     * <p>
909     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
910     * android:focusable}.
911     */
912    public static final int FOCUSABLE = 0x00000001;
913
914    /**
915     * This view determines focusability automatically. This is the default.
916     * <p>
917     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
918     * android:focusable}.
919     */
920    public static final int FOCUSABLE_AUTO = 0x00000010;
921
922    /**
923     * Mask for use with setFlags indicating bits used for focus.
924     */
925    private static final int FOCUSABLE_MASK = 0x00000011;
926
927    /**
928     * This view will adjust its padding to fit sytem windows (e.g. status bar)
929     */
930    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
931
932    /** @hide */
933    @IntDef({VISIBLE, INVISIBLE, GONE})
934    @Retention(RetentionPolicy.SOURCE)
935    public @interface Visibility {}
936
937    /**
938     * This view is visible.
939     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
940     * android:visibility}.
941     */
942    public static final int VISIBLE = 0x00000000;
943
944    /**
945     * This view is invisible, but it still takes up space for layout purposes.
946     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
947     * android:visibility}.
948     */
949    public static final int INVISIBLE = 0x00000004;
950
951    /**
952     * This view is invisible, and it doesn't take any space for layout
953     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
954     * android:visibility}.
955     */
956    public static final int GONE = 0x00000008;
957
958    /**
959     * Mask for use with setFlags indicating bits used for visibility.
960     * {@hide}
961     */
962    static final int VISIBILITY_MASK = 0x0000000C;
963
964    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
965
966    /**
967     * This view contains an email address.
968     *
969     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_EMAIL_ADDRESS}"
970     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
971     */
972    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
973
974    /**
975     * The view contains a real name.
976     *
977     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_NAME}" to
978     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
979     */
980    public static final String AUTOFILL_HINT_NAME = "name";
981
982    /**
983     * The view contains a user name.
984     *
985     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_USERNAME}" to
986     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
987     */
988    public static final String AUTOFILL_HINT_USERNAME = "username";
989
990    /**
991     * The view contains a password.
992     *
993     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PASSWORD}" to
994     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
995     */
996    public static final String AUTOFILL_HINT_PASSWORD = "password";
997
998    /**
999     * The view contains a phone number.
1000     *
1001     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PHONE}" to
1002     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1003     */
1004    public static final String AUTOFILL_HINT_PHONE = "phone";
1005
1006    /**
1007     * The view contains a postal address.
1008     *
1009     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_ADDRESS}"
1010     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1011     */
1012    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1013
1014    /**
1015     * The view contains a postal code.
1016     *
1017     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_CODE}" to
1018     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1019     */
1020    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1021
1022    /**
1023     * The view contains a credit card number.
1024     *
1025     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1026     * #AUTOFILL_HINT_CREDIT_CARD_NUMBER}" to <a href="#attr_android:autofillHint"> {@code
1027     * android:autofillHint}.
1028     */
1029    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1030
1031    /**
1032     * The view contains a credit card security code.
1033     *
1034     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1035     * #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}" to <a href="#attr_android:autofillHint"> {@code
1036     * android:autofillHint}.
1037     */
1038    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1039
1040    /**
1041     * The view contains a credit card expiration date.
1042     *
1043     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1044     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}" to <a href="#attr_android:autofillHint"> {@code
1045     * android:autofillHint}.
1046     */
1047    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1048            "creditCardExpirationDate";
1049
1050    /**
1051     * The view contains the month a credit card expires.
1052     *
1053     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1054     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}" to <a href="#attr_android:autofillHint"> {@code
1055     * android:autofillHint}.
1056     */
1057    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1058            "creditCardExpirationMonth";
1059
1060    /**
1061     * The view contains the year a credit card expires.
1062     *
1063     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1064     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}" to <a href="#attr_android:autofillHint"> {@code
1065     * android:autofillHint}.
1066     */
1067    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1068            "creditCardExpirationYear";
1069
1070    /**
1071     * The view contains the day a credit card expires.
1072     *
1073     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1074     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}" to <a href="#attr_android:autofillHint"> {@code
1075     * android:autofillHint}.
1076     */
1077    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1078
1079    /**
1080     * Hints for the autofill services that describes the content of the view.
1081     */
1082    private @Nullable String[] mAutofillHints;
1083
1084    /**
1085     * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1086     */
1087    private AutofillId mAutofillId;
1088
1089    /** @hide */
1090    @IntDef({
1091            AUTOFILL_TYPE_NONE,
1092            AUTOFILL_TYPE_TEXT,
1093            AUTOFILL_TYPE_TOGGLE,
1094            AUTOFILL_TYPE_LIST,
1095            AUTOFILL_TYPE_DATE
1096    })
1097    @Retention(RetentionPolicy.SOURCE)
1098    public @interface AutofillType {}
1099
1100    /**
1101     * Autofill type for views that cannot be autofilled.
1102     */
1103    public static final int AUTOFILL_TYPE_NONE = 0;
1104
1105    /**
1106     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1107     *
1108     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1109     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1110     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1111     */
1112    public static final int AUTOFILL_TYPE_TEXT = 1;
1113
1114    /**
1115     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1116     *
1117     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1118     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1119     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1120     */
1121    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1122
1123    /**
1124     * Autofill type for a selection list field, which is filled by an {@code int}
1125     * representing the element index inside the list (starting at {@code 0}).
1126     *
1127     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1128     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1129     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1130     *
1131     * <p>The available options in the selection list are typically provided by
1132     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1133     */
1134    public static final int AUTOFILL_TYPE_LIST = 3;
1135
1136
1137    /**
1138     * Autofill type for a field that contains a date, which is represented by a long representing
1139     * the number of milliseconds since the standard base time known as "the epoch", namely
1140     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1141     *
1142     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1143     * {@link AutofillValue#forDate(long)}, and the values passed to
1144     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1145     */
1146    public static final int AUTOFILL_TYPE_DATE = 4;
1147
1148    /** @hide */
1149    @IntDef({
1150            IMPORTANT_FOR_AUTOFILL_AUTO,
1151            IMPORTANT_FOR_AUTOFILL_YES,
1152            IMPORTANT_FOR_AUTOFILL_NO,
1153            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1154            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1155    })
1156    @Retention(RetentionPolicy.SOURCE)
1157    public @interface AutofillImportance {}
1158
1159    /**
1160     * Automatically determine whether a view is important for autofill.
1161     */
1162    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1163
1164    /**
1165     * The view is important for autofill, and its children (if any) will be traversed.
1166     */
1167    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1168
1169    /**
1170     * The view is not important for autofill, but its children (if any) will be traversed.
1171     */
1172    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1173
1174    /**
1175     * The view is important for autofill, but its children (if any) will not be traversed.
1176     */
1177    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1178
1179    /**
1180     * The view is not important for autofill, and its children (if any) will not be traversed.
1181     */
1182    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1183
1184    /** @hide */
1185    @IntDef(
1186            flag = true,
1187            value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS})
1188    @Retention(RetentionPolicy.SOURCE)
1189    public @interface AutofillFlags {}
1190
1191    /**
1192     * Flag requesting you to add views not-important for autofill to the assist data.
1193     */
1194    public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1195
1196    /**
1197     * This view is enabled. Interpretation varies by subclass.
1198     * Use with ENABLED_MASK when calling setFlags.
1199     * {@hide}
1200     */
1201    static final int ENABLED = 0x00000000;
1202
1203    /**
1204     * This view is disabled. Interpretation varies by subclass.
1205     * Use with ENABLED_MASK when calling setFlags.
1206     * {@hide}
1207     */
1208    static final int DISABLED = 0x00000020;
1209
1210   /**
1211    * Mask for use with setFlags indicating bits used for indicating whether
1212    * this view is enabled
1213    * {@hide}
1214    */
1215    static final int ENABLED_MASK = 0x00000020;
1216
1217    /**
1218     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1219     * called and further optimizations will be performed. It is okay to have
1220     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1221     * {@hide}
1222     */
1223    static final int WILL_NOT_DRAW = 0x00000080;
1224
1225    /**
1226     * Mask for use with setFlags indicating bits used for indicating whether
1227     * this view is will draw
1228     * {@hide}
1229     */
1230    static final int DRAW_MASK = 0x00000080;
1231
1232    /**
1233     * <p>This view doesn't show scrollbars.</p>
1234     * {@hide}
1235     */
1236    static final int SCROLLBARS_NONE = 0x00000000;
1237
1238    /**
1239     * <p>This view shows horizontal scrollbars.</p>
1240     * {@hide}
1241     */
1242    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1243
1244    /**
1245     * <p>This view shows vertical scrollbars.</p>
1246     * {@hide}
1247     */
1248    static final int SCROLLBARS_VERTICAL = 0x00000200;
1249
1250    /**
1251     * <p>Mask for use with setFlags indicating bits used for indicating which
1252     * scrollbars are enabled.</p>
1253     * {@hide}
1254     */
1255    static final int SCROLLBARS_MASK = 0x00000300;
1256
1257    /**
1258     * Indicates that the view should filter touches when its window is obscured.
1259     * Refer to the class comments for more information about this security feature.
1260     * {@hide}
1261     */
1262    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1263
1264    /**
1265     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1266     * that they are optional and should be skipped if the window has
1267     * requested system UI flags that ignore those insets for layout.
1268     */
1269    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1270
1271    /**
1272     * <p>This view doesn't show fading edges.</p>
1273     * {@hide}
1274     */
1275    static final int FADING_EDGE_NONE = 0x00000000;
1276
1277    /**
1278     * <p>This view shows horizontal fading edges.</p>
1279     * {@hide}
1280     */
1281    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1282
1283    /**
1284     * <p>This view shows vertical fading edges.</p>
1285     * {@hide}
1286     */
1287    static final int FADING_EDGE_VERTICAL = 0x00002000;
1288
1289    /**
1290     * <p>Mask for use with setFlags indicating bits used for indicating which
1291     * fading edges are enabled.</p>
1292     * {@hide}
1293     */
1294    static final int FADING_EDGE_MASK = 0x00003000;
1295
1296    /**
1297     * <p>Indicates this view can be clicked. When clickable, a View reacts
1298     * to clicks by notifying the OnClickListener.<p>
1299     * {@hide}
1300     */
1301    static final int CLICKABLE = 0x00004000;
1302
1303    /**
1304     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1305     * {@hide}
1306     */
1307    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1308
1309    /**
1310     * <p>Indicates that no icicle should be saved for this view.<p>
1311     * {@hide}
1312     */
1313    static final int SAVE_DISABLED = 0x000010000;
1314
1315    /**
1316     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1317     * property.</p>
1318     * {@hide}
1319     */
1320    static final int SAVE_DISABLED_MASK = 0x000010000;
1321
1322    /**
1323     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1324     * {@hide}
1325     */
1326    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1327
1328    /**
1329     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1330     * {@hide}
1331     */
1332    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1333
1334    /** @hide */
1335    @Retention(RetentionPolicy.SOURCE)
1336    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1337    public @interface DrawingCacheQuality {}
1338
1339    /**
1340     * <p>Enables low quality mode for the drawing cache.</p>
1341     */
1342    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1343
1344    /**
1345     * <p>Enables high quality mode for the drawing cache.</p>
1346     */
1347    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1348
1349    /**
1350     * <p>Enables automatic quality mode for the drawing cache.</p>
1351     */
1352    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1353
1354    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1355            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1356    };
1357
1358    /**
1359     * <p>Mask for use with setFlags indicating bits used for the cache
1360     * quality property.</p>
1361     * {@hide}
1362     */
1363    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1364
1365    /**
1366     * <p>
1367     * Indicates this view can be long clicked. When long clickable, a View
1368     * reacts to long clicks by notifying the OnLongClickListener or showing a
1369     * context menu.
1370     * </p>
1371     * {@hide}
1372     */
1373    static final int LONG_CLICKABLE = 0x00200000;
1374
1375    /**
1376     * <p>Indicates that this view gets its drawable states from its direct parent
1377     * and ignores its original internal states.</p>
1378     *
1379     * @hide
1380     */
1381    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1382
1383    /**
1384     * <p>
1385     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1386     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1387     * OnContextClickListener.
1388     * </p>
1389     * {@hide}
1390     */
1391    static final int CONTEXT_CLICKABLE = 0x00800000;
1392
1393
1394    /** @hide */
1395    @IntDef({
1396        SCROLLBARS_INSIDE_OVERLAY,
1397        SCROLLBARS_INSIDE_INSET,
1398        SCROLLBARS_OUTSIDE_OVERLAY,
1399        SCROLLBARS_OUTSIDE_INSET
1400    })
1401    @Retention(RetentionPolicy.SOURCE)
1402    public @interface ScrollBarStyle {}
1403
1404    /**
1405     * The scrollbar style to display the scrollbars inside the content area,
1406     * without increasing the padding. The scrollbars will be overlaid with
1407     * translucency on the view's content.
1408     */
1409    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1410
1411    /**
1412     * The scrollbar style to display the scrollbars inside the padded area,
1413     * increasing the padding of the view. The scrollbars will not overlap the
1414     * content area of the view.
1415     */
1416    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1417
1418    /**
1419     * The scrollbar style to display the scrollbars at the edge of the view,
1420     * without increasing the padding. The scrollbars will be overlaid with
1421     * translucency.
1422     */
1423    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1424
1425    /**
1426     * The scrollbar style to display the scrollbars at the edge of the view,
1427     * increasing the padding of the view. The scrollbars will only overlap the
1428     * background, if any.
1429     */
1430    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1431
1432    /**
1433     * Mask to check if the scrollbar style is overlay or inset.
1434     * {@hide}
1435     */
1436    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1437
1438    /**
1439     * Mask to check if the scrollbar style is inside or outside.
1440     * {@hide}
1441     */
1442    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1443
1444    /**
1445     * Mask for scrollbar style.
1446     * {@hide}
1447     */
1448    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1449
1450    /**
1451     * View flag indicating that the screen should remain on while the
1452     * window containing this view is visible to the user.  This effectively
1453     * takes care of automatically setting the WindowManager's
1454     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1455     */
1456    public static final int KEEP_SCREEN_ON = 0x04000000;
1457
1458    /**
1459     * View flag indicating whether this view should have sound effects enabled
1460     * for events such as clicking and touching.
1461     */
1462    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1463
1464    /**
1465     * View flag indicating whether this view should have haptic feedback
1466     * enabled for events such as long presses.
1467     */
1468    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1469
1470    /**
1471     * <p>Indicates that the view hierarchy should stop saving state when
1472     * it reaches this view.  If state saving is initiated immediately at
1473     * the view, it will be allowed.
1474     * {@hide}
1475     */
1476    static final int PARENT_SAVE_DISABLED = 0x20000000;
1477
1478    /**
1479     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1480     * {@hide}
1481     */
1482    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1483
1484    private static Paint sDebugPaint;
1485
1486    /**
1487     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1488     * {@hide}
1489     */
1490    static final int TOOLTIP = 0x40000000;
1491
1492    /** @hide */
1493    @IntDef(flag = true,
1494            value = {
1495                FOCUSABLES_ALL,
1496                FOCUSABLES_TOUCH_MODE
1497            })
1498    @Retention(RetentionPolicy.SOURCE)
1499    public @interface FocusableMode {}
1500
1501    /**
1502     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1503     * should add all focusable Views regardless if they are focusable in touch mode.
1504     */
1505    public static final int FOCUSABLES_ALL = 0x00000000;
1506
1507    /**
1508     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1509     * should add only Views focusable in touch mode.
1510     */
1511    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1512
1513    /** @hide */
1514    @IntDef({
1515            FOCUS_BACKWARD,
1516            FOCUS_FORWARD,
1517            FOCUS_LEFT,
1518            FOCUS_UP,
1519            FOCUS_RIGHT,
1520            FOCUS_DOWN
1521    })
1522    @Retention(RetentionPolicy.SOURCE)
1523    public @interface FocusDirection {}
1524
1525    /** @hide */
1526    @IntDef({
1527            FOCUS_LEFT,
1528            FOCUS_UP,
1529            FOCUS_RIGHT,
1530            FOCUS_DOWN
1531    })
1532    @Retention(RetentionPolicy.SOURCE)
1533    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1534
1535    /**
1536     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1537     * item.
1538     */
1539    public static final int FOCUS_BACKWARD = 0x00000001;
1540
1541    /**
1542     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1543     * item.
1544     */
1545    public static final int FOCUS_FORWARD = 0x00000002;
1546
1547    /**
1548     * Use with {@link #focusSearch(int)}. Move focus to the left.
1549     */
1550    public static final int FOCUS_LEFT = 0x00000011;
1551
1552    /**
1553     * Use with {@link #focusSearch(int)}. Move focus up.
1554     */
1555    public static final int FOCUS_UP = 0x00000021;
1556
1557    /**
1558     * Use with {@link #focusSearch(int)}. Move focus to the right.
1559     */
1560    public static final int FOCUS_RIGHT = 0x00000042;
1561
1562    /**
1563     * Use with {@link #focusSearch(int)}. Move focus down.
1564     */
1565    public static final int FOCUS_DOWN = 0x00000082;
1566
1567    /**
1568     * Bits of {@link #getMeasuredWidthAndState()} and
1569     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1570     */
1571    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1572
1573    /**
1574     * Bits of {@link #getMeasuredWidthAndState()} and
1575     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1576     */
1577    public static final int MEASURED_STATE_MASK = 0xff000000;
1578
1579    /**
1580     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1581     * for functions that combine both width and height into a single int,
1582     * such as {@link #getMeasuredState()} and the childState argument of
1583     * {@link #resolveSizeAndState(int, int, int)}.
1584     */
1585    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1586
1587    /**
1588     * Bit of {@link #getMeasuredWidthAndState()} and
1589     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1590     * is smaller that the space the view would like to have.
1591     */
1592    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1593
1594    /**
1595     * Base View state sets
1596     */
1597    // Singles
1598    /**
1599     * Indicates the view has no states set. States are used with
1600     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1601     * view depending on its state.
1602     *
1603     * @see android.graphics.drawable.Drawable
1604     * @see #getDrawableState()
1605     */
1606    protected static final int[] EMPTY_STATE_SET;
1607    /**
1608     * Indicates the view is enabled. States are used with
1609     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1610     * view depending on its state.
1611     *
1612     * @see android.graphics.drawable.Drawable
1613     * @see #getDrawableState()
1614     */
1615    protected static final int[] ENABLED_STATE_SET;
1616    /**
1617     * Indicates the view is focused. States are used with
1618     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1619     * view depending on its state.
1620     *
1621     * @see android.graphics.drawable.Drawable
1622     * @see #getDrawableState()
1623     */
1624    protected static final int[] FOCUSED_STATE_SET;
1625    /**
1626     * Indicates the view is selected. States are used with
1627     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1628     * view depending on its state.
1629     *
1630     * @see android.graphics.drawable.Drawable
1631     * @see #getDrawableState()
1632     */
1633    protected static final int[] SELECTED_STATE_SET;
1634    /**
1635     * Indicates the view is pressed. States are used with
1636     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1637     * view depending on its state.
1638     *
1639     * @see android.graphics.drawable.Drawable
1640     * @see #getDrawableState()
1641     */
1642    protected static final int[] PRESSED_STATE_SET;
1643    /**
1644     * Indicates the view's window has focus. States are used with
1645     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1646     * view depending on its state.
1647     *
1648     * @see android.graphics.drawable.Drawable
1649     * @see #getDrawableState()
1650     */
1651    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1652    // Doubles
1653    /**
1654     * Indicates the view is enabled and has the focus.
1655     *
1656     * @see #ENABLED_STATE_SET
1657     * @see #FOCUSED_STATE_SET
1658     */
1659    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1660    /**
1661     * Indicates the view is enabled and selected.
1662     *
1663     * @see #ENABLED_STATE_SET
1664     * @see #SELECTED_STATE_SET
1665     */
1666    protected static final int[] ENABLED_SELECTED_STATE_SET;
1667    /**
1668     * Indicates the view is enabled and that its window has focus.
1669     *
1670     * @see #ENABLED_STATE_SET
1671     * @see #WINDOW_FOCUSED_STATE_SET
1672     */
1673    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1674    /**
1675     * Indicates the view is focused and selected.
1676     *
1677     * @see #FOCUSED_STATE_SET
1678     * @see #SELECTED_STATE_SET
1679     */
1680    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1681    /**
1682     * Indicates the view has the focus and that its window has the focus.
1683     *
1684     * @see #FOCUSED_STATE_SET
1685     * @see #WINDOW_FOCUSED_STATE_SET
1686     */
1687    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1688    /**
1689     * Indicates the view is selected and that its window has the focus.
1690     *
1691     * @see #SELECTED_STATE_SET
1692     * @see #WINDOW_FOCUSED_STATE_SET
1693     */
1694    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1695    // Triples
1696    /**
1697     * Indicates the view is enabled, focused and selected.
1698     *
1699     * @see #ENABLED_STATE_SET
1700     * @see #FOCUSED_STATE_SET
1701     * @see #SELECTED_STATE_SET
1702     */
1703    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1704    /**
1705     * Indicates the view is enabled, focused and its window has the focus.
1706     *
1707     * @see #ENABLED_STATE_SET
1708     * @see #FOCUSED_STATE_SET
1709     * @see #WINDOW_FOCUSED_STATE_SET
1710     */
1711    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1712    /**
1713     * Indicates the view is enabled, selected and its window has the focus.
1714     *
1715     * @see #ENABLED_STATE_SET
1716     * @see #SELECTED_STATE_SET
1717     * @see #WINDOW_FOCUSED_STATE_SET
1718     */
1719    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1720    /**
1721     * Indicates the view is focused, selected and its window has the focus.
1722     *
1723     * @see #FOCUSED_STATE_SET
1724     * @see #SELECTED_STATE_SET
1725     * @see #WINDOW_FOCUSED_STATE_SET
1726     */
1727    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1728    /**
1729     * Indicates the view is enabled, focused, selected and its window
1730     * has the focus.
1731     *
1732     * @see #ENABLED_STATE_SET
1733     * @see #FOCUSED_STATE_SET
1734     * @see #SELECTED_STATE_SET
1735     * @see #WINDOW_FOCUSED_STATE_SET
1736     */
1737    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1738    /**
1739     * Indicates the view is pressed and its window has the focus.
1740     *
1741     * @see #PRESSED_STATE_SET
1742     * @see #WINDOW_FOCUSED_STATE_SET
1743     */
1744    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1745    /**
1746     * Indicates the view is pressed and selected.
1747     *
1748     * @see #PRESSED_STATE_SET
1749     * @see #SELECTED_STATE_SET
1750     */
1751    protected static final int[] PRESSED_SELECTED_STATE_SET;
1752    /**
1753     * Indicates the view is pressed, selected and its window has the focus.
1754     *
1755     * @see #PRESSED_STATE_SET
1756     * @see #SELECTED_STATE_SET
1757     * @see #WINDOW_FOCUSED_STATE_SET
1758     */
1759    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1760    /**
1761     * Indicates the view is pressed and focused.
1762     *
1763     * @see #PRESSED_STATE_SET
1764     * @see #FOCUSED_STATE_SET
1765     */
1766    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1767    /**
1768     * Indicates the view is pressed, focused and its window has the focus.
1769     *
1770     * @see #PRESSED_STATE_SET
1771     * @see #FOCUSED_STATE_SET
1772     * @see #WINDOW_FOCUSED_STATE_SET
1773     */
1774    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1775    /**
1776     * Indicates the view is pressed, focused and selected.
1777     *
1778     * @see #PRESSED_STATE_SET
1779     * @see #SELECTED_STATE_SET
1780     * @see #FOCUSED_STATE_SET
1781     */
1782    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1783    /**
1784     * Indicates the view is pressed, focused, selected and its window has the focus.
1785     *
1786     * @see #PRESSED_STATE_SET
1787     * @see #FOCUSED_STATE_SET
1788     * @see #SELECTED_STATE_SET
1789     * @see #WINDOW_FOCUSED_STATE_SET
1790     */
1791    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1792    /**
1793     * Indicates the view is pressed and enabled.
1794     *
1795     * @see #PRESSED_STATE_SET
1796     * @see #ENABLED_STATE_SET
1797     */
1798    protected static final int[] PRESSED_ENABLED_STATE_SET;
1799    /**
1800     * Indicates the view is pressed, enabled and its window has the focus.
1801     *
1802     * @see #PRESSED_STATE_SET
1803     * @see #ENABLED_STATE_SET
1804     * @see #WINDOW_FOCUSED_STATE_SET
1805     */
1806    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1807    /**
1808     * Indicates the view is pressed, enabled and selected.
1809     *
1810     * @see #PRESSED_STATE_SET
1811     * @see #ENABLED_STATE_SET
1812     * @see #SELECTED_STATE_SET
1813     */
1814    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1815    /**
1816     * Indicates the view is pressed, enabled, selected and its window has the
1817     * focus.
1818     *
1819     * @see #PRESSED_STATE_SET
1820     * @see #ENABLED_STATE_SET
1821     * @see #SELECTED_STATE_SET
1822     * @see #WINDOW_FOCUSED_STATE_SET
1823     */
1824    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1825    /**
1826     * Indicates the view is pressed, enabled and focused.
1827     *
1828     * @see #PRESSED_STATE_SET
1829     * @see #ENABLED_STATE_SET
1830     * @see #FOCUSED_STATE_SET
1831     */
1832    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1833    /**
1834     * Indicates the view is pressed, enabled, focused and its window has the
1835     * focus.
1836     *
1837     * @see #PRESSED_STATE_SET
1838     * @see #ENABLED_STATE_SET
1839     * @see #FOCUSED_STATE_SET
1840     * @see #WINDOW_FOCUSED_STATE_SET
1841     */
1842    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1843    /**
1844     * Indicates the view is pressed, enabled, focused and selected.
1845     *
1846     * @see #PRESSED_STATE_SET
1847     * @see #ENABLED_STATE_SET
1848     * @see #SELECTED_STATE_SET
1849     * @see #FOCUSED_STATE_SET
1850     */
1851    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1852    /**
1853     * Indicates the view is pressed, enabled, focused, selected and its window
1854     * has the focus.
1855     *
1856     * @see #PRESSED_STATE_SET
1857     * @see #ENABLED_STATE_SET
1858     * @see #SELECTED_STATE_SET
1859     * @see #FOCUSED_STATE_SET
1860     * @see #WINDOW_FOCUSED_STATE_SET
1861     */
1862    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1863
1864    static {
1865        EMPTY_STATE_SET = StateSet.get(0);
1866
1867        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1868
1869        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1870        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1871                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1872
1873        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1874        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1875                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1876        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1877                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1878        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1879                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1880                        | StateSet.VIEW_STATE_FOCUSED);
1881
1882        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1883        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1884                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1885        ENABLED_SELECTED_STATE_SET = StateSet.get(
1886                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1887        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1888                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1889                        | StateSet.VIEW_STATE_ENABLED);
1890        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1891                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1892        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1893                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1894                        | StateSet.VIEW_STATE_ENABLED);
1895        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1896                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1897                        | StateSet.VIEW_STATE_ENABLED);
1898        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1899                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1900                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1901
1902        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1903        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1904                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1905        PRESSED_SELECTED_STATE_SET = StateSet.get(
1906                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1907        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1908                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1909                        | StateSet.VIEW_STATE_PRESSED);
1910        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1911                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1912        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1913                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1914                        | StateSet.VIEW_STATE_PRESSED);
1915        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1916                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1917                        | StateSet.VIEW_STATE_PRESSED);
1918        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1919                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1920                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1921        PRESSED_ENABLED_STATE_SET = StateSet.get(
1922                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1923        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1924                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1925                        | StateSet.VIEW_STATE_PRESSED);
1926        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1927                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1928                        | StateSet.VIEW_STATE_PRESSED);
1929        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1930                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1931                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1932        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1933                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1934                        | StateSet.VIEW_STATE_PRESSED);
1935        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1936                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1937                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1938        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1939                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1940                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1941        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1942                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1943                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1944                        | StateSet.VIEW_STATE_PRESSED);
1945    }
1946
1947    /**
1948     * Accessibility event types that are dispatched for text population.
1949     */
1950    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1951            AccessibilityEvent.TYPE_VIEW_CLICKED
1952            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1953            | AccessibilityEvent.TYPE_VIEW_SELECTED
1954            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1955            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1956            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1957            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1958            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1959            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1960            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1961            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1962
1963    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1964
1965    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1966
1967    /**
1968     * Temporary Rect currently for use in setBackground().  This will probably
1969     * be extended in the future to hold our own class with more than just
1970     * a Rect. :)
1971     */
1972    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1973
1974    /**
1975     * Map used to store views' tags.
1976     */
1977    private SparseArray<Object> mKeyedTags;
1978
1979    /**
1980     * The animation currently associated with this view.
1981     * @hide
1982     */
1983    protected Animation mCurrentAnimation = null;
1984
1985    /**
1986     * Width as measured during measure pass.
1987     * {@hide}
1988     */
1989    @ViewDebug.ExportedProperty(category = "measurement")
1990    int mMeasuredWidth;
1991
1992    /**
1993     * Height as measured during measure pass.
1994     * {@hide}
1995     */
1996    @ViewDebug.ExportedProperty(category = "measurement")
1997    int mMeasuredHeight;
1998
1999    /**
2000     * Flag to indicate that this view was marked INVALIDATED, or had its display list
2001     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2002     * its display list. This flag, used only when hw accelerated, allows us to clear the
2003     * flag while retaining this information until it's needed (at getDisplayList() time and
2004     * in drawChild(), when we decide to draw a view's children's display lists into our own).
2005     *
2006     * {@hide}
2007     */
2008    boolean mRecreateDisplayList = false;
2009
2010    /**
2011     * The view's identifier.
2012     * {@hide}
2013     *
2014     * @see #setId(int)
2015     * @see #getId()
2016     */
2017    @IdRes
2018    @ViewDebug.ExportedProperty(resolveId = true)
2019    int mID = NO_ID;
2020
2021    /** The ID of this view for accessibility and autofill purposes.
2022     * <ul>
2023     *     <li>== {@link #NO_ID}: ID has not been assigned yet
2024     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
2025     *                                                  unique in the process. This might change
2026     *                                                  over activity lifecycle events.
2027     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
2028     *                                                  unique in the activity. This stays the same
2029     *                                                  over activity lifecycle events.
2030     */
2031    private int mAccessibilityViewId = NO_ID;
2032
2033    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2034
2035    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2036
2037    /**
2038     * The view's tag.
2039     * {@hide}
2040     *
2041     * @see #setTag(Object)
2042     * @see #getTag()
2043     */
2044    protected Object mTag = null;
2045
2046    // for mPrivateFlags:
2047    /** {@hide} */
2048    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2049    /** {@hide} */
2050    static final int PFLAG_FOCUSED                     = 0x00000002;
2051    /** {@hide} */
2052    static final int PFLAG_SELECTED                    = 0x00000004;
2053    /** {@hide} */
2054    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2055    /** {@hide} */
2056    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2057    /** {@hide} */
2058    static final int PFLAG_DRAWN                       = 0x00000020;
2059    /**
2060     * When this flag is set, this view is running an animation on behalf of its
2061     * children and should therefore not cancel invalidate requests, even if they
2062     * lie outside of this view's bounds.
2063     *
2064     * {@hide}
2065     */
2066    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2067    /** {@hide} */
2068    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2069    /** {@hide} */
2070    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2071    /** {@hide} */
2072    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2073    /** {@hide} */
2074    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2075    /** {@hide} */
2076    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2077    /** {@hide} */
2078    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2079
2080    private static final int PFLAG_PRESSED             = 0x00004000;
2081
2082    /** {@hide} */
2083    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2084    /**
2085     * Flag used to indicate that this view should be drawn once more (and only once
2086     * more) after its animation has completed.
2087     * {@hide}
2088     */
2089    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2090
2091    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2092
2093    /**
2094     * Indicates that the View returned true when onSetAlpha() was called and that
2095     * the alpha must be restored.
2096     * {@hide}
2097     */
2098    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2099
2100    /**
2101     * Set by {@link #setScrollContainer(boolean)}.
2102     */
2103    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2104
2105    /**
2106     * Set by {@link #setScrollContainer(boolean)}.
2107     */
2108    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2109
2110    /**
2111     * View flag indicating whether this view was invalidated (fully or partially.)
2112     *
2113     * @hide
2114     */
2115    static final int PFLAG_DIRTY                       = 0x00200000;
2116
2117    /**
2118     * View flag indicating whether this view was invalidated by an opaque
2119     * invalidate request.
2120     *
2121     * @hide
2122     */
2123    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2124
2125    /**
2126     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2127     *
2128     * @hide
2129     */
2130    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2131
2132    /**
2133     * Indicates whether the background is opaque.
2134     *
2135     * @hide
2136     */
2137    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2138
2139    /**
2140     * Indicates whether the scrollbars are opaque.
2141     *
2142     * @hide
2143     */
2144    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2145
2146    /**
2147     * Indicates whether the view is opaque.
2148     *
2149     * @hide
2150     */
2151    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2152
2153    /**
2154     * Indicates a prepressed state;
2155     * the short time between ACTION_DOWN and recognizing
2156     * a 'real' press. Prepressed is used to recognize quick taps
2157     * even when they are shorter than ViewConfiguration.getTapTimeout().
2158     *
2159     * @hide
2160     */
2161    private static final int PFLAG_PREPRESSED          = 0x02000000;
2162
2163    /**
2164     * Indicates whether the view is temporarily detached.
2165     *
2166     * @hide
2167     */
2168    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2169
2170    /**
2171     * Indicates that we should awaken scroll bars once attached
2172     *
2173     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2174     * during window attachment and it is no longer needed. Feel free to repurpose it.
2175     *
2176     * @hide
2177     */
2178    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2179
2180    /**
2181     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2182     * @hide
2183     */
2184    private static final int PFLAG_HOVERED             = 0x10000000;
2185
2186    /**
2187     * no longer needed, should be reused
2188     */
2189    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2190
2191    /** {@hide} */
2192    static final int PFLAG_ACTIVATED                   = 0x40000000;
2193
2194    /**
2195     * Indicates that this view was specifically invalidated, not just dirtied because some
2196     * child view was invalidated. The flag is used to determine when we need to recreate
2197     * a view's display list (as opposed to just returning a reference to its existing
2198     * display list).
2199     *
2200     * @hide
2201     */
2202    static final int PFLAG_INVALIDATED                 = 0x80000000;
2203
2204    /**
2205     * Masks for mPrivateFlags2, as generated by dumpFlags():
2206     *
2207     * |-------|-------|-------|-------|
2208     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2209     *                                1  PFLAG2_DRAG_HOVERED
2210     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2211     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2212     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2213     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2214     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2215     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2216     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2217     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2218     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2219     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2220     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2221     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2222     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2223     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2224     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2225     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2226     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2227     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2228     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2229     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2230     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2231     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2232     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2233     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2234     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2235     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2236     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2237     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2238     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2239     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2240     *    1                              PFLAG2_PADDING_RESOLVED
2241     *   1                               PFLAG2_DRAWABLE_RESOLVED
2242     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2243     * |-------|-------|-------|-------|
2244     */
2245
2246    /**
2247     * Indicates that this view has reported that it can accept the current drag's content.
2248     * Cleared when the drag operation concludes.
2249     * @hide
2250     */
2251    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2252
2253    /**
2254     * Indicates that this view is currently directly under the drag location in a
2255     * drag-and-drop operation involving content that it can accept.  Cleared when
2256     * the drag exits the view, or when the drag operation concludes.
2257     * @hide
2258     */
2259    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2260
2261    /** @hide */
2262    @IntDef({
2263        LAYOUT_DIRECTION_LTR,
2264        LAYOUT_DIRECTION_RTL,
2265        LAYOUT_DIRECTION_INHERIT,
2266        LAYOUT_DIRECTION_LOCALE
2267    })
2268    @Retention(RetentionPolicy.SOURCE)
2269    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2270    public @interface LayoutDir {}
2271
2272    /** @hide */
2273    @IntDef({
2274        LAYOUT_DIRECTION_LTR,
2275        LAYOUT_DIRECTION_RTL
2276    })
2277    @Retention(RetentionPolicy.SOURCE)
2278    public @interface ResolvedLayoutDir {}
2279
2280    /**
2281     * A flag to indicate that the layout direction of this view has not been defined yet.
2282     * @hide
2283     */
2284    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2285
2286    /**
2287     * Horizontal layout direction of this view is from Left to Right.
2288     * Use with {@link #setLayoutDirection}.
2289     */
2290    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2291
2292    /**
2293     * Horizontal layout direction of this view is from Right to Left.
2294     * Use with {@link #setLayoutDirection}.
2295     */
2296    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2297
2298    /**
2299     * Horizontal layout direction of this view is inherited from its parent.
2300     * Use with {@link #setLayoutDirection}.
2301     */
2302    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2303
2304    /**
2305     * Horizontal layout direction of this view is from deduced from the default language
2306     * script for the locale. Use with {@link #setLayoutDirection}.
2307     */
2308    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2309
2310    /**
2311     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2312     * @hide
2313     */
2314    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2315
2316    /**
2317     * Mask for use with private flags indicating bits used for horizontal layout direction.
2318     * @hide
2319     */
2320    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2321
2322    /**
2323     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2324     * right-to-left direction.
2325     * @hide
2326     */
2327    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2328
2329    /**
2330     * Indicates whether the view horizontal layout direction has been resolved.
2331     * @hide
2332     */
2333    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2334
2335    /**
2336     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2337     * @hide
2338     */
2339    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2340            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2341
2342    /*
2343     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2344     * flag value.
2345     * @hide
2346     */
2347    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2348            LAYOUT_DIRECTION_LTR,
2349            LAYOUT_DIRECTION_RTL,
2350            LAYOUT_DIRECTION_INHERIT,
2351            LAYOUT_DIRECTION_LOCALE
2352    };
2353
2354    /**
2355     * Default horizontal layout direction.
2356     */
2357    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2358
2359    /**
2360     * Default horizontal layout direction.
2361     * @hide
2362     */
2363    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2364
2365    /**
2366     * Text direction is inherited through {@link ViewGroup}
2367     */
2368    public static final int TEXT_DIRECTION_INHERIT = 0;
2369
2370    /**
2371     * Text direction is using "first strong algorithm". The first strong directional character
2372     * determines the paragraph direction. If there is no strong directional character, the
2373     * paragraph direction is the view's resolved layout direction.
2374     */
2375    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2376
2377    /**
2378     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2379     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2380     * If there are neither, the paragraph direction is the view's resolved layout direction.
2381     */
2382    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2383
2384    /**
2385     * Text direction is forced to LTR.
2386     */
2387    public static final int TEXT_DIRECTION_LTR = 3;
2388
2389    /**
2390     * Text direction is forced to RTL.
2391     */
2392    public static final int TEXT_DIRECTION_RTL = 4;
2393
2394    /**
2395     * Text direction is coming from the system Locale.
2396     */
2397    public static final int TEXT_DIRECTION_LOCALE = 5;
2398
2399    /**
2400     * Text direction is using "first strong algorithm". The first strong directional character
2401     * determines the paragraph direction. If there is no strong directional character, the
2402     * paragraph direction is LTR.
2403     */
2404    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2405
2406    /**
2407     * Text direction is using "first strong algorithm". The first strong directional character
2408     * determines the paragraph direction. If there is no strong directional character, the
2409     * paragraph direction is RTL.
2410     */
2411    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2412
2413    /**
2414     * Default text direction is inherited
2415     */
2416    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2417
2418    /**
2419     * Default resolved text direction
2420     * @hide
2421     */
2422    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2423
2424    /**
2425     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2426     * @hide
2427     */
2428    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2429
2430    /**
2431     * Mask for use with private flags indicating bits used for text direction.
2432     * @hide
2433     */
2434    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2435            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2436
2437    /**
2438     * Array of text direction flags for mapping attribute "textDirection" to correct
2439     * flag value.
2440     * @hide
2441     */
2442    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2443            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2444            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2445            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2446            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2447            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2448            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2449            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2450            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2451    };
2452
2453    /**
2454     * Indicates whether the view text direction has been resolved.
2455     * @hide
2456     */
2457    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2458            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2459
2460    /**
2461     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2462     * @hide
2463     */
2464    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2465
2466    /**
2467     * Mask for use with private flags indicating bits used for resolved text direction.
2468     * @hide
2469     */
2470    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2471            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2472
2473    /**
2474     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2475     * @hide
2476     */
2477    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2478            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2479
2480    /** @hide */
2481    @IntDef({
2482        TEXT_ALIGNMENT_INHERIT,
2483        TEXT_ALIGNMENT_GRAVITY,
2484        TEXT_ALIGNMENT_CENTER,
2485        TEXT_ALIGNMENT_TEXT_START,
2486        TEXT_ALIGNMENT_TEXT_END,
2487        TEXT_ALIGNMENT_VIEW_START,
2488        TEXT_ALIGNMENT_VIEW_END
2489    })
2490    @Retention(RetentionPolicy.SOURCE)
2491    public @interface TextAlignment {}
2492
2493    /**
2494     * Default text alignment. The text alignment of this View is inherited from its parent.
2495     * Use with {@link #setTextAlignment(int)}
2496     */
2497    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2498
2499    /**
2500     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2501     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2502     *
2503     * Use with {@link #setTextAlignment(int)}
2504     */
2505    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2506
2507    /**
2508     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2509     *
2510     * Use with {@link #setTextAlignment(int)}
2511     */
2512    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2513
2514    /**
2515     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2516     *
2517     * Use with {@link #setTextAlignment(int)}
2518     */
2519    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2520
2521    /**
2522     * Center the paragraph, e.g. ALIGN_CENTER.
2523     *
2524     * Use with {@link #setTextAlignment(int)}
2525     */
2526    public static final int TEXT_ALIGNMENT_CENTER = 4;
2527
2528    /**
2529     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2530     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2531     *
2532     * Use with {@link #setTextAlignment(int)}
2533     */
2534    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2535
2536    /**
2537     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2538     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2539     *
2540     * Use with {@link #setTextAlignment(int)}
2541     */
2542    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2543
2544    /**
2545     * Default text alignment is inherited
2546     */
2547    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2548
2549    /**
2550     * Default resolved text alignment
2551     * @hide
2552     */
2553    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2554
2555    /**
2556      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2557      * @hide
2558      */
2559    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2560
2561    /**
2562      * Mask for use with private flags indicating bits used for text alignment.
2563      * @hide
2564      */
2565    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2566
2567    /**
2568     * Array of text direction flags for mapping attribute "textAlignment" to correct
2569     * flag value.
2570     * @hide
2571     */
2572    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2573            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2574            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2575            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2576            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2577            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2578            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2579            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2580    };
2581
2582    /**
2583     * Indicates whether the view text alignment has been resolved.
2584     * @hide
2585     */
2586    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2587
2588    /**
2589     * Bit shift to get the resolved text alignment.
2590     * @hide
2591     */
2592    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2593
2594    /**
2595     * Mask for use with private flags indicating bits used for text alignment.
2596     * @hide
2597     */
2598    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2599            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2600
2601    /**
2602     * Indicates whether if the view text alignment has been resolved to gravity
2603     */
2604    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2605            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2606
2607    // Accessiblity constants for mPrivateFlags2
2608
2609    /**
2610     * Shift for the bits in {@link #mPrivateFlags2} related to the
2611     * "importantForAccessibility" attribute.
2612     */
2613    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2614
2615    /**
2616     * Automatically determine whether a view is important for accessibility.
2617     */
2618    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2619
2620    /**
2621     * The view is important for accessibility.
2622     */
2623    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2624
2625    /**
2626     * The view is not important for accessibility.
2627     */
2628    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2629
2630    /**
2631     * The view is not important for accessibility, nor are any of its
2632     * descendant views.
2633     */
2634    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2635
2636    /**
2637     * The default whether the view is important for accessibility.
2638     */
2639    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2640
2641    /**
2642     * Mask for obtaining the bits which specify how to determine
2643     * whether a view is important for accessibility.
2644     */
2645    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2646        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2647        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2648        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2649
2650    /**
2651     * Shift for the bits in {@link #mPrivateFlags2} related to the
2652     * "accessibilityLiveRegion" attribute.
2653     */
2654    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2655
2656    /**
2657     * Live region mode specifying that accessibility services should not
2658     * automatically announce changes to this view. This is the default live
2659     * region mode for most views.
2660     * <p>
2661     * Use with {@link #setAccessibilityLiveRegion(int)}.
2662     */
2663    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2664
2665    /**
2666     * Live region mode specifying that accessibility services should announce
2667     * changes to this view.
2668     * <p>
2669     * Use with {@link #setAccessibilityLiveRegion(int)}.
2670     */
2671    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2672
2673    /**
2674     * Live region mode specifying that accessibility services should interrupt
2675     * ongoing speech to immediately announce changes to this view.
2676     * <p>
2677     * Use with {@link #setAccessibilityLiveRegion(int)}.
2678     */
2679    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2680
2681    /**
2682     * The default whether the view is important for accessibility.
2683     */
2684    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2685
2686    /**
2687     * Mask for obtaining the bits which specify a view's accessibility live
2688     * region mode.
2689     */
2690    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2691            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2692            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2693
2694    /**
2695     * Flag indicating whether a view has accessibility focus.
2696     */
2697    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2698
2699    /**
2700     * Flag whether the accessibility state of the subtree rooted at this view changed.
2701     */
2702    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2703
2704    /**
2705     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2706     * is used to check whether later changes to the view's transform should invalidate the
2707     * view to force the quickReject test to run again.
2708     */
2709    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2710
2711    /**
2712     * Flag indicating that start/end padding has been resolved into left/right padding
2713     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2714     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2715     * during measurement. In some special cases this is required such as when an adapter-based
2716     * view measures prospective children without attaching them to a window.
2717     */
2718    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2719
2720    /**
2721     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2722     */
2723    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2724
2725    /**
2726     * Indicates that the view is tracking some sort of transient state
2727     * that the app should not need to be aware of, but that the framework
2728     * should take special care to preserve.
2729     */
2730    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2731
2732    /**
2733     * Group of bits indicating that RTL properties resolution is done.
2734     */
2735    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2736            PFLAG2_TEXT_DIRECTION_RESOLVED |
2737            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2738            PFLAG2_PADDING_RESOLVED |
2739            PFLAG2_DRAWABLE_RESOLVED;
2740
2741    // There are a couple of flags left in mPrivateFlags2
2742
2743    /* End of masks for mPrivateFlags2 */
2744
2745    /**
2746     * Masks for mPrivateFlags3, as generated by dumpFlags():
2747     *
2748     * |-------|-------|-------|-------|
2749     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2750     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2751     *                               1   PFLAG3_IS_LAID_OUT
2752     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2753     *                             1     PFLAG3_CALLED_SUPER
2754     *                            1      PFLAG3_APPLYING_INSETS
2755     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2756     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2757     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2758     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2759     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2760     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2761     *                     1             PFLAG3_SCROLL_INDICATOR_START
2762     *                    1              PFLAG3_SCROLL_INDICATOR_END
2763     *                   1               PFLAG3_ASSIST_BLOCKED
2764     *                  1                PFLAG3_CLUSTER
2765     *                 1                 PFLAG3_IS_AUTOFILLED
2766     *                1                  PFLAG3_FINGER_DOWN
2767     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2768     *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2769     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2770     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2771     *        1                          PFLAG3_TEMPORARY_DETACH
2772     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2773     * |-------|-------|-------|-------|
2774     */
2775
2776    /**
2777     * Flag indicating that view has a transform animation set on it. This is used to track whether
2778     * an animation is cleared between successive frames, in order to tell the associated
2779     * DisplayList to clear its animation matrix.
2780     */
2781    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2782
2783    /**
2784     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2785     * animation is cleared between successive frames, in order to tell the associated
2786     * DisplayList to restore its alpha value.
2787     */
2788    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2789
2790    /**
2791     * Flag indicating that the view has been through at least one layout since it
2792     * was last attached to a window.
2793     */
2794    static final int PFLAG3_IS_LAID_OUT = 0x4;
2795
2796    /**
2797     * Flag indicating that a call to measure() was skipped and should be done
2798     * instead when layout() is invoked.
2799     */
2800    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2801
2802    /**
2803     * Flag indicating that an overridden method correctly called down to
2804     * the superclass implementation as required by the API spec.
2805     */
2806    static final int PFLAG3_CALLED_SUPER = 0x10;
2807
2808    /**
2809     * Flag indicating that we're in the process of applying window insets.
2810     */
2811    static final int PFLAG3_APPLYING_INSETS = 0x20;
2812
2813    /**
2814     * Flag indicating that we're in the process of fitting system windows using the old method.
2815     */
2816    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2817
2818    /**
2819     * Flag indicating that nested scrolling is enabled for this view.
2820     * The view will optionally cooperate with views up its parent chain to allow for
2821     * integrated nested scrolling along the same axis.
2822     */
2823    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2824
2825    /**
2826     * Flag indicating that the bottom scroll indicator should be displayed
2827     * when this view can scroll up.
2828     */
2829    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2830
2831    /**
2832     * Flag indicating that the bottom scroll indicator should be displayed
2833     * when this view can scroll down.
2834     */
2835    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2836
2837    /**
2838     * Flag indicating that the left scroll indicator should be displayed
2839     * when this view can scroll left.
2840     */
2841    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2842
2843    /**
2844     * Flag indicating that the right scroll indicator should be displayed
2845     * when this view can scroll right.
2846     */
2847    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2848
2849    /**
2850     * Flag indicating that the start scroll indicator should be displayed
2851     * when this view can scroll in the start direction.
2852     */
2853    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2854
2855    /**
2856     * Flag indicating that the end scroll indicator should be displayed
2857     * when this view can scroll in the end direction.
2858     */
2859    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2860
2861    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2862
2863    static final int SCROLL_INDICATORS_NONE = 0x0000;
2864
2865    /**
2866     * Mask for use with setFlags indicating bits used for indicating which
2867     * scroll indicators are enabled.
2868     */
2869    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2870            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2871            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2872            | PFLAG3_SCROLL_INDICATOR_END;
2873
2874    /**
2875     * Left-shift required to translate between public scroll indicator flags
2876     * and internal PFLAGS3 flags. When used as a right-shift, translates
2877     * PFLAGS3 flags to public flags.
2878     */
2879    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2880
2881    /** @hide */
2882    @Retention(RetentionPolicy.SOURCE)
2883    @IntDef(flag = true,
2884            value = {
2885                    SCROLL_INDICATOR_TOP,
2886                    SCROLL_INDICATOR_BOTTOM,
2887                    SCROLL_INDICATOR_LEFT,
2888                    SCROLL_INDICATOR_RIGHT,
2889                    SCROLL_INDICATOR_START,
2890                    SCROLL_INDICATOR_END,
2891            })
2892    public @interface ScrollIndicators {}
2893
2894    /**
2895     * Scroll indicator direction for the top edge of the view.
2896     *
2897     * @see #setScrollIndicators(int)
2898     * @see #setScrollIndicators(int, int)
2899     * @see #getScrollIndicators()
2900     */
2901    public static final int SCROLL_INDICATOR_TOP =
2902            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2903
2904    /**
2905     * Scroll indicator direction for the bottom edge of the view.
2906     *
2907     * @see #setScrollIndicators(int)
2908     * @see #setScrollIndicators(int, int)
2909     * @see #getScrollIndicators()
2910     */
2911    public static final int SCROLL_INDICATOR_BOTTOM =
2912            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2913
2914    /**
2915     * Scroll indicator direction for the left edge of the view.
2916     *
2917     * @see #setScrollIndicators(int)
2918     * @see #setScrollIndicators(int, int)
2919     * @see #getScrollIndicators()
2920     */
2921    public static final int SCROLL_INDICATOR_LEFT =
2922            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2923
2924    /**
2925     * Scroll indicator direction for the right edge of the view.
2926     *
2927     * @see #setScrollIndicators(int)
2928     * @see #setScrollIndicators(int, int)
2929     * @see #getScrollIndicators()
2930     */
2931    public static final int SCROLL_INDICATOR_RIGHT =
2932            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2933
2934    /**
2935     * Scroll indicator direction for the starting edge of the view.
2936     * <p>
2937     * Resolved according to the view's layout direction, see
2938     * {@link #getLayoutDirection()} for more information.
2939     *
2940     * @see #setScrollIndicators(int)
2941     * @see #setScrollIndicators(int, int)
2942     * @see #getScrollIndicators()
2943     */
2944    public static final int SCROLL_INDICATOR_START =
2945            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2946
2947    /**
2948     * Scroll indicator direction for the ending edge of the view.
2949     * <p>
2950     * Resolved according to the view's layout direction, see
2951     * {@link #getLayoutDirection()} for more information.
2952     *
2953     * @see #setScrollIndicators(int)
2954     * @see #setScrollIndicators(int, int)
2955     * @see #getScrollIndicators()
2956     */
2957    public static final int SCROLL_INDICATOR_END =
2958            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2959
2960    /**
2961     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2962     * into this view.<p>
2963     */
2964    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2965
2966    /**
2967     * Flag indicating that the view is a root of a keyboard navigation cluster.
2968     *
2969     * @see #isKeyboardNavigationCluster()
2970     * @see #setKeyboardNavigationCluster(boolean)
2971     */
2972    private static final int PFLAG3_CLUSTER = 0x8000;
2973
2974    /**
2975     * Flag indicating that the view is autofilled
2976     *
2977     * @see #isAutofilled()
2978     * @see #setAutofilled(boolean)
2979     */
2980    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
2981
2982    /**
2983     * Indicates that the user is currently touching the screen.
2984     * Currently used for the tooltip positioning only.
2985     */
2986    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2987
2988    /**
2989     * Flag indicating that this view is the default-focus view.
2990     *
2991     * @see #isFocusedByDefault()
2992     * @see #setFocusedByDefault(boolean)
2993     */
2994    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2995
2996    /**
2997     * Shift for the bits in {@link #mPrivateFlags3} related to the
2998     * "importantForAutofill" attribute.
2999     */
3000    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3001
3002    /**
3003     * Mask for obtaining the bits which specify how to determine
3004     * whether a view is important for autofill.
3005     */
3006    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3007            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3008            | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3009            | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3010            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3011
3012    /**
3013     * Whether this view has rendered elements that overlap (see {@link
3014     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3015     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3016     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3017     * determined by whatever {@link #hasOverlappingRendering()} returns.
3018     */
3019    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3020
3021    /**
3022     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3023     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3024     */
3025    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3026
3027    /**
3028     * Flag indicating that the view is temporarily detached from the parent view.
3029     *
3030     * @see #onStartTemporaryDetach()
3031     * @see #onFinishTemporaryDetach()
3032     */
3033    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3034
3035    /**
3036     * Flag indicating that the view does not wish to be revealed within its parent
3037     * hierarchy when it gains focus. Expressed in the negative since the historical
3038     * default behavior is to reveal on focus; this flag suppresses that behavior.
3039     *
3040     * @see #setRevealOnFocusHint(boolean)
3041     * @see #getRevealOnFocusHint()
3042     */
3043    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3044
3045    /* End of masks for mPrivateFlags3 */
3046
3047    /**
3048     * Always allow a user to over-scroll this view, provided it is a
3049     * view that can scroll.
3050     *
3051     * @see #getOverScrollMode()
3052     * @see #setOverScrollMode(int)
3053     */
3054    public static final int OVER_SCROLL_ALWAYS = 0;
3055
3056    /**
3057     * Allow a user to over-scroll this view only if the content is large
3058     * enough to meaningfully scroll, provided it is a view that can scroll.
3059     *
3060     * @see #getOverScrollMode()
3061     * @see #setOverScrollMode(int)
3062     */
3063    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3064
3065    /**
3066     * Never allow a user to over-scroll this view.
3067     *
3068     * @see #getOverScrollMode()
3069     * @see #setOverScrollMode(int)
3070     */
3071    public static final int OVER_SCROLL_NEVER = 2;
3072
3073    /**
3074     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3075     * requested the system UI (status bar) to be visible (the default).
3076     *
3077     * @see #setSystemUiVisibility(int)
3078     */
3079    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3080
3081    /**
3082     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3083     * system UI to enter an unobtrusive "low profile" mode.
3084     *
3085     * <p>This is for use in games, book readers, video players, or any other
3086     * "immersive" application where the usual system chrome is deemed too distracting.
3087     *
3088     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3089     *
3090     * @see #setSystemUiVisibility(int)
3091     */
3092    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3093
3094    /**
3095     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3096     * system navigation be temporarily hidden.
3097     *
3098     * <p>This is an even less obtrusive state than that called for by
3099     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3100     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3101     * those to disappear. This is useful (in conjunction with the
3102     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3103     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3104     * window flags) for displaying content using every last pixel on the display.
3105     *
3106     * <p>There is a limitation: because navigation controls are so important, the least user
3107     * interaction will cause them to reappear immediately.  When this happens, both
3108     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3109     * so that both elements reappear at the same time.
3110     *
3111     * @see #setSystemUiVisibility(int)
3112     */
3113    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3114
3115    /**
3116     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3117     * into the normal fullscreen mode so that its content can take over the screen
3118     * while still allowing the user to interact with the application.
3119     *
3120     * <p>This has the same visual effect as
3121     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3122     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3123     * meaning that non-critical screen decorations (such as the status bar) will be
3124     * hidden while the user is in the View's window, focusing the experience on
3125     * that content.  Unlike the window flag, if you are using ActionBar in
3126     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3127     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3128     * hide the action bar.
3129     *
3130     * <p>This approach to going fullscreen is best used over the window flag when
3131     * it is a transient state -- that is, the application does this at certain
3132     * points in its user interaction where it wants to allow the user to focus
3133     * on content, but not as a continuous state.  For situations where the application
3134     * would like to simply stay full screen the entire time (such as a game that
3135     * wants to take over the screen), the
3136     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3137     * is usually a better approach.  The state set here will be removed by the system
3138     * in various situations (such as the user moving to another application) like
3139     * the other system UI states.
3140     *
3141     * <p>When using this flag, the application should provide some easy facility
3142     * for the user to go out of it.  A common example would be in an e-book
3143     * reader, where tapping on the screen brings back whatever screen and UI
3144     * decorations that had been hidden while the user was immersed in reading
3145     * the book.
3146     *
3147     * @see #setSystemUiVisibility(int)
3148     */
3149    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3150
3151    /**
3152     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3153     * flags, we would like a stable view of the content insets given to
3154     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3155     * will always represent the worst case that the application can expect
3156     * as a continuous state.  In the stock Android UI this is the space for
3157     * the system bar, nav bar, and status bar, but not more transient elements
3158     * such as an input method.
3159     *
3160     * The stable layout your UI sees is based on the system UI modes you can
3161     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3162     * then you will get a stable layout for changes of the
3163     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3164     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3165     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3166     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3167     * with a stable layout.  (Note that you should avoid using
3168     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3169     *
3170     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3171     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3172     * then a hidden status bar will be considered a "stable" state for purposes
3173     * here.  This allows your UI to continually hide the status bar, while still
3174     * using the system UI flags to hide the action bar while still retaining
3175     * a stable layout.  Note that changing the window fullscreen flag will never
3176     * provide a stable layout for a clean transition.
3177     *
3178     * <p>If you are using ActionBar in
3179     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3180     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3181     * insets it adds to those given to the application.
3182     */
3183    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3184
3185    /**
3186     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3187     * to be laid out as if it has requested
3188     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3189     * allows it to avoid artifacts when switching in and out of that mode, at
3190     * the expense that some of its user interface may be covered by screen
3191     * decorations when they are shown.  You can perform layout of your inner
3192     * UI elements to account for the navigation system UI through the
3193     * {@link #fitSystemWindows(Rect)} method.
3194     */
3195    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3196
3197    /**
3198     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3199     * to be laid out as if it has requested
3200     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3201     * allows it to avoid artifacts when switching in and out of that mode, at
3202     * the expense that some of its user interface may be covered by screen
3203     * decorations when they are shown.  You can perform layout of your inner
3204     * UI elements to account for non-fullscreen system UI through the
3205     * {@link #fitSystemWindows(Rect)} method.
3206     */
3207    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3208
3209    /**
3210     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3211     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3212     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3213     * user interaction.
3214     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3215     * has an effect when used in combination with that flag.</p>
3216     */
3217    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3218
3219    /**
3220     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3221     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3222     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3223     * experience while also hiding the system bars.  If this flag is not set,
3224     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3225     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3226     * if the user swipes from the top of the screen.
3227     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3228     * system gestures, such as swiping from the top of the screen.  These transient system bars
3229     * will overlay app’s content, may have some degree of transparency, and will automatically
3230     * hide after a short timeout.
3231     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3232     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3233     * with one or both of those flags.</p>
3234     */
3235    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3236
3237    /**
3238     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3239     * is compatible with light status bar backgrounds.
3240     *
3241     * <p>For this to take effect, the window must request
3242     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3243     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3244     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3245     *         FLAG_TRANSLUCENT_STATUS}.
3246     *
3247     * @see android.R.attr#windowLightStatusBar
3248     */
3249    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3250
3251    /**
3252     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3253     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3254     */
3255    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3256
3257    /**
3258     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3259     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3260     */
3261    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3262
3263    /**
3264     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3265     * that is compatible with light navigation bar backgrounds.
3266     *
3267     * <p>For this to take effect, the window must request
3268     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3269     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3270     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3271     *         FLAG_TRANSLUCENT_NAVIGATION}.
3272     */
3273    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3274
3275    /**
3276     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3277     */
3278    @Deprecated
3279    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3280
3281    /**
3282     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3283     */
3284    @Deprecated
3285    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3286
3287    /**
3288     * @hide
3289     *
3290     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3291     * out of the public fields to keep the undefined bits out of the developer's way.
3292     *
3293     * Flag to make the status bar not expandable.  Unless you also
3294     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3295     */
3296    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3297
3298    /**
3299     * @hide
3300     *
3301     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3302     * out of the public fields to keep the undefined bits out of the developer's way.
3303     *
3304     * Flag to hide notification icons and scrolling ticker text.
3305     */
3306    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3307
3308    /**
3309     * @hide
3310     *
3311     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3312     * out of the public fields to keep the undefined bits out of the developer's way.
3313     *
3314     * Flag to disable incoming notification alerts.  This will not block
3315     * icons, but it will block sound, vibrating and other visual or aural notifications.
3316     */
3317    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3318
3319    /**
3320     * @hide
3321     *
3322     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3323     * out of the public fields to keep the undefined bits out of the developer's way.
3324     *
3325     * Flag to hide only the scrolling ticker.  Note that
3326     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3327     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3328     */
3329    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3330
3331    /**
3332     * @hide
3333     *
3334     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3335     * out of the public fields to keep the undefined bits out of the developer's way.
3336     *
3337     * Flag to hide the center system info area.
3338     */
3339    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3340
3341    /**
3342     * @hide
3343     *
3344     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3345     * out of the public fields to keep the undefined bits out of the developer's way.
3346     *
3347     * Flag to hide only the home button.  Don't use this
3348     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3349     */
3350    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3351
3352    /**
3353     * @hide
3354     *
3355     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3356     * out of the public fields to keep the undefined bits out of the developer's way.
3357     *
3358     * Flag to hide only the back button. Don't use this
3359     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3360     */
3361    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3362
3363    /**
3364     * @hide
3365     *
3366     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3367     * out of the public fields to keep the undefined bits out of the developer's way.
3368     *
3369     * Flag to hide only the clock.  You might use this if your activity has
3370     * its own clock making the status bar's clock redundant.
3371     */
3372    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3373
3374    /**
3375     * @hide
3376     *
3377     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3378     * out of the public fields to keep the undefined bits out of the developer's way.
3379     *
3380     * Flag to hide only the recent apps button. Don't use this
3381     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3382     */
3383    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3384
3385    /**
3386     * @hide
3387     *
3388     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3389     * out of the public fields to keep the undefined bits out of the developer's way.
3390     *
3391     * Flag to disable the global search gesture. Don't use this
3392     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3393     */
3394    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3395
3396    /**
3397     * @hide
3398     *
3399     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3400     * out of the public fields to keep the undefined bits out of the developer's way.
3401     *
3402     * Flag to specify that the status bar is displayed in transient mode.
3403     */
3404    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3405
3406    /**
3407     * @hide
3408     *
3409     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3410     * out of the public fields to keep the undefined bits out of the developer's way.
3411     *
3412     * Flag to specify that the navigation bar is displayed in transient mode.
3413     */
3414    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3415
3416    /**
3417     * @hide
3418     *
3419     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3420     * out of the public fields to keep the undefined bits out of the developer's way.
3421     *
3422     * Flag to specify that the hidden status bar would like to be shown.
3423     */
3424    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3425
3426    /**
3427     * @hide
3428     *
3429     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3430     * out of the public fields to keep the undefined bits out of the developer's way.
3431     *
3432     * Flag to specify that the hidden navigation bar would like to be shown.
3433     */
3434    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3435
3436    /**
3437     * @hide
3438     *
3439     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3440     * out of the public fields to keep the undefined bits out of the developer's way.
3441     *
3442     * Flag to specify that the status bar is displayed in translucent mode.
3443     */
3444    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3445
3446    /**
3447     * @hide
3448     *
3449     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3450     * out of the public fields to keep the undefined bits out of the developer's way.
3451     *
3452     * Flag to specify that the navigation bar is displayed in translucent mode.
3453     */
3454    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3455
3456    /**
3457     * @hide
3458     *
3459     * Makes navigation bar transparent (but not the status bar).
3460     */
3461    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3462
3463    /**
3464     * @hide
3465     *
3466     * Makes status bar transparent (but not the navigation bar).
3467     */
3468    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3469
3470    /**
3471     * @hide
3472     *
3473     * Makes both status bar and navigation bar transparent.
3474     */
3475    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3476            | STATUS_BAR_TRANSPARENT;
3477
3478    /**
3479     * @hide
3480     */
3481    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3482
3483    /**
3484     * These are the system UI flags that can be cleared by events outside
3485     * of an application.  Currently this is just the ability to tap on the
3486     * screen while hiding the navigation bar to have it return.
3487     * @hide
3488     */
3489    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3490            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3491            | SYSTEM_UI_FLAG_FULLSCREEN;
3492
3493    /**
3494     * Flags that can impact the layout in relation to system UI.
3495     */
3496    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3497            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3498            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3499
3500    /** @hide */
3501    @IntDef(flag = true,
3502            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3503    @Retention(RetentionPolicy.SOURCE)
3504    public @interface FindViewFlags {}
3505
3506    /**
3507     * Find views that render the specified text.
3508     *
3509     * @see #findViewsWithText(ArrayList, CharSequence, int)
3510     */
3511    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3512
3513    /**
3514     * Find find views that contain the specified content description.
3515     *
3516     * @see #findViewsWithText(ArrayList, CharSequence, int)
3517     */
3518    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3519
3520    /**
3521     * Find views that contain {@link AccessibilityNodeProvider}. Such
3522     * a View is a root of virtual view hierarchy and may contain the searched
3523     * text. If this flag is set Views with providers are automatically
3524     * added and it is a responsibility of the client to call the APIs of
3525     * the provider to determine whether the virtual tree rooted at this View
3526     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3527     * representing the virtual views with this text.
3528     *
3529     * @see #findViewsWithText(ArrayList, CharSequence, int)
3530     *
3531     * @hide
3532     */
3533    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3534
3535    /**
3536     * The undefined cursor position.
3537     *
3538     * @hide
3539     */
3540    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3541
3542    /**
3543     * Indicates that the screen has changed state and is now off.
3544     *
3545     * @see #onScreenStateChanged(int)
3546     */
3547    public static final int SCREEN_STATE_OFF = 0x0;
3548
3549    /**
3550     * Indicates that the screen has changed state and is now on.
3551     *
3552     * @see #onScreenStateChanged(int)
3553     */
3554    public static final int SCREEN_STATE_ON = 0x1;
3555
3556    /**
3557     * Indicates no axis of view scrolling.
3558     */
3559    public static final int SCROLL_AXIS_NONE = 0;
3560
3561    /**
3562     * Indicates scrolling along the horizontal axis.
3563     */
3564    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3565
3566    /**
3567     * Indicates scrolling along the vertical axis.
3568     */
3569    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3570
3571    /**
3572     * Controls the over-scroll mode for this view.
3573     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3574     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3575     * and {@link #OVER_SCROLL_NEVER}.
3576     */
3577    private int mOverScrollMode;
3578
3579    /**
3580     * The parent this view is attached to.
3581     * {@hide}
3582     *
3583     * @see #getParent()
3584     */
3585    protected ViewParent mParent;
3586
3587    /**
3588     * {@hide}
3589     */
3590    AttachInfo mAttachInfo;
3591
3592    /**
3593     * {@hide}
3594     */
3595    @ViewDebug.ExportedProperty(flagMapping = {
3596        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3597                name = "FORCE_LAYOUT"),
3598        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3599                name = "LAYOUT_REQUIRED"),
3600        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3601            name = "DRAWING_CACHE_INVALID", outputIf = false),
3602        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3603        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3604        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3605        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3606    }, formatToHexString = true)
3607
3608    /* @hide */
3609    public int mPrivateFlags;
3610    int mPrivateFlags2;
3611    int mPrivateFlags3;
3612
3613    /**
3614     * This view's request for the visibility of the status bar.
3615     * @hide
3616     */
3617    @ViewDebug.ExportedProperty(flagMapping = {
3618        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3619                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3620                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3621        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3622                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3623                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3624        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3625                                equals = SYSTEM_UI_FLAG_VISIBLE,
3626                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3627    }, formatToHexString = true)
3628    int mSystemUiVisibility;
3629
3630    /**
3631     * Reference count for transient state.
3632     * @see #setHasTransientState(boolean)
3633     */
3634    int mTransientStateCount = 0;
3635
3636    /**
3637     * Count of how many windows this view has been attached to.
3638     */
3639    int mWindowAttachCount;
3640
3641    /**
3642     * The layout parameters associated with this view and used by the parent
3643     * {@link android.view.ViewGroup} to determine how this view should be
3644     * laid out.
3645     * {@hide}
3646     */
3647    protected ViewGroup.LayoutParams mLayoutParams;
3648
3649    /**
3650     * The view flags hold various views states.
3651     * {@hide}
3652     */
3653    @ViewDebug.ExportedProperty(formatToHexString = true)
3654    int mViewFlags;
3655
3656    static class TransformationInfo {
3657        /**
3658         * The transform matrix for the View. This transform is calculated internally
3659         * based on the translation, rotation, and scale properties.
3660         *
3661         * Do *not* use this variable directly; instead call getMatrix(), which will
3662         * load the value from the View's RenderNode.
3663         */
3664        private final Matrix mMatrix = new Matrix();
3665
3666        /**
3667         * The inverse transform matrix for the View. This transform is calculated
3668         * internally based on the translation, rotation, and scale properties.
3669         *
3670         * Do *not* use this variable directly; instead call getInverseMatrix(),
3671         * which will load the value from the View's RenderNode.
3672         */
3673        private Matrix mInverseMatrix;
3674
3675        /**
3676         * The opacity of the View. This is a value from 0 to 1, where 0 means
3677         * completely transparent and 1 means completely opaque.
3678         */
3679        @ViewDebug.ExportedProperty
3680        float mAlpha = 1f;
3681
3682        /**
3683         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3684         * property only used by transitions, which is composited with the other alpha
3685         * values to calculate the final visual alpha value.
3686         */
3687        float mTransitionAlpha = 1f;
3688    }
3689
3690    /** @hide */
3691    public TransformationInfo mTransformationInfo;
3692
3693    /**
3694     * Current clip bounds. to which all drawing of this view are constrained.
3695     */
3696    Rect mClipBounds = null;
3697
3698    private boolean mLastIsOpaque;
3699
3700    /**
3701     * The distance in pixels from the left edge of this view's parent
3702     * to the left edge of this view.
3703     * {@hide}
3704     */
3705    @ViewDebug.ExportedProperty(category = "layout")
3706    protected int mLeft;
3707    /**
3708     * The distance in pixels from the left edge of this view's parent
3709     * to the right edge of this view.
3710     * {@hide}
3711     */
3712    @ViewDebug.ExportedProperty(category = "layout")
3713    protected int mRight;
3714    /**
3715     * The distance in pixels from the top edge of this view's parent
3716     * to the top edge of this view.
3717     * {@hide}
3718     */
3719    @ViewDebug.ExportedProperty(category = "layout")
3720    protected int mTop;
3721    /**
3722     * The distance in pixels from the top edge of this view's parent
3723     * to the bottom edge of this view.
3724     * {@hide}
3725     */
3726    @ViewDebug.ExportedProperty(category = "layout")
3727    protected int mBottom;
3728
3729    /**
3730     * The offset, in pixels, by which the content of this view is scrolled
3731     * horizontally.
3732     * {@hide}
3733     */
3734    @ViewDebug.ExportedProperty(category = "scrolling")
3735    protected int mScrollX;
3736    /**
3737     * The offset, in pixels, by which the content of this view is scrolled
3738     * vertically.
3739     * {@hide}
3740     */
3741    @ViewDebug.ExportedProperty(category = "scrolling")
3742    protected int mScrollY;
3743
3744    /**
3745     * The left padding in pixels, that is the distance in pixels between the
3746     * left edge of this view and the left edge of its content.
3747     * {@hide}
3748     */
3749    @ViewDebug.ExportedProperty(category = "padding")
3750    protected int mPaddingLeft = 0;
3751    /**
3752     * The right padding in pixels, that is the distance in pixels between the
3753     * right edge of this view and the right edge of its content.
3754     * {@hide}
3755     */
3756    @ViewDebug.ExportedProperty(category = "padding")
3757    protected int mPaddingRight = 0;
3758    /**
3759     * The top padding in pixels, that is the distance in pixels between the
3760     * top edge of this view and the top edge of its content.
3761     * {@hide}
3762     */
3763    @ViewDebug.ExportedProperty(category = "padding")
3764    protected int mPaddingTop;
3765    /**
3766     * The bottom padding in pixels, that is the distance in pixels between the
3767     * bottom edge of this view and the bottom edge of its content.
3768     * {@hide}
3769     */
3770    @ViewDebug.ExportedProperty(category = "padding")
3771    protected int mPaddingBottom;
3772
3773    /**
3774     * The layout insets in pixels, that is the distance in pixels between the
3775     * visible edges of this view its bounds.
3776     */
3777    private Insets mLayoutInsets;
3778
3779    /**
3780     * Briefly describes the view and is primarily used for accessibility support.
3781     */
3782    private CharSequence mContentDescription;
3783
3784    /**
3785     * Specifies the id of a view for which this view serves as a label for
3786     * accessibility purposes.
3787     */
3788    private int mLabelForId = View.NO_ID;
3789
3790    /**
3791     * Predicate for matching labeled view id with its label for
3792     * accessibility purposes.
3793     */
3794    private MatchLabelForPredicate mMatchLabelForPredicate;
3795
3796    /**
3797     * Specifies a view before which this one is visited in accessibility traversal.
3798     */
3799    private int mAccessibilityTraversalBeforeId = NO_ID;
3800
3801    /**
3802     * Specifies a view after which this one is visited in accessibility traversal.
3803     */
3804    private int mAccessibilityTraversalAfterId = NO_ID;
3805
3806    /**
3807     * Predicate for matching a view by its id.
3808     */
3809    private MatchIdPredicate mMatchIdPredicate;
3810
3811    /**
3812     * Cache the paddingRight set by the user to append to the scrollbar's size.
3813     *
3814     * @hide
3815     */
3816    @ViewDebug.ExportedProperty(category = "padding")
3817    protected int mUserPaddingRight;
3818
3819    /**
3820     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3821     *
3822     * @hide
3823     */
3824    @ViewDebug.ExportedProperty(category = "padding")
3825    protected int mUserPaddingBottom;
3826
3827    /**
3828     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3829     *
3830     * @hide
3831     */
3832    @ViewDebug.ExportedProperty(category = "padding")
3833    protected int mUserPaddingLeft;
3834
3835    /**
3836     * Cache the paddingStart set by the user to append to the scrollbar's size.
3837     *
3838     */
3839    @ViewDebug.ExportedProperty(category = "padding")
3840    int mUserPaddingStart;
3841
3842    /**
3843     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3844     *
3845     */
3846    @ViewDebug.ExportedProperty(category = "padding")
3847    int mUserPaddingEnd;
3848
3849    /**
3850     * Cache initial left padding.
3851     *
3852     * @hide
3853     */
3854    int mUserPaddingLeftInitial;
3855
3856    /**
3857     * Cache initial right padding.
3858     *
3859     * @hide
3860     */
3861    int mUserPaddingRightInitial;
3862
3863    /**
3864     * Default undefined padding
3865     */
3866    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3867
3868    /**
3869     * Cache if a left padding has been defined
3870     */
3871    private boolean mLeftPaddingDefined = false;
3872
3873    /**
3874     * Cache if a right padding has been defined
3875     */
3876    private boolean mRightPaddingDefined = false;
3877
3878    /**
3879     * @hide
3880     */
3881    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3882    /**
3883     * @hide
3884     */
3885    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3886
3887    private LongSparseLongArray mMeasureCache;
3888
3889    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3890    private Drawable mBackground;
3891    private TintInfo mBackgroundTint;
3892
3893    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3894    private ForegroundInfo mForegroundInfo;
3895
3896    private Drawable mScrollIndicatorDrawable;
3897
3898    /**
3899     * RenderNode used for backgrounds.
3900     * <p>
3901     * When non-null and valid, this is expected to contain an up-to-date copy
3902     * of the background drawable. It is cleared on temporary detach, and reset
3903     * on cleanup.
3904     */
3905    private RenderNode mBackgroundRenderNode;
3906
3907    private int mBackgroundResource;
3908    private boolean mBackgroundSizeChanged;
3909
3910    /** The default focus highlight.
3911     * @see #mDefaultFocusHighlightEnabled
3912     * @see Drawable#hasFocusStateSpecified()
3913     */
3914    private Drawable mDefaultFocusHighlight;
3915    private Drawable mDefaultFocusHighlightCache;
3916    private boolean mDefaultFocusHighlightSizeChanged;
3917    /**
3918     * True if the default focus highlight is needed on the target device.
3919     */
3920    private static boolean sUseDefaultFocusHighlight;
3921
3922    private String mTransitionName;
3923
3924    static class TintInfo {
3925        ColorStateList mTintList;
3926        PorterDuff.Mode mTintMode;
3927        boolean mHasTintMode;
3928        boolean mHasTintList;
3929    }
3930
3931    private static class ForegroundInfo {
3932        private Drawable mDrawable;
3933        private TintInfo mTintInfo;
3934        private int mGravity = Gravity.FILL;
3935        private boolean mInsidePadding = true;
3936        private boolean mBoundsChanged = true;
3937        private final Rect mSelfBounds = new Rect();
3938        private final Rect mOverlayBounds = new Rect();
3939    }
3940
3941    static class ListenerInfo {
3942        /**
3943         * Listener used to dispatch focus change events.
3944         * This field should be made private, so it is hidden from the SDK.
3945         * {@hide}
3946         */
3947        protected OnFocusChangeListener mOnFocusChangeListener;
3948
3949        /**
3950         * Listeners for layout change events.
3951         */
3952        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3953
3954        protected OnScrollChangeListener mOnScrollChangeListener;
3955
3956        /**
3957         * Listeners for attach events.
3958         */
3959        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3960
3961        /**
3962         * Listener used to dispatch click events.
3963         * This field should be made private, so it is hidden from the SDK.
3964         * {@hide}
3965         */
3966        public OnClickListener mOnClickListener;
3967
3968        /**
3969         * Listener used to dispatch long click events.
3970         * This field should be made private, so it is hidden from the SDK.
3971         * {@hide}
3972         */
3973        protected OnLongClickListener mOnLongClickListener;
3974
3975        /**
3976         * Listener used to dispatch context click events. This field should be made private, so it
3977         * is hidden from the SDK.
3978         * {@hide}
3979         */
3980        protected OnContextClickListener mOnContextClickListener;
3981
3982        /**
3983         * Listener used to build the context menu.
3984         * This field should be made private, so it is hidden from the SDK.
3985         * {@hide}
3986         */
3987        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3988
3989        private OnKeyListener mOnKeyListener;
3990
3991        private OnTouchListener mOnTouchListener;
3992
3993        private OnHoverListener mOnHoverListener;
3994
3995        private OnGenericMotionListener mOnGenericMotionListener;
3996
3997        private OnDragListener mOnDragListener;
3998
3999        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4000
4001        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4002
4003        OnCapturedPointerListener mOnCapturedPointerListener;
4004    }
4005
4006    ListenerInfo mListenerInfo;
4007
4008    private static class TooltipInfo {
4009        /**
4010         * Text to be displayed in a tooltip popup.
4011         */
4012        @Nullable
4013        CharSequence mTooltipText;
4014
4015        /**
4016         * View-relative position of the tooltip anchor point.
4017         */
4018        int mAnchorX;
4019        int mAnchorY;
4020
4021        /**
4022         * The tooltip popup.
4023         */
4024        @Nullable
4025        TooltipPopup mTooltipPopup;
4026
4027        /**
4028         * Set to true if the tooltip was shown as a result of a long click.
4029         */
4030        boolean mTooltipFromLongClick;
4031
4032        /**
4033         * Keep these Runnables so that they can be used to reschedule.
4034         */
4035        Runnable mShowTooltipRunnable;
4036        Runnable mHideTooltipRunnable;
4037    }
4038
4039    TooltipInfo mTooltipInfo;
4040
4041    // Temporary values used to hold (x,y) coordinates when delegating from the
4042    // two-arg performLongClick() method to the legacy no-arg version.
4043    private float mLongClickX = Float.NaN;
4044    private float mLongClickY = Float.NaN;
4045
4046    /**
4047     * The application environment this view lives in.
4048     * This field should be made private, so it is hidden from the SDK.
4049     * {@hide}
4050     */
4051    @ViewDebug.ExportedProperty(deepExport = true)
4052    protected Context mContext;
4053
4054    private final Resources mResources;
4055
4056    private ScrollabilityCache mScrollCache;
4057
4058    private int[] mDrawableState = null;
4059
4060    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4061
4062    /**
4063     * Animator that automatically runs based on state changes.
4064     */
4065    private StateListAnimator mStateListAnimator;
4066
4067    /**
4068     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4069     * the user may specify which view to go to next.
4070     */
4071    private int mNextFocusLeftId = View.NO_ID;
4072
4073    /**
4074     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4075     * the user may specify which view to go to next.
4076     */
4077    private int mNextFocusRightId = View.NO_ID;
4078
4079    /**
4080     * When this view has focus and the next focus is {@link #FOCUS_UP},
4081     * the user may specify which view to go to next.
4082     */
4083    private int mNextFocusUpId = View.NO_ID;
4084
4085    /**
4086     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4087     * the user may specify which view to go to next.
4088     */
4089    private int mNextFocusDownId = View.NO_ID;
4090
4091    /**
4092     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4093     * the user may specify which view to go to next.
4094     */
4095    int mNextFocusForwardId = View.NO_ID;
4096
4097    /**
4098     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4099     *
4100     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4101     */
4102    int mNextClusterForwardId = View.NO_ID;
4103
4104    /**
4105     * Whether this View should use a default focus highlight when it gets focused but doesn't
4106     * have {@link android.R.attr#state_focused} defined in its background.
4107     */
4108    boolean mDefaultFocusHighlightEnabled = true;
4109
4110    private CheckForLongPress mPendingCheckForLongPress;
4111    private CheckForTap mPendingCheckForTap = null;
4112    private PerformClick mPerformClick;
4113    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4114
4115    private UnsetPressedState mUnsetPressedState;
4116
4117    /**
4118     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4119     * up event while a long press is invoked as soon as the long press duration is reached, so
4120     * a long press could be performed before the tap is checked, in which case the tap's action
4121     * should not be invoked.
4122     */
4123    private boolean mHasPerformedLongPress;
4124
4125    /**
4126     * Whether a context click button is currently pressed down. This is true when the stylus is
4127     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4128     * pressed. This is false once the button is released or if the stylus has been lifted.
4129     */
4130    private boolean mInContextButtonPress;
4131
4132    /**
4133     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4134     * true after a stylus button press has occured, when the next up event should not be recognized
4135     * as a tap.
4136     */
4137    private boolean mIgnoreNextUpEvent;
4138
4139    /**
4140     * The minimum height of the view. We'll try our best to have the height
4141     * of this view to at least this amount.
4142     */
4143    @ViewDebug.ExportedProperty(category = "measurement")
4144    private int mMinHeight;
4145
4146    /**
4147     * The minimum width of the view. We'll try our best to have the width
4148     * of this view to at least this amount.
4149     */
4150    @ViewDebug.ExportedProperty(category = "measurement")
4151    private int mMinWidth;
4152
4153    /**
4154     * The delegate to handle touch events that are physically in this view
4155     * but should be handled by another view.
4156     */
4157    private TouchDelegate mTouchDelegate = null;
4158
4159    /**
4160     * Solid color to use as a background when creating the drawing cache. Enables
4161     * the cache to use 16 bit bitmaps instead of 32 bit.
4162     */
4163    private int mDrawingCacheBackgroundColor = 0;
4164
4165    /**
4166     * Special tree observer used when mAttachInfo is null.
4167     */
4168    private ViewTreeObserver mFloatingTreeObserver;
4169
4170    /**
4171     * Cache the touch slop from the context that created the view.
4172     */
4173    private int mTouchSlop;
4174
4175    /**
4176     * Object that handles automatic animation of view properties.
4177     */
4178    private ViewPropertyAnimator mAnimator = null;
4179
4180    /**
4181     * List of registered FrameMetricsObservers.
4182     */
4183    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4184
4185    /**
4186     * Flag indicating that a drag can cross window boundaries.  When
4187     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4188     * with this flag set, all visible applications with targetSdkVersion >=
4189     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4190     * in the drag operation and receive the dragged content.
4191     *
4192     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4193     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4194     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4195     */
4196    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4197
4198    /**
4199     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4200     * request read access to the content URI(s) contained in the {@link ClipData} object.
4201     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4202     */
4203    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4204
4205    /**
4206     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4207     * request write access to the content URI(s) contained in the {@link ClipData} object.
4208     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4209     */
4210    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4211
4212    /**
4213     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4214     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4215     * reboots until explicitly revoked with
4216     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4217     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4218     */
4219    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4220            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4221
4222    /**
4223     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4224     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4225     * match against the original granted URI.
4226     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4227     */
4228    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4229            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4230
4231    /**
4232     * Flag indicating that the drag shadow will be opaque.  When
4233     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4234     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4235     */
4236    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4237
4238    /**
4239     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4240     */
4241    private float mVerticalScrollFactor;
4242
4243    /**
4244     * Position of the vertical scroll bar.
4245     */
4246    private int mVerticalScrollbarPosition;
4247
4248    /**
4249     * Position the scroll bar at the default position as determined by the system.
4250     */
4251    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4252
4253    /**
4254     * Position the scroll bar along the left edge.
4255     */
4256    public static final int SCROLLBAR_POSITION_LEFT = 1;
4257
4258    /**
4259     * Position the scroll bar along the right edge.
4260     */
4261    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4262
4263    /**
4264     * Indicates that the view does not have a layer.
4265     *
4266     * @see #getLayerType()
4267     * @see #setLayerType(int, android.graphics.Paint)
4268     * @see #LAYER_TYPE_SOFTWARE
4269     * @see #LAYER_TYPE_HARDWARE
4270     */
4271    public static final int LAYER_TYPE_NONE = 0;
4272
4273    /**
4274     * <p>Indicates that the view has a software layer. A software layer is backed
4275     * by a bitmap and causes the view to be rendered using Android's software
4276     * rendering pipeline, even if hardware acceleration is enabled.</p>
4277     *
4278     * <p>Software layers have various usages:</p>
4279     * <p>When the application is not using hardware acceleration, a software layer
4280     * is useful to apply a specific color filter and/or blending mode and/or
4281     * translucency to a view and all its children.</p>
4282     * <p>When the application is using hardware acceleration, a software layer
4283     * is useful to render drawing primitives not supported by the hardware
4284     * accelerated pipeline. It can also be used to cache a complex view tree
4285     * into a texture and reduce the complexity of drawing operations. For instance,
4286     * when animating a complex view tree with a translation, a software layer can
4287     * be used to render the view tree only once.</p>
4288     * <p>Software layers should be avoided when the affected view tree updates
4289     * often. Every update will require to re-render the software layer, which can
4290     * potentially be slow (particularly when hardware acceleration is turned on
4291     * since the layer will have to be uploaded into a hardware texture after every
4292     * update.)</p>
4293     *
4294     * @see #getLayerType()
4295     * @see #setLayerType(int, android.graphics.Paint)
4296     * @see #LAYER_TYPE_NONE
4297     * @see #LAYER_TYPE_HARDWARE
4298     */
4299    public static final int LAYER_TYPE_SOFTWARE = 1;
4300
4301    /**
4302     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4303     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4304     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4305     * rendering pipeline, but only if hardware acceleration is turned on for the
4306     * view hierarchy. When hardware acceleration is turned off, hardware layers
4307     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4308     *
4309     * <p>A hardware layer is useful to apply a specific color filter and/or
4310     * blending mode and/or translucency to a view and all its children.</p>
4311     * <p>A hardware layer can be used to cache a complex view tree into a
4312     * texture and reduce the complexity of drawing operations. For instance,
4313     * when animating a complex view tree with a translation, a hardware layer can
4314     * be used to render the view tree only once.</p>
4315     * <p>A hardware layer can also be used to increase the rendering quality when
4316     * rotation transformations are applied on a view. It can also be used to
4317     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4318     *
4319     * @see #getLayerType()
4320     * @see #setLayerType(int, android.graphics.Paint)
4321     * @see #LAYER_TYPE_NONE
4322     * @see #LAYER_TYPE_SOFTWARE
4323     */
4324    public static final int LAYER_TYPE_HARDWARE = 2;
4325
4326    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4327            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4328            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4329            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4330    })
4331    int mLayerType = LAYER_TYPE_NONE;
4332    Paint mLayerPaint;
4333
4334    /**
4335     * Set to true when drawing cache is enabled and cannot be created.
4336     *
4337     * @hide
4338     */
4339    public boolean mCachingFailed;
4340    private Bitmap mDrawingCache;
4341    private Bitmap mUnscaledDrawingCache;
4342
4343    /**
4344     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4345     * <p>
4346     * When non-null and valid, this is expected to contain an up-to-date copy
4347     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4348     * cleanup.
4349     */
4350    final RenderNode mRenderNode;
4351
4352    /**
4353     * Set to true when the view is sending hover accessibility events because it
4354     * is the innermost hovered view.
4355     */
4356    private boolean mSendingHoverAccessibilityEvents;
4357
4358    /**
4359     * Delegate for injecting accessibility functionality.
4360     */
4361    AccessibilityDelegate mAccessibilityDelegate;
4362
4363    /**
4364     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4365     * and add/remove objects to/from the overlay directly through the Overlay methods.
4366     */
4367    ViewOverlay mOverlay;
4368
4369    /**
4370     * The currently active parent view for receiving delegated nested scrolling events.
4371     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4372     * by {@link #stopNestedScroll()} at the same point where we clear
4373     * requestDisallowInterceptTouchEvent.
4374     */
4375    private ViewParent mNestedScrollingParent;
4376
4377    /**
4378     * Consistency verifier for debugging purposes.
4379     * @hide
4380     */
4381    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4382            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4383                    new InputEventConsistencyVerifier(this, 0) : null;
4384
4385    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4386
4387    private int[] mTempNestedScrollConsumed;
4388
4389    /**
4390     * An overlay is going to draw this View instead of being drawn as part of this
4391     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4392     * when this view is invalidated.
4393     */
4394    GhostView mGhostView;
4395
4396    /**
4397     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4398     * @hide
4399     */
4400    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4401    public String[] mAttributes;
4402
4403    /**
4404     * Maps a Resource id to its name.
4405     */
4406    private static SparseArray<String> mAttributeMap;
4407
4408    /**
4409     * Queue of pending runnables. Used to postpone calls to post() until this
4410     * view is attached and has a handler.
4411     */
4412    private HandlerActionQueue mRunQueue;
4413
4414    /**
4415     * The pointer icon when the mouse hovers on this view. The default is null.
4416     */
4417    private PointerIcon mPointerIcon;
4418
4419    /**
4420     * @hide
4421     */
4422    String mStartActivityRequestWho;
4423
4424    @Nullable
4425    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4426
4427    /** Used to delay visibility updates sent to the autofill manager */
4428    private Handler mVisibilityChangeForAutofillHandler;
4429
4430    /**
4431     * Simple constructor to use when creating a view from code.
4432     *
4433     * @param context The Context the view is running in, through which it can
4434     *        access the current theme, resources, etc.
4435     */
4436    public View(Context context) {
4437        mContext = context;
4438        mResources = context != null ? context.getResources() : null;
4439        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4440        // Set some flags defaults
4441        mPrivateFlags2 =
4442                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4443                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4444                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4445                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4446                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4447                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4448        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4449        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4450        mUserPaddingStart = UNDEFINED_PADDING;
4451        mUserPaddingEnd = UNDEFINED_PADDING;
4452        mRenderNode = RenderNode.create(getClass().getName(), this);
4453
4454        if (!sCompatibilityDone && context != null) {
4455            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4456
4457            // Older apps may need this compatibility hack for measurement.
4458            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4459
4460            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4461            // of whether a layout was requested on that View.
4462            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4463
4464            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4465
4466            // In M and newer, our widgets can pass a "hint" value in the size
4467            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4468            // know what the expected parent size is going to be, so e.g. list items can size
4469            // themselves at 1/3 the size of their container. It breaks older apps though,
4470            // specifically apps that use some popular open source libraries.
4471            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4472
4473            // Old versions of the platform would give different results from
4474            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4475            // modes, so we always need to run an additional EXACTLY pass.
4476            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4477
4478            // Prior to N, layout params could change without requiring a
4479            // subsequent call to setLayoutParams() and they would usually
4480            // work. Partial layout breaks this assumption.
4481            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4482
4483            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4484            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4485            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4486
4487            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4488            // in apps so we target check it to avoid breaking existing apps.
4489            sPreserveMarginParamsInLayoutParamConversion =
4490                    targetSdkVersion >= Build.VERSION_CODES.N;
4491
4492            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4493
4494            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4495
4496            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4497
4498            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4499                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4500
4501            sCompatibilityDone = true;
4502        }
4503    }
4504
4505    /**
4506     * Constructor that is called when inflating a view from XML. This is called
4507     * when a view is being constructed from an XML file, supplying attributes
4508     * that were specified in the XML file. This version uses a default style of
4509     * 0, so the only attribute values applied are those in the Context's Theme
4510     * and the given AttributeSet.
4511     *
4512     * <p>
4513     * The method onFinishInflate() will be called after all children have been
4514     * added.
4515     *
4516     * @param context The Context the view is running in, through which it can
4517     *        access the current theme, resources, etc.
4518     * @param attrs The attributes of the XML tag that is inflating the view.
4519     * @see #View(Context, AttributeSet, int)
4520     */
4521    public View(Context context, @Nullable AttributeSet attrs) {
4522        this(context, attrs, 0);
4523    }
4524
4525    /**
4526     * Perform inflation from XML and apply a class-specific base style from a
4527     * theme attribute. This constructor of View allows subclasses to use their
4528     * own base style when they are inflating. For example, a Button class's
4529     * constructor would call this version of the super class constructor and
4530     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4531     * allows the theme's button style to modify all of the base view attributes
4532     * (in particular its background) as well as the Button class's attributes.
4533     *
4534     * @param context The Context the view is running in, through which it can
4535     *        access the current theme, resources, etc.
4536     * @param attrs The attributes of the XML tag that is inflating the view.
4537     * @param defStyleAttr An attribute in the current theme that contains a
4538     *        reference to a style resource that supplies default values for
4539     *        the view. Can be 0 to not look for defaults.
4540     * @see #View(Context, AttributeSet)
4541     */
4542    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4543        this(context, attrs, defStyleAttr, 0);
4544    }
4545
4546    /**
4547     * Perform inflation from XML and apply a class-specific base style from a
4548     * theme attribute or style resource. This constructor of View allows
4549     * subclasses to use their own base style when they are inflating.
4550     * <p>
4551     * When determining the final value of a particular attribute, there are
4552     * four inputs that come into play:
4553     * <ol>
4554     * <li>Any attribute values in the given AttributeSet.
4555     * <li>The style resource specified in the AttributeSet (named "style").
4556     * <li>The default style specified by <var>defStyleAttr</var>.
4557     * <li>The default style specified by <var>defStyleRes</var>.
4558     * <li>The base values in this theme.
4559     * </ol>
4560     * <p>
4561     * Each of these inputs is considered in-order, with the first listed taking
4562     * precedence over the following ones. In other words, if in the
4563     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4564     * , then the button's text will <em>always</em> be black, regardless of
4565     * what is specified in any of the styles.
4566     *
4567     * @param context The Context the view is running in, through which it can
4568     *        access the current theme, resources, etc.
4569     * @param attrs The attributes of the XML tag that is inflating the view.
4570     * @param defStyleAttr An attribute in the current theme that contains a
4571     *        reference to a style resource that supplies default values for
4572     *        the view. Can be 0 to not look for defaults.
4573     * @param defStyleRes A resource identifier of a style resource that
4574     *        supplies default values for the view, used only if
4575     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4576     *        to not look for defaults.
4577     * @see #View(Context, AttributeSet, int)
4578     */
4579    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4580        this(context);
4581
4582        final TypedArray a = context.obtainStyledAttributes(
4583                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4584
4585        if (mDebugViewAttributes) {
4586            saveAttributeData(attrs, a);
4587        }
4588
4589        Drawable background = null;
4590
4591        int leftPadding = -1;
4592        int topPadding = -1;
4593        int rightPadding = -1;
4594        int bottomPadding = -1;
4595        int startPadding = UNDEFINED_PADDING;
4596        int endPadding = UNDEFINED_PADDING;
4597
4598        int padding = -1;
4599        int paddingHorizontal = -1;
4600        int paddingVertical = -1;
4601
4602        int viewFlagValues = 0;
4603        int viewFlagMasks = 0;
4604
4605        boolean setScrollContainer = false;
4606
4607        int x = 0;
4608        int y = 0;
4609
4610        float tx = 0;
4611        float ty = 0;
4612        float tz = 0;
4613        float elevation = 0;
4614        float rotation = 0;
4615        float rotationX = 0;
4616        float rotationY = 0;
4617        float sx = 1f;
4618        float sy = 1f;
4619        boolean transformSet = false;
4620
4621        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4622        int overScrollMode = mOverScrollMode;
4623        boolean initializeScrollbars = false;
4624        boolean initializeScrollIndicators = false;
4625
4626        boolean startPaddingDefined = false;
4627        boolean endPaddingDefined = false;
4628        boolean leftPaddingDefined = false;
4629        boolean rightPaddingDefined = false;
4630
4631        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4632
4633        // Set default values.
4634        viewFlagValues |= FOCUSABLE_AUTO;
4635        viewFlagMasks |= FOCUSABLE_AUTO;
4636
4637        final int N = a.getIndexCount();
4638        for (int i = 0; i < N; i++) {
4639            int attr = a.getIndex(i);
4640            switch (attr) {
4641                case com.android.internal.R.styleable.View_background:
4642                    background = a.getDrawable(attr);
4643                    break;
4644                case com.android.internal.R.styleable.View_padding:
4645                    padding = a.getDimensionPixelSize(attr, -1);
4646                    mUserPaddingLeftInitial = padding;
4647                    mUserPaddingRightInitial = padding;
4648                    leftPaddingDefined = true;
4649                    rightPaddingDefined = true;
4650                    break;
4651                case com.android.internal.R.styleable.View_paddingHorizontal:
4652                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4653                    mUserPaddingLeftInitial = paddingHorizontal;
4654                    mUserPaddingRightInitial = paddingHorizontal;
4655                    leftPaddingDefined = true;
4656                    rightPaddingDefined = true;
4657                    break;
4658                case com.android.internal.R.styleable.View_paddingVertical:
4659                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4660                    break;
4661                 case com.android.internal.R.styleable.View_paddingLeft:
4662                    leftPadding = a.getDimensionPixelSize(attr, -1);
4663                    mUserPaddingLeftInitial = leftPadding;
4664                    leftPaddingDefined = true;
4665                    break;
4666                case com.android.internal.R.styleable.View_paddingTop:
4667                    topPadding = a.getDimensionPixelSize(attr, -1);
4668                    break;
4669                case com.android.internal.R.styleable.View_paddingRight:
4670                    rightPadding = a.getDimensionPixelSize(attr, -1);
4671                    mUserPaddingRightInitial = rightPadding;
4672                    rightPaddingDefined = true;
4673                    break;
4674                case com.android.internal.R.styleable.View_paddingBottom:
4675                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4676                    break;
4677                case com.android.internal.R.styleable.View_paddingStart:
4678                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4679                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4680                    break;
4681                case com.android.internal.R.styleable.View_paddingEnd:
4682                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4683                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4684                    break;
4685                case com.android.internal.R.styleable.View_scrollX:
4686                    x = a.getDimensionPixelOffset(attr, 0);
4687                    break;
4688                case com.android.internal.R.styleable.View_scrollY:
4689                    y = a.getDimensionPixelOffset(attr, 0);
4690                    break;
4691                case com.android.internal.R.styleable.View_alpha:
4692                    setAlpha(a.getFloat(attr, 1f));
4693                    break;
4694                case com.android.internal.R.styleable.View_transformPivotX:
4695                    setPivotX(a.getDimension(attr, 0));
4696                    break;
4697                case com.android.internal.R.styleable.View_transformPivotY:
4698                    setPivotY(a.getDimension(attr, 0));
4699                    break;
4700                case com.android.internal.R.styleable.View_translationX:
4701                    tx = a.getDimension(attr, 0);
4702                    transformSet = true;
4703                    break;
4704                case com.android.internal.R.styleable.View_translationY:
4705                    ty = a.getDimension(attr, 0);
4706                    transformSet = true;
4707                    break;
4708                case com.android.internal.R.styleable.View_translationZ:
4709                    tz = a.getDimension(attr, 0);
4710                    transformSet = true;
4711                    break;
4712                case com.android.internal.R.styleable.View_elevation:
4713                    elevation = a.getDimension(attr, 0);
4714                    transformSet = true;
4715                    break;
4716                case com.android.internal.R.styleable.View_rotation:
4717                    rotation = a.getFloat(attr, 0);
4718                    transformSet = true;
4719                    break;
4720                case com.android.internal.R.styleable.View_rotationX:
4721                    rotationX = a.getFloat(attr, 0);
4722                    transformSet = true;
4723                    break;
4724                case com.android.internal.R.styleable.View_rotationY:
4725                    rotationY = a.getFloat(attr, 0);
4726                    transformSet = true;
4727                    break;
4728                case com.android.internal.R.styleable.View_scaleX:
4729                    sx = a.getFloat(attr, 1f);
4730                    transformSet = true;
4731                    break;
4732                case com.android.internal.R.styleable.View_scaleY:
4733                    sy = a.getFloat(attr, 1f);
4734                    transformSet = true;
4735                    break;
4736                case com.android.internal.R.styleable.View_id:
4737                    mID = a.getResourceId(attr, NO_ID);
4738                    break;
4739                case com.android.internal.R.styleable.View_tag:
4740                    mTag = a.getText(attr);
4741                    break;
4742                case com.android.internal.R.styleable.View_fitsSystemWindows:
4743                    if (a.getBoolean(attr, false)) {
4744                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4745                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4746                    }
4747                    break;
4748                case com.android.internal.R.styleable.View_focusable:
4749                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4750                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4751                        viewFlagMasks |= FOCUSABLE_MASK;
4752                    }
4753                    break;
4754                case com.android.internal.R.styleable.View_focusableInTouchMode:
4755                    if (a.getBoolean(attr, false)) {
4756                        // unset auto focus since focusableInTouchMode implies explicit focusable
4757                        viewFlagValues &= ~FOCUSABLE_AUTO;
4758                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4759                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4760                    }
4761                    break;
4762                case com.android.internal.R.styleable.View_clickable:
4763                    if (a.getBoolean(attr, false)) {
4764                        viewFlagValues |= CLICKABLE;
4765                        viewFlagMasks |= CLICKABLE;
4766                    }
4767                    break;
4768                case com.android.internal.R.styleable.View_longClickable:
4769                    if (a.getBoolean(attr, false)) {
4770                        viewFlagValues |= LONG_CLICKABLE;
4771                        viewFlagMasks |= LONG_CLICKABLE;
4772                    }
4773                    break;
4774                case com.android.internal.R.styleable.View_contextClickable:
4775                    if (a.getBoolean(attr, false)) {
4776                        viewFlagValues |= CONTEXT_CLICKABLE;
4777                        viewFlagMasks |= CONTEXT_CLICKABLE;
4778                    }
4779                    break;
4780                case com.android.internal.R.styleable.View_saveEnabled:
4781                    if (!a.getBoolean(attr, true)) {
4782                        viewFlagValues |= SAVE_DISABLED;
4783                        viewFlagMasks |= SAVE_DISABLED_MASK;
4784                    }
4785                    break;
4786                case com.android.internal.R.styleable.View_duplicateParentState:
4787                    if (a.getBoolean(attr, false)) {
4788                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4789                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4790                    }
4791                    break;
4792                case com.android.internal.R.styleable.View_visibility:
4793                    final int visibility = a.getInt(attr, 0);
4794                    if (visibility != 0) {
4795                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4796                        viewFlagMasks |= VISIBILITY_MASK;
4797                    }
4798                    break;
4799                case com.android.internal.R.styleable.View_layoutDirection:
4800                    // Clear any layout direction flags (included resolved bits) already set
4801                    mPrivateFlags2 &=
4802                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4803                    // Set the layout direction flags depending on the value of the attribute
4804                    final int layoutDirection = a.getInt(attr, -1);
4805                    final int value = (layoutDirection != -1) ?
4806                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4807                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4808                    break;
4809                case com.android.internal.R.styleable.View_drawingCacheQuality:
4810                    final int cacheQuality = a.getInt(attr, 0);
4811                    if (cacheQuality != 0) {
4812                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4813                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4814                    }
4815                    break;
4816                case com.android.internal.R.styleable.View_contentDescription:
4817                    setContentDescription(a.getString(attr));
4818                    break;
4819                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4820                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4821                    break;
4822                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4823                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4824                    break;
4825                case com.android.internal.R.styleable.View_labelFor:
4826                    setLabelFor(a.getResourceId(attr, NO_ID));
4827                    break;
4828                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4829                    if (!a.getBoolean(attr, true)) {
4830                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4831                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4832                    }
4833                    break;
4834                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4835                    if (!a.getBoolean(attr, true)) {
4836                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4837                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4838                    }
4839                    break;
4840                case R.styleable.View_scrollbars:
4841                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4842                    if (scrollbars != SCROLLBARS_NONE) {
4843                        viewFlagValues |= scrollbars;
4844                        viewFlagMasks |= SCROLLBARS_MASK;
4845                        initializeScrollbars = true;
4846                    }
4847                    break;
4848                //noinspection deprecation
4849                case R.styleable.View_fadingEdge:
4850                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4851                        // Ignore the attribute starting with ICS
4852                        break;
4853                    }
4854                    // With builds < ICS, fall through and apply fading edges
4855                case R.styleable.View_requiresFadingEdge:
4856                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4857                    if (fadingEdge != FADING_EDGE_NONE) {
4858                        viewFlagValues |= fadingEdge;
4859                        viewFlagMasks |= FADING_EDGE_MASK;
4860                        initializeFadingEdgeInternal(a);
4861                    }
4862                    break;
4863                case R.styleable.View_scrollbarStyle:
4864                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4865                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4866                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4867                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4868                    }
4869                    break;
4870                case R.styleable.View_isScrollContainer:
4871                    setScrollContainer = true;
4872                    if (a.getBoolean(attr, false)) {
4873                        setScrollContainer(true);
4874                    }
4875                    break;
4876                case com.android.internal.R.styleable.View_keepScreenOn:
4877                    if (a.getBoolean(attr, false)) {
4878                        viewFlagValues |= KEEP_SCREEN_ON;
4879                        viewFlagMasks |= KEEP_SCREEN_ON;
4880                    }
4881                    break;
4882                case R.styleable.View_filterTouchesWhenObscured:
4883                    if (a.getBoolean(attr, false)) {
4884                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4885                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4886                    }
4887                    break;
4888                case R.styleable.View_nextFocusLeft:
4889                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4890                    break;
4891                case R.styleable.View_nextFocusRight:
4892                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4893                    break;
4894                case R.styleable.View_nextFocusUp:
4895                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4896                    break;
4897                case R.styleable.View_nextFocusDown:
4898                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4899                    break;
4900                case R.styleable.View_nextFocusForward:
4901                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4902                    break;
4903                case R.styleable.View_nextClusterForward:
4904                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4905                    break;
4906                case R.styleable.View_minWidth:
4907                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4908                    break;
4909                case R.styleable.View_minHeight:
4910                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4911                    break;
4912                case R.styleable.View_onClick:
4913                    if (context.isRestricted()) {
4914                        throw new IllegalStateException("The android:onClick attribute cannot "
4915                                + "be used within a restricted context");
4916                    }
4917
4918                    final String handlerName = a.getString(attr);
4919                    if (handlerName != null) {
4920                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4921                    }
4922                    break;
4923                case R.styleable.View_overScrollMode:
4924                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4925                    break;
4926                case R.styleable.View_verticalScrollbarPosition:
4927                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4928                    break;
4929                case R.styleable.View_layerType:
4930                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4931                    break;
4932                case R.styleable.View_textDirection:
4933                    // Clear any text direction flag already set
4934                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4935                    // Set the text direction flags depending on the value of the attribute
4936                    final int textDirection = a.getInt(attr, -1);
4937                    if (textDirection != -1) {
4938                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4939                    }
4940                    break;
4941                case R.styleable.View_textAlignment:
4942                    // Clear any text alignment flag already set
4943                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4944                    // Set the text alignment flag depending on the value of the attribute
4945                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4946                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4947                    break;
4948                case R.styleable.View_importantForAccessibility:
4949                    setImportantForAccessibility(a.getInt(attr,
4950                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4951                    break;
4952                case R.styleable.View_accessibilityLiveRegion:
4953                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4954                    break;
4955                case R.styleable.View_transitionName:
4956                    setTransitionName(a.getString(attr));
4957                    break;
4958                case R.styleable.View_nestedScrollingEnabled:
4959                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4960                    break;
4961                case R.styleable.View_stateListAnimator:
4962                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4963                            a.getResourceId(attr, 0)));
4964                    break;
4965                case R.styleable.View_backgroundTint:
4966                    // This will get applied later during setBackground().
4967                    if (mBackgroundTint == null) {
4968                        mBackgroundTint = new TintInfo();
4969                    }
4970                    mBackgroundTint.mTintList = a.getColorStateList(
4971                            R.styleable.View_backgroundTint);
4972                    mBackgroundTint.mHasTintList = true;
4973                    break;
4974                case R.styleable.View_backgroundTintMode:
4975                    // This will get applied later during setBackground().
4976                    if (mBackgroundTint == null) {
4977                        mBackgroundTint = new TintInfo();
4978                    }
4979                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4980                            R.styleable.View_backgroundTintMode, -1), null);
4981                    mBackgroundTint.mHasTintMode = true;
4982                    break;
4983                case R.styleable.View_outlineProvider:
4984                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4985                            PROVIDER_BACKGROUND));
4986                    break;
4987                case R.styleable.View_foreground:
4988                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4989                        setForeground(a.getDrawable(attr));
4990                    }
4991                    break;
4992                case R.styleable.View_foregroundGravity:
4993                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4994                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4995                    }
4996                    break;
4997                case R.styleable.View_foregroundTintMode:
4998                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4999                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5000                    }
5001                    break;
5002                case R.styleable.View_foregroundTint:
5003                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5004                        setForegroundTintList(a.getColorStateList(attr));
5005                    }
5006                    break;
5007                case R.styleable.View_foregroundInsidePadding:
5008                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5009                        if (mForegroundInfo == null) {
5010                            mForegroundInfo = new ForegroundInfo();
5011                        }
5012                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5013                                mForegroundInfo.mInsidePadding);
5014                    }
5015                    break;
5016                case R.styleable.View_scrollIndicators:
5017                    final int scrollIndicators =
5018                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5019                                    & SCROLL_INDICATORS_PFLAG3_MASK;
5020                    if (scrollIndicators != 0) {
5021                        mPrivateFlags3 |= scrollIndicators;
5022                        initializeScrollIndicators = true;
5023                    }
5024                    break;
5025                case R.styleable.View_pointerIcon:
5026                    final int resourceId = a.getResourceId(attr, 0);
5027                    if (resourceId != 0) {
5028                        setPointerIcon(PointerIcon.load(
5029                                context.getResources(), resourceId));
5030                    } else {
5031                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5032                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5033                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5034                        }
5035                    }
5036                    break;
5037                case R.styleable.View_forceHasOverlappingRendering:
5038                    if (a.peekValue(attr) != null) {
5039                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5040                    }
5041                    break;
5042                case R.styleable.View_tooltipText:
5043                    setTooltipText(a.getText(attr));
5044                    break;
5045                case R.styleable.View_keyboardNavigationCluster:
5046                    if (a.peekValue(attr) != null) {
5047                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5048                    }
5049                    break;
5050                case R.styleable.View_focusedByDefault:
5051                    if (a.peekValue(attr) != null) {
5052                        setFocusedByDefault(a.getBoolean(attr, true));
5053                    }
5054                    break;
5055                case R.styleable.View_autofillHints:
5056                    if (a.peekValue(attr) != null) {
5057                        CharSequence[] rawHints = null;
5058                        String rawString = null;
5059
5060                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5061                            int resId = a.getResourceId(attr, 0);
5062
5063                            try {
5064                                rawHints = a.getTextArray(attr);
5065                            } catch (Resources.NotFoundException e) {
5066                                rawString = getResources().getString(resId);
5067                            }
5068                        } else {
5069                            rawString = a.getString(attr);
5070                        }
5071
5072                        if (rawHints == null) {
5073                            if (rawString == null) {
5074                                throw new IllegalArgumentException(
5075                                        "Could not resolve autofillHints");
5076                            } else {
5077                                rawHints = rawString.split(",");
5078                            }
5079                        }
5080
5081                        String[] hints = new String[rawHints.length];
5082
5083                        int numHints = rawHints.length;
5084                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5085                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5086                        }
5087                        setAutofillHints(hints);
5088                    }
5089                    break;
5090                case R.styleable.View_importantForAutofill:
5091                    if (a.peekValue(attr) != null) {
5092                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5093                    }
5094                    break;
5095                case R.styleable.View_defaultFocusHighlightEnabled:
5096                    if (a.peekValue(attr) != null) {
5097                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5098                    }
5099                    break;
5100            }
5101        }
5102
5103        setOverScrollMode(overScrollMode);
5104
5105        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5106        // the resolved layout direction). Those cached values will be used later during padding
5107        // resolution.
5108        mUserPaddingStart = startPadding;
5109        mUserPaddingEnd = endPadding;
5110
5111        if (background != null) {
5112            setBackground(background);
5113        }
5114
5115        // setBackground above will record that padding is currently provided by the background.
5116        // If we have padding specified via xml, record that here instead and use it.
5117        mLeftPaddingDefined = leftPaddingDefined;
5118        mRightPaddingDefined = rightPaddingDefined;
5119
5120        if (padding >= 0) {
5121            leftPadding = padding;
5122            topPadding = padding;
5123            rightPadding = padding;
5124            bottomPadding = padding;
5125            mUserPaddingLeftInitial = padding;
5126            mUserPaddingRightInitial = padding;
5127        } else {
5128            if (paddingHorizontal >= 0) {
5129                leftPadding = paddingHorizontal;
5130                rightPadding = paddingHorizontal;
5131                mUserPaddingLeftInitial = paddingHorizontal;
5132                mUserPaddingRightInitial = paddingHorizontal;
5133            }
5134            if (paddingVertical >= 0) {
5135                topPadding = paddingVertical;
5136                bottomPadding = paddingVertical;
5137            }
5138        }
5139
5140        if (isRtlCompatibilityMode()) {
5141            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5142            // left / right padding are used if defined (meaning here nothing to do). If they are not
5143            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5144            // start / end and resolve them as left / right (layout direction is not taken into account).
5145            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5146            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5147            // defined.
5148            if (!mLeftPaddingDefined && startPaddingDefined) {
5149                leftPadding = startPadding;
5150            }
5151            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5152            if (!mRightPaddingDefined && endPaddingDefined) {
5153                rightPadding = endPadding;
5154            }
5155            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5156        } else {
5157            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5158            // values defined. Otherwise, left /right values are used.
5159            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5160            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5161            // defined.
5162            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5163
5164            if (mLeftPaddingDefined && !hasRelativePadding) {
5165                mUserPaddingLeftInitial = leftPadding;
5166            }
5167            if (mRightPaddingDefined && !hasRelativePadding) {
5168                mUserPaddingRightInitial = rightPadding;
5169            }
5170        }
5171
5172        internalSetPadding(
5173                mUserPaddingLeftInitial,
5174                topPadding >= 0 ? topPadding : mPaddingTop,
5175                mUserPaddingRightInitial,
5176                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5177
5178        if (viewFlagMasks != 0) {
5179            setFlags(viewFlagValues, viewFlagMasks);
5180        }
5181
5182        if (initializeScrollbars) {
5183            initializeScrollbarsInternal(a);
5184        }
5185
5186        if (initializeScrollIndicators) {
5187            initializeScrollIndicatorsInternal();
5188        }
5189
5190        a.recycle();
5191
5192        // Needs to be called after mViewFlags is set
5193        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5194            recomputePadding();
5195        }
5196
5197        if (x != 0 || y != 0) {
5198            scrollTo(x, y);
5199        }
5200
5201        if (transformSet) {
5202            setTranslationX(tx);
5203            setTranslationY(ty);
5204            setTranslationZ(tz);
5205            setElevation(elevation);
5206            setRotation(rotation);
5207            setRotationX(rotationX);
5208            setRotationY(rotationY);
5209            setScaleX(sx);
5210            setScaleY(sy);
5211        }
5212
5213        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5214            setScrollContainer(true);
5215        }
5216
5217        computeOpaqueFlags();
5218    }
5219
5220    /**
5221     * An implementation of OnClickListener that attempts to lazily load a
5222     * named click handling method from a parent or ancestor context.
5223     */
5224    private static class DeclaredOnClickListener implements OnClickListener {
5225        private final View mHostView;
5226        private final String mMethodName;
5227
5228        private Method mResolvedMethod;
5229        private Context mResolvedContext;
5230
5231        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5232            mHostView = hostView;
5233            mMethodName = methodName;
5234        }
5235
5236        @Override
5237        public void onClick(@NonNull View v) {
5238            if (mResolvedMethod == null) {
5239                resolveMethod(mHostView.getContext(), mMethodName);
5240            }
5241
5242            try {
5243                mResolvedMethod.invoke(mResolvedContext, v);
5244            } catch (IllegalAccessException e) {
5245                throw new IllegalStateException(
5246                        "Could not execute non-public method for android:onClick", e);
5247            } catch (InvocationTargetException e) {
5248                throw new IllegalStateException(
5249                        "Could not execute method for android:onClick", e);
5250            }
5251        }
5252
5253        @NonNull
5254        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5255            while (context != null) {
5256                try {
5257                    if (!context.isRestricted()) {
5258                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5259                        if (method != null) {
5260                            mResolvedMethod = method;
5261                            mResolvedContext = context;
5262                            return;
5263                        }
5264                    }
5265                } catch (NoSuchMethodException e) {
5266                    // Failed to find method, keep searching up the hierarchy.
5267                }
5268
5269                if (context instanceof ContextWrapper) {
5270                    context = ((ContextWrapper) context).getBaseContext();
5271                } else {
5272                    // Can't search up the hierarchy, null out and fail.
5273                    context = null;
5274                }
5275            }
5276
5277            final int id = mHostView.getId();
5278            final String idText = id == NO_ID ? "" : " with id '"
5279                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5280            throw new IllegalStateException("Could not find method " + mMethodName
5281                    + "(View) in a parent or ancestor Context for android:onClick "
5282                    + "attribute defined on view " + mHostView.getClass() + idText);
5283        }
5284    }
5285
5286    /**
5287     * Non-public constructor for use in testing
5288     */
5289    View() {
5290        mResources = null;
5291        mRenderNode = RenderNode.create(getClass().getName(), this);
5292    }
5293
5294    final boolean debugDraw() {
5295        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5296    }
5297
5298    private static SparseArray<String> getAttributeMap() {
5299        if (mAttributeMap == null) {
5300            mAttributeMap = new SparseArray<>();
5301        }
5302        return mAttributeMap;
5303    }
5304
5305    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5306        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5307        final int indexCount = t.getIndexCount();
5308        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5309
5310        int i = 0;
5311
5312        // Store raw XML attributes.
5313        for (int j = 0; j < attrsCount; ++j) {
5314            attributes[i] = attrs.getAttributeName(j);
5315            attributes[i + 1] = attrs.getAttributeValue(j);
5316            i += 2;
5317        }
5318
5319        // Store resolved styleable attributes.
5320        final Resources res = t.getResources();
5321        final SparseArray<String> attributeMap = getAttributeMap();
5322        for (int j = 0; j < indexCount; ++j) {
5323            final int index = t.getIndex(j);
5324            if (!t.hasValueOrEmpty(index)) {
5325                // Value is undefined. Skip it.
5326                continue;
5327            }
5328
5329            final int resourceId = t.getResourceId(index, 0);
5330            if (resourceId == 0) {
5331                // Value is not a reference. Skip it.
5332                continue;
5333            }
5334
5335            String resourceName = attributeMap.get(resourceId);
5336            if (resourceName == null) {
5337                try {
5338                    resourceName = res.getResourceName(resourceId);
5339                } catch (Resources.NotFoundException e) {
5340                    resourceName = "0x" + Integer.toHexString(resourceId);
5341                }
5342                attributeMap.put(resourceId, resourceName);
5343            }
5344
5345            attributes[i] = resourceName;
5346            attributes[i + 1] = t.getString(index);
5347            i += 2;
5348        }
5349
5350        // Trim to fit contents.
5351        final String[] trimmed = new String[i];
5352        System.arraycopy(attributes, 0, trimmed, 0, i);
5353        mAttributes = trimmed;
5354    }
5355
5356    public String toString() {
5357        StringBuilder out = new StringBuilder(128);
5358        out.append(getClass().getName());
5359        out.append('{');
5360        out.append(Integer.toHexString(System.identityHashCode(this)));
5361        out.append(' ');
5362        switch (mViewFlags&VISIBILITY_MASK) {
5363            case VISIBLE: out.append('V'); break;
5364            case INVISIBLE: out.append('I'); break;
5365            case GONE: out.append('G'); break;
5366            default: out.append('.'); break;
5367        }
5368        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5369        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5370        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5371        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5372        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5373        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5374        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5375        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5376        out.append(' ');
5377        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5378        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5379        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5380        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5381            out.append('p');
5382        } else {
5383            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5384        }
5385        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5386        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5387        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5388        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5389        out.append(' ');
5390        out.append(mLeft);
5391        out.append(',');
5392        out.append(mTop);
5393        out.append('-');
5394        out.append(mRight);
5395        out.append(',');
5396        out.append(mBottom);
5397        final int id = getId();
5398        if (id != NO_ID) {
5399            out.append(" #");
5400            out.append(Integer.toHexString(id));
5401            final Resources r = mResources;
5402            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5403                try {
5404                    String pkgname;
5405                    switch (id&0xff000000) {
5406                        case 0x7f000000:
5407                            pkgname="app";
5408                            break;
5409                        case 0x01000000:
5410                            pkgname="android";
5411                            break;
5412                        default:
5413                            pkgname = r.getResourcePackageName(id);
5414                            break;
5415                    }
5416                    String typename = r.getResourceTypeName(id);
5417                    String entryname = r.getResourceEntryName(id);
5418                    out.append(" ");
5419                    out.append(pkgname);
5420                    out.append(":");
5421                    out.append(typename);
5422                    out.append("/");
5423                    out.append(entryname);
5424                } catch (Resources.NotFoundException e) {
5425                }
5426            }
5427        }
5428        out.append("}");
5429        return out.toString();
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     *
5443     * @removed
5444     */
5445    protected void initializeFadingEdge(TypedArray a) {
5446        // This method probably shouldn't have been included in the SDK to begin with.
5447        // It relies on 'a' having been initialized using an attribute filter array that is
5448        // not publicly available to the SDK. The old method has been renamed
5449        // to initializeFadingEdgeInternal and hidden for framework use only;
5450        // this one initializes using defaults to make it safe to call for apps.
5451
5452        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5453
5454        initializeFadingEdgeInternal(arr);
5455
5456        arr.recycle();
5457    }
5458
5459    /**
5460     * <p>
5461     * Initializes the fading edges from a given set of styled attributes. This
5462     * method should be called by subclasses that need fading edges and when an
5463     * instance of these subclasses is created programmatically rather than
5464     * being inflated from XML. This method is automatically called when the XML
5465     * is inflated.
5466     * </p>
5467     *
5468     * @param a the styled attributes set to initialize the fading edges from
5469     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5470     */
5471    protected void initializeFadingEdgeInternal(TypedArray a) {
5472        initScrollCache();
5473
5474        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5475                R.styleable.View_fadingEdgeLength,
5476                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5477    }
5478
5479    /**
5480     * Returns the size of the vertical faded edges used to indicate that more
5481     * content in this view is visible.
5482     *
5483     * @return The size in pixels of the vertical faded edge or 0 if vertical
5484     *         faded edges are not enabled for this view.
5485     * @attr ref android.R.styleable#View_fadingEdgeLength
5486     */
5487    public int getVerticalFadingEdgeLength() {
5488        if (isVerticalFadingEdgeEnabled()) {
5489            ScrollabilityCache cache = mScrollCache;
5490            if (cache != null) {
5491                return cache.fadingEdgeLength;
5492            }
5493        }
5494        return 0;
5495    }
5496
5497    /**
5498     * Set the size of the faded edge used to indicate that more content in this
5499     * view is available.  Will not change whether the fading edge is enabled; use
5500     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5501     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5502     * for the vertical or horizontal fading edges.
5503     *
5504     * @param length The size in pixels of the faded edge used to indicate that more
5505     *        content in this view is visible.
5506     */
5507    public void setFadingEdgeLength(int length) {
5508        initScrollCache();
5509        mScrollCache.fadingEdgeLength = length;
5510    }
5511
5512    /**
5513     * Returns the size of the horizontal faded edges used to indicate that more
5514     * content in this view is visible.
5515     *
5516     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5517     *         faded edges are not enabled for this view.
5518     * @attr ref android.R.styleable#View_fadingEdgeLength
5519     */
5520    public int getHorizontalFadingEdgeLength() {
5521        if (isHorizontalFadingEdgeEnabled()) {
5522            ScrollabilityCache cache = mScrollCache;
5523            if (cache != null) {
5524                return cache.fadingEdgeLength;
5525            }
5526        }
5527        return 0;
5528    }
5529
5530    /**
5531     * Returns the width of the vertical scrollbar.
5532     *
5533     * @return The width in pixels of the vertical scrollbar or 0 if there
5534     *         is no vertical scrollbar.
5535     */
5536    public int getVerticalScrollbarWidth() {
5537        ScrollabilityCache cache = mScrollCache;
5538        if (cache != null) {
5539            ScrollBarDrawable scrollBar = cache.scrollBar;
5540            if (scrollBar != null) {
5541                int size = scrollBar.getSize(true);
5542                if (size <= 0) {
5543                    size = cache.scrollBarSize;
5544                }
5545                return size;
5546            }
5547            return 0;
5548        }
5549        return 0;
5550    }
5551
5552    /**
5553     * Returns the height of the horizontal scrollbar.
5554     *
5555     * @return The height in pixels of the horizontal scrollbar or 0 if
5556     *         there is no horizontal scrollbar.
5557     */
5558    protected int getHorizontalScrollbarHeight() {
5559        ScrollabilityCache cache = mScrollCache;
5560        if (cache != null) {
5561            ScrollBarDrawable scrollBar = cache.scrollBar;
5562            if (scrollBar != null) {
5563                int size = scrollBar.getSize(false);
5564                if (size <= 0) {
5565                    size = cache.scrollBarSize;
5566                }
5567                return size;
5568            }
5569            return 0;
5570        }
5571        return 0;
5572    }
5573
5574    /**
5575     * <p>
5576     * Initializes the scrollbars from a given set of styled attributes. This
5577     * method should be called by subclasses that need scrollbars and when an
5578     * instance of these subclasses is created programmatically rather than
5579     * being inflated from XML. This method is automatically called when the XML
5580     * is inflated.
5581     * </p>
5582     *
5583     * @param a the styled attributes set to initialize the scrollbars from
5584     *
5585     * @removed
5586     */
5587    protected void initializeScrollbars(TypedArray a) {
5588        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5589        // using the View filter array which is not available to the SDK. As such, internal
5590        // framework usage now uses initializeScrollbarsInternal and we grab a default
5591        // TypedArray with the right filter instead here.
5592        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5593
5594        initializeScrollbarsInternal(arr);
5595
5596        // We ignored the method parameter. Recycle the one we actually did use.
5597        arr.recycle();
5598    }
5599
5600    /**
5601     * <p>
5602     * Initializes the scrollbars from a given set of styled attributes. This
5603     * method should be called by subclasses that need scrollbars and when an
5604     * instance of these subclasses is created programmatically rather than
5605     * being inflated from XML. This method is automatically called when the XML
5606     * is inflated.
5607     * </p>
5608     *
5609     * @param a the styled attributes set to initialize the scrollbars from
5610     * @hide
5611     */
5612    protected void initializeScrollbarsInternal(TypedArray a) {
5613        initScrollCache();
5614
5615        final ScrollabilityCache scrollabilityCache = mScrollCache;
5616
5617        if (scrollabilityCache.scrollBar == null) {
5618            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5619            scrollabilityCache.scrollBar.setState(getDrawableState());
5620            scrollabilityCache.scrollBar.setCallback(this);
5621        }
5622
5623        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5624
5625        if (!fadeScrollbars) {
5626            scrollabilityCache.state = ScrollabilityCache.ON;
5627        }
5628        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5629
5630
5631        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5632                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5633                        .getScrollBarFadeDuration());
5634        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5635                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5636                ViewConfiguration.getScrollDefaultDelay());
5637
5638
5639        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5640                com.android.internal.R.styleable.View_scrollbarSize,
5641                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5642
5643        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5644        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5645
5646        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5647        if (thumb != null) {
5648            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5649        }
5650
5651        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5652                false);
5653        if (alwaysDraw) {
5654            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5655        }
5656
5657        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5658        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5659
5660        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5661        if (thumb != null) {
5662            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5663        }
5664
5665        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5666                false);
5667        if (alwaysDraw) {
5668            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5669        }
5670
5671        // Apply layout direction to the new Drawables if needed
5672        final int layoutDirection = getLayoutDirection();
5673        if (track != null) {
5674            track.setLayoutDirection(layoutDirection);
5675        }
5676        if (thumb != null) {
5677            thumb.setLayoutDirection(layoutDirection);
5678        }
5679
5680        // Re-apply user/background padding so that scrollbar(s) get added
5681        resolvePadding();
5682    }
5683
5684    private void initializeScrollIndicatorsInternal() {
5685        // Some day maybe we'll break this into top/left/start/etc. and let the
5686        // client control it. Until then, you can have any scroll indicator you
5687        // want as long as it's a 1dp foreground-colored rectangle.
5688        if (mScrollIndicatorDrawable == null) {
5689            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5690        }
5691    }
5692
5693    /**
5694     * <p>
5695     * Initalizes the scrollability cache if necessary.
5696     * </p>
5697     */
5698    private void initScrollCache() {
5699        if (mScrollCache == null) {
5700            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5701        }
5702    }
5703
5704    private ScrollabilityCache getScrollCache() {
5705        initScrollCache();
5706        return mScrollCache;
5707    }
5708
5709    /**
5710     * Set the position of the vertical scroll bar. Should be one of
5711     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5712     * {@link #SCROLLBAR_POSITION_RIGHT}.
5713     *
5714     * @param position Where the vertical scroll bar should be positioned.
5715     */
5716    public void setVerticalScrollbarPosition(int position) {
5717        if (mVerticalScrollbarPosition != position) {
5718            mVerticalScrollbarPosition = position;
5719            computeOpaqueFlags();
5720            resolvePadding();
5721        }
5722    }
5723
5724    /**
5725     * @return The position where the vertical scroll bar will show, if applicable.
5726     * @see #setVerticalScrollbarPosition(int)
5727     */
5728    public int getVerticalScrollbarPosition() {
5729        return mVerticalScrollbarPosition;
5730    }
5731
5732    boolean isOnScrollbar(float x, float y) {
5733        if (mScrollCache == null) {
5734            return false;
5735        }
5736        x += getScrollX();
5737        y += getScrollY();
5738        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5739            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5740            getVerticalScrollBarBounds(null, touchBounds);
5741            if (touchBounds.contains((int) x, (int) y)) {
5742                return true;
5743            }
5744        }
5745        if (isHorizontalScrollBarEnabled()) {
5746            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5747            getHorizontalScrollBarBounds(null, touchBounds);
5748            if (touchBounds.contains((int) x, (int) y)) {
5749                return true;
5750            }
5751        }
5752        return false;
5753    }
5754
5755    boolean isOnScrollbarThumb(float x, float y) {
5756        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5757    }
5758
5759    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5760        if (mScrollCache == null) {
5761            return false;
5762        }
5763        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5764            x += getScrollX();
5765            y += getScrollY();
5766            final Rect bounds = mScrollCache.mScrollBarBounds;
5767            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5768            getVerticalScrollBarBounds(bounds, touchBounds);
5769            final int range = computeVerticalScrollRange();
5770            final int offset = computeVerticalScrollOffset();
5771            final int extent = computeVerticalScrollExtent();
5772            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5773                    extent, range);
5774            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5775                    extent, range, offset);
5776            final int thumbTop = bounds.top + thumbOffset;
5777            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5778            if (x >= touchBounds.left && x <= touchBounds.right
5779                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5780                return true;
5781            }
5782        }
5783        return false;
5784    }
5785
5786    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5787        if (mScrollCache == null) {
5788            return false;
5789        }
5790        if (isHorizontalScrollBarEnabled()) {
5791            x += getScrollX();
5792            y += getScrollY();
5793            final Rect bounds = mScrollCache.mScrollBarBounds;
5794            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5795            getHorizontalScrollBarBounds(bounds, touchBounds);
5796            final int range = computeHorizontalScrollRange();
5797            final int offset = computeHorizontalScrollOffset();
5798            final int extent = computeHorizontalScrollExtent();
5799            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5800                    extent, range);
5801            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5802                    extent, range, offset);
5803            final int thumbLeft = bounds.left + thumbOffset;
5804            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5805            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5806                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5807                return true;
5808            }
5809        }
5810        return false;
5811    }
5812
5813    boolean isDraggingScrollBar() {
5814        return mScrollCache != null
5815                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5816    }
5817
5818    /**
5819     * Sets the state of all scroll indicators.
5820     * <p>
5821     * See {@link #setScrollIndicators(int, int)} for usage information.
5822     *
5823     * @param indicators a bitmask of indicators that should be enabled, or
5824     *                   {@code 0} to disable all indicators
5825     * @see #setScrollIndicators(int, int)
5826     * @see #getScrollIndicators()
5827     * @attr ref android.R.styleable#View_scrollIndicators
5828     */
5829    public void setScrollIndicators(@ScrollIndicators int indicators) {
5830        setScrollIndicators(indicators,
5831                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5832    }
5833
5834    /**
5835     * Sets the state of the scroll indicators specified by the mask. To change
5836     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5837     * <p>
5838     * When a scroll indicator is enabled, it will be displayed if the view
5839     * can scroll in the direction of the indicator.
5840     * <p>
5841     * Multiple indicator types may be enabled or disabled by passing the
5842     * logical OR of the desired types. If multiple types are specified, they
5843     * will all be set to the same enabled state.
5844     * <p>
5845     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5846     *
5847     * @param indicators the indicator direction, or the logical OR of multiple
5848     *             indicator directions. One or more of:
5849     *             <ul>
5850     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5851     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5852     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5853     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5854     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5855     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5856     *             </ul>
5857     * @see #setScrollIndicators(int)
5858     * @see #getScrollIndicators()
5859     * @attr ref android.R.styleable#View_scrollIndicators
5860     */
5861    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5862        // Shift and sanitize mask.
5863        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5864        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5865
5866        // Shift and mask indicators.
5867        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5868        indicators &= mask;
5869
5870        // Merge with non-masked flags.
5871        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5872
5873        if (mPrivateFlags3 != updatedFlags) {
5874            mPrivateFlags3 = updatedFlags;
5875
5876            if (indicators != 0) {
5877                initializeScrollIndicatorsInternal();
5878            }
5879            invalidate();
5880        }
5881    }
5882
5883    /**
5884     * Returns a bitmask representing the enabled scroll indicators.
5885     * <p>
5886     * For example, if the top and left scroll indicators are enabled and all
5887     * other indicators are disabled, the return value will be
5888     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5889     * <p>
5890     * To check whether the bottom scroll indicator is enabled, use the value
5891     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5892     *
5893     * @return a bitmask representing the enabled scroll indicators
5894     */
5895    @ScrollIndicators
5896    public int getScrollIndicators() {
5897        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5898                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5899    }
5900
5901    ListenerInfo getListenerInfo() {
5902        if (mListenerInfo != null) {
5903            return mListenerInfo;
5904        }
5905        mListenerInfo = new ListenerInfo();
5906        return mListenerInfo;
5907    }
5908
5909    /**
5910     * Register a callback to be invoked when the scroll X or Y positions of
5911     * this view change.
5912     * <p>
5913     * <b>Note:</b> Some views handle scrolling independently from View and may
5914     * have their own separate listeners for scroll-type events. For example,
5915     * {@link android.widget.ListView ListView} allows clients to register an
5916     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5917     * to listen for changes in list scroll position.
5918     *
5919     * @param l The listener to notify when the scroll X or Y position changes.
5920     * @see android.view.View#getScrollX()
5921     * @see android.view.View#getScrollY()
5922     */
5923    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5924        getListenerInfo().mOnScrollChangeListener = l;
5925    }
5926
5927    /**
5928     * Register a callback to be invoked when focus of this view changed.
5929     *
5930     * @param l The callback that will run.
5931     */
5932    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5933        getListenerInfo().mOnFocusChangeListener = l;
5934    }
5935
5936    /**
5937     * Add a listener that will be called when the bounds of the view change due to
5938     * layout processing.
5939     *
5940     * @param listener The listener that will be called when layout bounds change.
5941     */
5942    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5943        ListenerInfo li = getListenerInfo();
5944        if (li.mOnLayoutChangeListeners == null) {
5945            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5946        }
5947        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5948            li.mOnLayoutChangeListeners.add(listener);
5949        }
5950    }
5951
5952    /**
5953     * Remove a listener for layout changes.
5954     *
5955     * @param listener The listener for layout bounds change.
5956     */
5957    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5958        ListenerInfo li = mListenerInfo;
5959        if (li == null || li.mOnLayoutChangeListeners == null) {
5960            return;
5961        }
5962        li.mOnLayoutChangeListeners.remove(listener);
5963    }
5964
5965    /**
5966     * Add a listener for attach state changes.
5967     *
5968     * This listener will be called whenever this view is attached or detached
5969     * from a window. Remove the listener using
5970     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5971     *
5972     * @param listener Listener to attach
5973     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5974     */
5975    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5976        ListenerInfo li = getListenerInfo();
5977        if (li.mOnAttachStateChangeListeners == null) {
5978            li.mOnAttachStateChangeListeners
5979                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5980        }
5981        li.mOnAttachStateChangeListeners.add(listener);
5982    }
5983
5984    /**
5985     * Remove a listener for attach state changes. The listener will receive no further
5986     * notification of window attach/detach events.
5987     *
5988     * @param listener Listener to remove
5989     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5990     */
5991    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5992        ListenerInfo li = mListenerInfo;
5993        if (li == null || li.mOnAttachStateChangeListeners == null) {
5994            return;
5995        }
5996        li.mOnAttachStateChangeListeners.remove(listener);
5997    }
5998
5999    /**
6000     * Returns the focus-change callback registered for this view.
6001     *
6002     * @return The callback, or null if one is not registered.
6003     */
6004    public OnFocusChangeListener getOnFocusChangeListener() {
6005        ListenerInfo li = mListenerInfo;
6006        return li != null ? li.mOnFocusChangeListener : null;
6007    }
6008
6009    /**
6010     * Register a callback to be invoked when this view is clicked. If this view is not
6011     * clickable, it becomes clickable.
6012     *
6013     * @param l The callback that will run
6014     *
6015     * @see #setClickable(boolean)
6016     */
6017    public void setOnClickListener(@Nullable OnClickListener l) {
6018        if (!isClickable()) {
6019            setClickable(true);
6020        }
6021        getListenerInfo().mOnClickListener = l;
6022    }
6023
6024    /**
6025     * Return whether this view has an attached OnClickListener.  Returns
6026     * true if there is a listener, false if there is none.
6027     */
6028    public boolean hasOnClickListeners() {
6029        ListenerInfo li = mListenerInfo;
6030        return (li != null && li.mOnClickListener != null);
6031    }
6032
6033    /**
6034     * Register a callback to be invoked when this view is clicked and held. If this view is not
6035     * long clickable, it becomes long clickable.
6036     *
6037     * @param l The callback that will run
6038     *
6039     * @see #setLongClickable(boolean)
6040     */
6041    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6042        if (!isLongClickable()) {
6043            setLongClickable(true);
6044        }
6045        getListenerInfo().mOnLongClickListener = l;
6046    }
6047
6048    /**
6049     * Register a callback to be invoked when this view is context clicked. If the view is not
6050     * context clickable, it becomes context clickable.
6051     *
6052     * @param l The callback that will run
6053     * @see #setContextClickable(boolean)
6054     */
6055    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6056        if (!isContextClickable()) {
6057            setContextClickable(true);
6058        }
6059        getListenerInfo().mOnContextClickListener = l;
6060    }
6061
6062    /**
6063     * Register a callback to be invoked when the context menu for this view is
6064     * being built. If this view is not long clickable, it becomes long clickable.
6065     *
6066     * @param l The callback that will run
6067     *
6068     */
6069    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6070        if (!isLongClickable()) {
6071            setLongClickable(true);
6072        }
6073        getListenerInfo().mOnCreateContextMenuListener = l;
6074    }
6075
6076    /**
6077     * Set an observer to collect stats for each frame rendered for this view.
6078     *
6079     * @hide
6080     */
6081    public void addFrameMetricsListener(Window window,
6082            Window.OnFrameMetricsAvailableListener listener,
6083            Handler handler) {
6084        if (mAttachInfo != null) {
6085            if (mAttachInfo.mThreadedRenderer != null) {
6086                if (mFrameMetricsObservers == null) {
6087                    mFrameMetricsObservers = new ArrayList<>();
6088                }
6089
6090                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6091                        handler.getLooper(), listener);
6092                mFrameMetricsObservers.add(fmo);
6093                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6094            } else {
6095                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6096            }
6097        } else {
6098            if (mFrameMetricsObservers == null) {
6099                mFrameMetricsObservers = new ArrayList<>();
6100            }
6101
6102            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6103                    handler.getLooper(), listener);
6104            mFrameMetricsObservers.add(fmo);
6105        }
6106    }
6107
6108    /**
6109     * Remove observer configured to collect frame stats for this view.
6110     *
6111     * @hide
6112     */
6113    public void removeFrameMetricsListener(
6114            Window.OnFrameMetricsAvailableListener listener) {
6115        ThreadedRenderer renderer = getThreadedRenderer();
6116        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6117        if (fmo == null) {
6118            throw new IllegalArgumentException(
6119                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6120        }
6121
6122        if (mFrameMetricsObservers != null) {
6123            mFrameMetricsObservers.remove(fmo);
6124            if (renderer != null) {
6125                renderer.removeFrameMetricsObserver(fmo);
6126            }
6127        }
6128    }
6129
6130    private void registerPendingFrameMetricsObservers() {
6131        if (mFrameMetricsObservers != null) {
6132            ThreadedRenderer renderer = getThreadedRenderer();
6133            if (renderer != null) {
6134                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6135                    renderer.addFrameMetricsObserver(fmo);
6136                }
6137            } else {
6138                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6139            }
6140        }
6141    }
6142
6143    private FrameMetricsObserver findFrameMetricsObserver(
6144            Window.OnFrameMetricsAvailableListener listener) {
6145        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6146            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6147            if (observer.mListener == listener) {
6148                return observer;
6149            }
6150        }
6151
6152        return null;
6153    }
6154
6155    /**
6156     * Call this view's OnClickListener, if it is defined.  Performs all normal
6157     * actions associated with clicking: reporting accessibility event, playing
6158     * a sound, etc.
6159     *
6160     * @return True there was an assigned OnClickListener that was called, false
6161     *         otherwise is returned.
6162     */
6163    public boolean performClick() {
6164        final boolean result;
6165        final ListenerInfo li = mListenerInfo;
6166        if (li != null && li.mOnClickListener != null) {
6167            playSoundEffect(SoundEffectConstants.CLICK);
6168            li.mOnClickListener.onClick(this);
6169            result = true;
6170        } else {
6171            result = false;
6172        }
6173
6174        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6175
6176        notifyEnterOrExitForAutoFillIfNeeded(true);
6177
6178        return result;
6179    }
6180
6181    /**
6182     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6183     * this only calls the listener, and does not do any associated clicking
6184     * actions like reporting an accessibility event.
6185     *
6186     * @return True there was an assigned OnClickListener that was called, false
6187     *         otherwise is returned.
6188     */
6189    public boolean callOnClick() {
6190        ListenerInfo li = mListenerInfo;
6191        if (li != null && li.mOnClickListener != null) {
6192            li.mOnClickListener.onClick(this);
6193            return true;
6194        }
6195        return false;
6196    }
6197
6198    /**
6199     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6200     * context menu if the OnLongClickListener did not consume the event.
6201     *
6202     * @return {@code true} if one of the above receivers consumed the event,
6203     *         {@code false} otherwise
6204     */
6205    public boolean performLongClick() {
6206        return performLongClickInternal(mLongClickX, mLongClickY);
6207    }
6208
6209    /**
6210     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6211     * context menu if the OnLongClickListener did not consume the event,
6212     * anchoring it to an (x,y) coordinate.
6213     *
6214     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6215     *          to disable anchoring
6216     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6217     *          to disable anchoring
6218     * @return {@code true} if one of the above receivers consumed the event,
6219     *         {@code false} otherwise
6220     */
6221    public boolean performLongClick(float x, float y) {
6222        mLongClickX = x;
6223        mLongClickY = y;
6224        final boolean handled = performLongClick();
6225        mLongClickX = Float.NaN;
6226        mLongClickY = Float.NaN;
6227        return handled;
6228    }
6229
6230    /**
6231     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6232     * context menu if the OnLongClickListener did not consume the event,
6233     * optionally anchoring it to an (x,y) coordinate.
6234     *
6235     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6236     *          to disable anchoring
6237     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6238     *          to disable anchoring
6239     * @return {@code true} if one of the above receivers consumed the event,
6240     *         {@code false} otherwise
6241     */
6242    private boolean performLongClickInternal(float x, float y) {
6243        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6244
6245        boolean handled = false;
6246        final ListenerInfo li = mListenerInfo;
6247        if (li != null && li.mOnLongClickListener != null) {
6248            handled = li.mOnLongClickListener.onLongClick(View.this);
6249        }
6250        if (!handled) {
6251            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6252            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6253        }
6254        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6255            if (!handled) {
6256                handled = showLongClickTooltip((int) x, (int) y);
6257            }
6258        }
6259        if (handled) {
6260            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6261        }
6262        return handled;
6263    }
6264
6265    /**
6266     * Call this view's OnContextClickListener, if it is defined.
6267     *
6268     * @param x the x coordinate of the context click
6269     * @param y the y coordinate of the context click
6270     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6271     *         otherwise.
6272     */
6273    public boolean performContextClick(float x, float y) {
6274        return performContextClick();
6275    }
6276
6277    /**
6278     * Call this view's OnContextClickListener, if it is defined.
6279     *
6280     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6281     *         otherwise.
6282     */
6283    public boolean performContextClick() {
6284        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6285
6286        boolean handled = false;
6287        ListenerInfo li = mListenerInfo;
6288        if (li != null && li.mOnContextClickListener != null) {
6289            handled = li.mOnContextClickListener.onContextClick(View.this);
6290        }
6291        if (handled) {
6292            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6293        }
6294        return handled;
6295    }
6296
6297    /**
6298     * Performs button-related actions during a touch down event.
6299     *
6300     * @param event The event.
6301     * @return True if the down was consumed.
6302     *
6303     * @hide
6304     */
6305    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6306        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6307            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6308            showContextMenu(event.getX(), event.getY());
6309            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6310            return true;
6311        }
6312        return false;
6313    }
6314
6315    /**
6316     * Shows the context menu for this view.
6317     *
6318     * @return {@code true} if the context menu was shown, {@code false}
6319     *         otherwise
6320     * @see #showContextMenu(float, float)
6321     */
6322    public boolean showContextMenu() {
6323        return getParent().showContextMenuForChild(this);
6324    }
6325
6326    /**
6327     * Shows the context menu for this view anchored to the specified
6328     * view-relative coordinate.
6329     *
6330     * @param x the X coordinate in pixels relative to the view to which the
6331     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6332     * @param y the Y coordinate in pixels relative to the view to which the
6333     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6334     * @return {@code true} if the context menu was shown, {@code false}
6335     *         otherwise
6336     */
6337    public boolean showContextMenu(float x, float y) {
6338        return getParent().showContextMenuForChild(this, x, y);
6339    }
6340
6341    /**
6342     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6343     *
6344     * @param callback Callback that will control the lifecycle of the action mode
6345     * @return The new action mode if it is started, null otherwise
6346     *
6347     * @see ActionMode
6348     * @see #startActionMode(android.view.ActionMode.Callback, int)
6349     */
6350    public ActionMode startActionMode(ActionMode.Callback callback) {
6351        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6352    }
6353
6354    /**
6355     * Start an action mode with the given type.
6356     *
6357     * @param callback Callback that will control the lifecycle of the action mode
6358     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6359     * @return The new action mode if it is started, null otherwise
6360     *
6361     * @see ActionMode
6362     */
6363    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6364        ViewParent parent = getParent();
6365        if (parent == null) return null;
6366        try {
6367            return parent.startActionModeForChild(this, callback, type);
6368        } catch (AbstractMethodError ame) {
6369            // Older implementations of custom views might not implement this.
6370            return parent.startActionModeForChild(this, callback);
6371        }
6372    }
6373
6374    /**
6375     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6376     * Context, creating a unique View identifier to retrieve the result.
6377     *
6378     * @param intent The Intent to be started.
6379     * @param requestCode The request code to use.
6380     * @hide
6381     */
6382    public void startActivityForResult(Intent intent, int requestCode) {
6383        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6384        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6385    }
6386
6387    /**
6388     * If this View corresponds to the calling who, dispatches the activity result.
6389     * @param who The identifier for the targeted View to receive the result.
6390     * @param requestCode The integer request code originally supplied to
6391     *                    startActivityForResult(), allowing you to identify who this
6392     *                    result came from.
6393     * @param resultCode The integer result code returned by the child activity
6394     *                   through its setResult().
6395     * @param data An Intent, which can return result data to the caller
6396     *               (various data can be attached to Intent "extras").
6397     * @return {@code true} if the activity result was dispatched.
6398     * @hide
6399     */
6400    public boolean dispatchActivityResult(
6401            String who, int requestCode, int resultCode, Intent data) {
6402        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6403            onActivityResult(requestCode, resultCode, data);
6404            mStartActivityRequestWho = null;
6405            return true;
6406        }
6407        return false;
6408    }
6409
6410    /**
6411     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6412     *
6413     * @param requestCode The integer request code originally supplied to
6414     *                    startActivityForResult(), allowing you to identify who this
6415     *                    result came from.
6416     * @param resultCode The integer result code returned by the child activity
6417     *                   through its setResult().
6418     * @param data An Intent, which can return result data to the caller
6419     *               (various data can be attached to Intent "extras").
6420     * @hide
6421     */
6422    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6423        // Do nothing.
6424    }
6425
6426    /**
6427     * Register a callback to be invoked when a hardware key is pressed in this view.
6428     * Key presses in software input methods will generally not trigger the methods of
6429     * this listener.
6430     * @param l the key listener to attach to this view
6431     */
6432    public void setOnKeyListener(OnKeyListener l) {
6433        getListenerInfo().mOnKeyListener = l;
6434    }
6435
6436    /**
6437     * Register a callback to be invoked when a touch event is sent to this view.
6438     * @param l the touch listener to attach to this view
6439     */
6440    public void setOnTouchListener(OnTouchListener l) {
6441        getListenerInfo().mOnTouchListener = l;
6442    }
6443
6444    /**
6445     * Register a callback to be invoked when a generic motion event is sent to this view.
6446     * @param l the generic motion listener to attach to this view
6447     */
6448    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6449        getListenerInfo().mOnGenericMotionListener = l;
6450    }
6451
6452    /**
6453     * Register a callback to be invoked when a hover event is sent to this view.
6454     * @param l the hover listener to attach to this view
6455     */
6456    public void setOnHoverListener(OnHoverListener l) {
6457        getListenerInfo().mOnHoverListener = l;
6458    }
6459
6460    /**
6461     * Register a drag event listener callback object for this View. The parameter is
6462     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6463     * View, the system calls the
6464     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6465     * @param l An implementation of {@link android.view.View.OnDragListener}.
6466     */
6467    public void setOnDragListener(OnDragListener l) {
6468        getListenerInfo().mOnDragListener = l;
6469    }
6470
6471    /**
6472     * Give this view focus. This will cause
6473     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6474     *
6475     * Note: this does not check whether this {@link View} should get focus, it just
6476     * gives it focus no matter what.  It should only be called internally by framework
6477     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6478     *
6479     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6480     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6481     *        focus moved when requestFocus() is called. It may not always
6482     *        apply, in which case use the default View.FOCUS_DOWN.
6483     * @param previouslyFocusedRect The rectangle of the view that had focus
6484     *        prior in this View's coordinate system.
6485     */
6486    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6487        if (DBG) {
6488            System.out.println(this + " requestFocus()");
6489        }
6490
6491        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6492            mPrivateFlags |= PFLAG_FOCUSED;
6493
6494            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6495
6496            if (mParent != null) {
6497                mParent.requestChildFocus(this, this);
6498                setFocusedInCluster();
6499            }
6500
6501            if (mAttachInfo != null) {
6502                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6503            }
6504
6505            onFocusChanged(true, direction, previouslyFocusedRect);
6506            refreshDrawableState();
6507        }
6508    }
6509
6510    /**
6511     * Sets this view's preference for reveal behavior when it gains focus.
6512     *
6513     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6514     * this view would prefer to be brought fully into view when it gains focus.
6515     * For example, a text field that a user is meant to type into. Other views such
6516     * as scrolling containers may prefer to opt-out of this behavior.</p>
6517     *
6518     * <p>The default value for views is true, though subclasses may change this
6519     * based on their preferred behavior.</p>
6520     *
6521     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6522     *
6523     * @see #getRevealOnFocusHint()
6524     */
6525    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6526        if (revealOnFocus) {
6527            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6528        } else {
6529            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6530        }
6531    }
6532
6533    /**
6534     * Returns this view's preference for reveal behavior when it gains focus.
6535     *
6536     * <p>When this method returns true for a child view requesting focus, ancestor
6537     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6538     * should make a best effort to make the newly focused child fully visible to the user.
6539     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6540     * other properties affecting visibility to the user as part of the focus change.</p>
6541     *
6542     * @return true if this view would prefer to become fully visible when it gains focus,
6543     *         false if it would prefer not to disrupt scroll positioning
6544     *
6545     * @see #setRevealOnFocusHint(boolean)
6546     */
6547    public final boolean getRevealOnFocusHint() {
6548        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6549    }
6550
6551    /**
6552     * Populates <code>outRect</code> with the hotspot bounds. By default,
6553     * the hotspot bounds are identical to the screen bounds.
6554     *
6555     * @param outRect rect to populate with hotspot bounds
6556     * @hide Only for internal use by views and widgets.
6557     */
6558    public void getHotspotBounds(Rect outRect) {
6559        final Drawable background = getBackground();
6560        if (background != null) {
6561            background.getHotspotBounds(outRect);
6562        } else {
6563            getBoundsOnScreen(outRect);
6564        }
6565    }
6566
6567    /**
6568     * Request that a rectangle of this view be visible on the screen,
6569     * scrolling if necessary just enough.
6570     *
6571     * <p>A View should call this if it maintains some notion of which part
6572     * of its content is interesting.  For example, a text editing view
6573     * should call this when its cursor moves.
6574     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6575     * It should not be affected by which part of the View is currently visible or its scroll
6576     * position.
6577     *
6578     * @param rectangle The rectangle in the View's content coordinate space
6579     * @return Whether any parent scrolled.
6580     */
6581    public boolean requestRectangleOnScreen(Rect rectangle) {
6582        return requestRectangleOnScreen(rectangle, false);
6583    }
6584
6585    /**
6586     * Request that a rectangle of this view be visible on the screen,
6587     * scrolling if necessary just enough.
6588     *
6589     * <p>A View should call this if it maintains some notion of which part
6590     * of its content is interesting.  For example, a text editing view
6591     * should call this when its cursor moves.
6592     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6593     * It should not be affected by which part of the View is currently visible or its scroll
6594     * position.
6595     * <p>When <code>immediate</code> is set to true, scrolling will not be
6596     * animated.
6597     *
6598     * @param rectangle The rectangle in the View's content coordinate space
6599     * @param immediate True to forbid animated scrolling, false otherwise
6600     * @return Whether any parent scrolled.
6601     */
6602    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6603        if (mParent == null) {
6604            return false;
6605        }
6606
6607        View child = this;
6608
6609        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6610        position.set(rectangle);
6611
6612        ViewParent parent = mParent;
6613        boolean scrolled = false;
6614        while (parent != null) {
6615            rectangle.set((int) position.left, (int) position.top,
6616                    (int) position.right, (int) position.bottom);
6617
6618            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6619
6620            if (!(parent instanceof View)) {
6621                break;
6622            }
6623
6624            // move it from child's content coordinate space to parent's content coordinate space
6625            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6626
6627            child = (View) parent;
6628            parent = child.getParent();
6629        }
6630
6631        return scrolled;
6632    }
6633
6634    /**
6635     * Called when this view wants to give up focus. If focus is cleared
6636     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6637     * <p>
6638     * <strong>Note:</strong> When a View clears focus the framework is trying
6639     * to give focus to the first focusable View from the top. Hence, if this
6640     * View is the first from the top that can take focus, then all callbacks
6641     * related to clearing focus will be invoked after which the framework will
6642     * give focus to this view.
6643     * </p>
6644     */
6645    public void clearFocus() {
6646        if (DBG) {
6647            System.out.println(this + " clearFocus()");
6648        }
6649
6650        clearFocusInternal(null, true, true);
6651    }
6652
6653    /**
6654     * Clears focus from the view, optionally propagating the change up through
6655     * the parent hierarchy and requesting that the root view place new focus.
6656     *
6657     * @param propagate whether to propagate the change up through the parent
6658     *            hierarchy
6659     * @param refocus when propagate is true, specifies whether to request the
6660     *            root view place new focus
6661     */
6662    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6663        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6664            mPrivateFlags &= ~PFLAG_FOCUSED;
6665
6666            if (propagate && mParent != null) {
6667                mParent.clearChildFocus(this);
6668            }
6669
6670            onFocusChanged(false, 0, null);
6671            refreshDrawableState();
6672
6673            if (propagate && (!refocus || !rootViewRequestFocus())) {
6674                notifyGlobalFocusCleared(this);
6675            }
6676        }
6677    }
6678
6679    void notifyGlobalFocusCleared(View oldFocus) {
6680        if (oldFocus != null && mAttachInfo != null) {
6681            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6682        }
6683    }
6684
6685    boolean rootViewRequestFocus() {
6686        final View root = getRootView();
6687        return root != null && root.requestFocus();
6688    }
6689
6690    /**
6691     * Called internally by the view system when a new view is getting focus.
6692     * This is what clears the old focus.
6693     * <p>
6694     * <b>NOTE:</b> The parent view's focused child must be updated manually
6695     * after calling this method. Otherwise, the view hierarchy may be left in
6696     * an inconstent state.
6697     */
6698    void unFocus(View focused) {
6699        if (DBG) {
6700            System.out.println(this + " unFocus()");
6701        }
6702
6703        clearFocusInternal(focused, false, false);
6704    }
6705
6706    /**
6707     * Returns true if this view has focus itself, or is the ancestor of the
6708     * view that has focus.
6709     *
6710     * @return True if this view has or contains focus, false otherwise.
6711     */
6712    @ViewDebug.ExportedProperty(category = "focus")
6713    public boolean hasFocus() {
6714        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6715    }
6716
6717    /**
6718     * Returns true if this view is focusable or if it contains a reachable View
6719     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6720     * is a view whose parents do not block descendants focus.
6721     * Only {@link #VISIBLE} views are considered focusable.
6722     *
6723     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6724     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6725     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6726     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6727     * {@code false} for views not explicitly marked as focusable.
6728     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6729     * behavior.</p>
6730     *
6731     * @return {@code true} if the view is focusable or if the view contains a focusable
6732     *         view, {@code false} otherwise
6733     *
6734     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6735     * @see ViewGroup#getTouchscreenBlocksFocus()
6736     * @see #hasExplicitFocusable()
6737     */
6738    public boolean hasFocusable() {
6739        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6740    }
6741
6742    /**
6743     * Returns true if this view is focusable or if it contains a reachable View
6744     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6745     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6746     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6747     * {@link #FOCUSABLE} are considered focusable.
6748     *
6749     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6750     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6751     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6752     * to focusable will not.</p>
6753     *
6754     * @return {@code true} if the view is focusable or if the view contains a focusable
6755     *         view, {@code false} otherwise
6756     *
6757     * @see #hasFocusable()
6758     */
6759    public boolean hasExplicitFocusable() {
6760        return hasFocusable(false, true);
6761    }
6762
6763    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6764        if (!isFocusableInTouchMode()) {
6765            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6766                final ViewGroup g = (ViewGroup) p;
6767                if (g.shouldBlockFocusForTouchscreen()) {
6768                    return false;
6769                }
6770            }
6771        }
6772
6773        // Invisible and gone views are never focusable.
6774        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6775            return false;
6776        }
6777
6778        // Only use effective focusable value when allowed.
6779        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6780            return true;
6781        }
6782
6783        return false;
6784    }
6785
6786    /**
6787     * Called by the view system when the focus state of this view changes.
6788     * When the focus change event is caused by directional navigation, direction
6789     * and previouslyFocusedRect provide insight into where the focus is coming from.
6790     * When overriding, be sure to call up through to the super class so that
6791     * the standard focus handling will occur.
6792     *
6793     * @param gainFocus True if the View has focus; false otherwise.
6794     * @param direction The direction focus has moved when requestFocus()
6795     *                  is called to give this view focus. Values are
6796     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6797     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6798     *                  It may not always apply, in which case use the default.
6799     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6800     *        system, of the previously focused view.  If applicable, this will be
6801     *        passed in as finer grained information about where the focus is coming
6802     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6803     */
6804    @CallSuper
6805    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6806            @Nullable Rect previouslyFocusedRect) {
6807        if (gainFocus) {
6808            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6809        } else {
6810            notifyViewAccessibilityStateChangedIfNeeded(
6811                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6812        }
6813
6814        // Here we check whether we still need the default focus highlight, and switch it on/off.
6815        switchDefaultFocusHighlight();
6816
6817        InputMethodManager imm = InputMethodManager.peekInstance();
6818        if (!gainFocus) {
6819            if (isPressed()) {
6820                setPressed(false);
6821            }
6822            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6823                imm.focusOut(this);
6824            }
6825            onFocusLost();
6826        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6827            imm.focusIn(this);
6828        }
6829
6830        invalidate(true);
6831        ListenerInfo li = mListenerInfo;
6832        if (li != null && li.mOnFocusChangeListener != null) {
6833            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6834        }
6835
6836        if (mAttachInfo != null) {
6837            mAttachInfo.mKeyDispatchState.reset(this);
6838        }
6839
6840        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6841    }
6842
6843    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6844        if (isAutofillable() && isAttachedToWindow()) {
6845            AutofillManager afm = getAutofillManager();
6846            if (afm != null) {
6847                if (enter && hasWindowFocus() && isFocused()) {
6848                    afm.notifyViewEntered(this);
6849                } else if (!hasWindowFocus() || !isFocused()) {
6850                    afm.notifyViewExited(this);
6851                }
6852            }
6853        }
6854    }
6855
6856    /**
6857     * Sends an accessibility event of the given type. If accessibility is
6858     * not enabled this method has no effect. The default implementation calls
6859     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6860     * to populate information about the event source (this View), then calls
6861     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6862     * populate the text content of the event source including its descendants,
6863     * and last calls
6864     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6865     * on its parent to request sending of the event to interested parties.
6866     * <p>
6867     * If an {@link AccessibilityDelegate} has been specified via calling
6868     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6869     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6870     * responsible for handling this call.
6871     * </p>
6872     *
6873     * @param eventType The type of the event to send, as defined by several types from
6874     * {@link android.view.accessibility.AccessibilityEvent}, such as
6875     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6876     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6877     *
6878     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6879     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6880     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6881     * @see AccessibilityDelegate
6882     */
6883    public void sendAccessibilityEvent(int eventType) {
6884        if (mAccessibilityDelegate != null) {
6885            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6886        } else {
6887            sendAccessibilityEventInternal(eventType);
6888        }
6889    }
6890
6891    /**
6892     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6893     * {@link AccessibilityEvent} to make an announcement which is related to some
6894     * sort of a context change for which none of the events representing UI transitions
6895     * is a good fit. For example, announcing a new page in a book. If accessibility
6896     * is not enabled this method does nothing.
6897     *
6898     * @param text The announcement text.
6899     */
6900    public void announceForAccessibility(CharSequence text) {
6901        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6902            AccessibilityEvent event = AccessibilityEvent.obtain(
6903                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6904            onInitializeAccessibilityEvent(event);
6905            event.getText().add(text);
6906            event.setContentDescription(null);
6907            mParent.requestSendAccessibilityEvent(this, event);
6908        }
6909    }
6910
6911    /**
6912     * @see #sendAccessibilityEvent(int)
6913     *
6914     * Note: Called from the default {@link AccessibilityDelegate}.
6915     *
6916     * @hide
6917     */
6918    public void sendAccessibilityEventInternal(int eventType) {
6919        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6920            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6921        }
6922    }
6923
6924    /**
6925     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6926     * takes as an argument an empty {@link AccessibilityEvent} and does not
6927     * perform a check whether accessibility is enabled.
6928     * <p>
6929     * If an {@link AccessibilityDelegate} has been specified via calling
6930     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6931     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6932     * is responsible for handling this call.
6933     * </p>
6934     *
6935     * @param event The event to send.
6936     *
6937     * @see #sendAccessibilityEvent(int)
6938     */
6939    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6940        if (mAccessibilityDelegate != null) {
6941            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6942        } else {
6943            sendAccessibilityEventUncheckedInternal(event);
6944        }
6945    }
6946
6947    /**
6948     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6949     *
6950     * Note: Called from the default {@link AccessibilityDelegate}.
6951     *
6952     * @hide
6953     */
6954    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6955        if (!isShown()) {
6956            return;
6957        }
6958        onInitializeAccessibilityEvent(event);
6959        // Only a subset of accessibility events populates text content.
6960        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6961            dispatchPopulateAccessibilityEvent(event);
6962        }
6963        // In the beginning we called #isShown(), so we know that getParent() is not null.
6964        ViewParent parent = getParent();
6965        if (parent != null) {
6966            getParent().requestSendAccessibilityEvent(this, event);
6967        }
6968    }
6969
6970    /**
6971     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6972     * to its children for adding their text content to the event. Note that the
6973     * event text is populated in a separate dispatch path since we add to the
6974     * event not only the text of the source but also the text of all its descendants.
6975     * A typical implementation will call
6976     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6977     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6978     * on each child. Override this method if custom population of the event text
6979     * content is required.
6980     * <p>
6981     * If an {@link AccessibilityDelegate} has been specified via calling
6982     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6983     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6984     * is responsible for handling this call.
6985     * </p>
6986     * <p>
6987     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6988     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6989     * </p>
6990     *
6991     * @param event The event.
6992     *
6993     * @return True if the event population was completed.
6994     */
6995    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6996        if (mAccessibilityDelegate != null) {
6997            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6998        } else {
6999            return dispatchPopulateAccessibilityEventInternal(event);
7000        }
7001    }
7002
7003    /**
7004     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7005     *
7006     * Note: Called from the default {@link AccessibilityDelegate}.
7007     *
7008     * @hide
7009     */
7010    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7011        onPopulateAccessibilityEvent(event);
7012        return false;
7013    }
7014
7015    /**
7016     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7017     * giving a chance to this View to populate the accessibility event with its
7018     * text content. While this method is free to modify event
7019     * attributes other than text content, doing so should normally be performed in
7020     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7021     * <p>
7022     * Example: Adding formatted date string to an accessibility event in addition
7023     *          to the text added by the super implementation:
7024     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7025     *     super.onPopulateAccessibilityEvent(event);
7026     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7027     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7028     *         mCurrentDate.getTimeInMillis(), flags);
7029     *     event.getText().add(selectedDateUtterance);
7030     * }</pre>
7031     * <p>
7032     * If an {@link AccessibilityDelegate} has been specified via calling
7033     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7034     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7035     * is responsible for handling this call.
7036     * </p>
7037     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7038     * information to the event, in case the default implementation has basic information to add.
7039     * </p>
7040     *
7041     * @param event The accessibility event which to populate.
7042     *
7043     * @see #sendAccessibilityEvent(int)
7044     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7045     */
7046    @CallSuper
7047    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7048        if (mAccessibilityDelegate != null) {
7049            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7050        } else {
7051            onPopulateAccessibilityEventInternal(event);
7052        }
7053    }
7054
7055    /**
7056     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7057     *
7058     * Note: Called from the default {@link AccessibilityDelegate}.
7059     *
7060     * @hide
7061     */
7062    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7063    }
7064
7065    /**
7066     * Initializes an {@link AccessibilityEvent} with information about
7067     * this View which is the event source. In other words, the source of
7068     * an accessibility event is the view whose state change triggered firing
7069     * the event.
7070     * <p>
7071     * Example: Setting the password property of an event in addition
7072     *          to properties set by the super implementation:
7073     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7074     *     super.onInitializeAccessibilityEvent(event);
7075     *     event.setPassword(true);
7076     * }</pre>
7077     * <p>
7078     * If an {@link AccessibilityDelegate} has been specified via calling
7079     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7080     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7081     * is responsible for handling this call.
7082     * </p>
7083     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7084     * information to the event, in case the default implementation has basic information to add.
7085     * </p>
7086     * @param event The event to initialize.
7087     *
7088     * @see #sendAccessibilityEvent(int)
7089     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7090     */
7091    @CallSuper
7092    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7093        if (mAccessibilityDelegate != null) {
7094            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7095        } else {
7096            onInitializeAccessibilityEventInternal(event);
7097        }
7098    }
7099
7100    /**
7101     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7102     *
7103     * Note: Called from the default {@link AccessibilityDelegate}.
7104     *
7105     * @hide
7106     */
7107    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7108        event.setSource(this);
7109        event.setClassName(getAccessibilityClassName());
7110        event.setPackageName(getContext().getPackageName());
7111        event.setEnabled(isEnabled());
7112        event.setContentDescription(mContentDescription);
7113
7114        switch (event.getEventType()) {
7115            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7116                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7117                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7118                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7119                event.setItemCount(focusablesTempList.size());
7120                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7121                if (mAttachInfo != null) {
7122                    focusablesTempList.clear();
7123                }
7124            } break;
7125            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7126                CharSequence text = getIterableTextForAccessibility();
7127                if (text != null && text.length() > 0) {
7128                    event.setFromIndex(getAccessibilitySelectionStart());
7129                    event.setToIndex(getAccessibilitySelectionEnd());
7130                    event.setItemCount(text.length());
7131                }
7132            } break;
7133        }
7134    }
7135
7136    /**
7137     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7138     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7139     * This method is responsible for obtaining an accessibility node info from a
7140     * pool of reusable instances and calling
7141     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7142     * initialize the former.
7143     * <p>
7144     * Note: The client is responsible for recycling the obtained instance by calling
7145     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7146     * </p>
7147     *
7148     * @return A populated {@link AccessibilityNodeInfo}.
7149     *
7150     * @see AccessibilityNodeInfo
7151     */
7152    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7153        if (mAccessibilityDelegate != null) {
7154            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7155        } else {
7156            return createAccessibilityNodeInfoInternal();
7157        }
7158    }
7159
7160    /**
7161     * @see #createAccessibilityNodeInfo()
7162     *
7163     * @hide
7164     */
7165    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7166        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7167        if (provider != null) {
7168            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7169        } else {
7170            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7171            onInitializeAccessibilityNodeInfo(info);
7172            return info;
7173        }
7174    }
7175
7176    /**
7177     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7178     * The base implementation sets:
7179     * <ul>
7180     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7181     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7182     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7183     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7184     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7185     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7186     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7187     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7188     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7189     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7190     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7191     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7192     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7193     * </ul>
7194     * <p>
7195     * Subclasses should override this method, call the super implementation,
7196     * and set additional attributes.
7197     * </p>
7198     * <p>
7199     * If an {@link AccessibilityDelegate} has been specified via calling
7200     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7201     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7202     * is responsible for handling this call.
7203     * </p>
7204     *
7205     * @param info The instance to initialize.
7206     */
7207    @CallSuper
7208    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7209        if (mAccessibilityDelegate != null) {
7210            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7211        } else {
7212            onInitializeAccessibilityNodeInfoInternal(info);
7213        }
7214    }
7215
7216    /**
7217     * Gets the location of this view in screen coordinates.
7218     *
7219     * @param outRect The output location
7220     * @hide
7221     */
7222    public void getBoundsOnScreen(Rect outRect) {
7223        getBoundsOnScreen(outRect, false);
7224    }
7225
7226    /**
7227     * Gets the location of this view in screen coordinates.
7228     *
7229     * @param outRect The output location
7230     * @param clipToParent Whether to clip child bounds to the parent ones.
7231     * @hide
7232     */
7233    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7234        if (mAttachInfo == null) {
7235            return;
7236        }
7237
7238        RectF position = mAttachInfo.mTmpTransformRect;
7239        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7240        mapRectFromViewToScreenCoords(position, clipToParent);
7241        outRect.set(Math.round(position.left), Math.round(position.top),
7242                Math.round(position.right), Math.round(position.bottom));
7243    }
7244
7245    /**
7246     * Map a rectangle from view-relative coordinates to screen-relative coordinates
7247     *
7248     * @param rect The rectangle to be mapped
7249     * @param clipToParent Whether to clip child bounds to the parent ones.
7250     * @hide
7251     */
7252    public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7253        if (!hasIdentityMatrix()) {
7254            getMatrix().mapRect(rect);
7255        }
7256
7257        rect.offset(mLeft, mTop);
7258
7259        ViewParent parent = mParent;
7260        while (parent instanceof View) {
7261            View parentView = (View) parent;
7262
7263            rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7264
7265            if (clipToParent) {
7266                rect.left = Math.max(rect.left, 0);
7267                rect.top = Math.max(rect.top, 0);
7268                rect.right = Math.min(rect.right, parentView.getWidth());
7269                rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7270            }
7271
7272            if (!parentView.hasIdentityMatrix()) {
7273                parentView.getMatrix().mapRect(rect);
7274            }
7275
7276            rect.offset(parentView.mLeft, parentView.mTop);
7277
7278            parent = parentView.mParent;
7279        }
7280
7281        if (parent instanceof ViewRootImpl) {
7282            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7283            rect.offset(0, -viewRootImpl.mCurScrollY);
7284        }
7285
7286        rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7287    }
7288
7289    /**
7290     * Return the class name of this object to be used for accessibility purposes.
7291     * Subclasses should only override this if they are implementing something that
7292     * should be seen as a completely new class of view when used by accessibility,
7293     * unrelated to the class it is deriving from.  This is used to fill in
7294     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7295     */
7296    public CharSequence getAccessibilityClassName() {
7297        return View.class.getName();
7298    }
7299
7300    /**
7301     * Called when assist structure is being retrieved from a view as part of
7302     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7303     * @param structure Fill in with structured view data.  The default implementation
7304     * fills in all data that can be inferred from the view itself.
7305     */
7306    public void onProvideStructure(ViewStructure structure) {
7307        onProvideStructureForAssistOrAutofill(structure, false);
7308    }
7309
7310    /**
7311     * Called when assist structure is being retrieved from a view as part of an autofill request.
7312     *
7313     * <p>This method already provides most of what's needed for autofill, but should be overridden
7314     * when:
7315     * <ul>
7316     *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7317     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7318     *   <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7319     * {@link ViewStructure#setAutofillOptions(CharSequence[])},
7320     * or {@link ViewStructure#setWebDomain(String)}.
7321     * </ul>
7322     *
7323     * @param structure Fill in with structured view data. The default implementation
7324     * fills in all data that can be inferred from the view itself.
7325     * @param flags optional flags.
7326     *
7327     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7328     */
7329    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
7330        onProvideStructureForAssistOrAutofill(structure, true);
7331    }
7332
7333    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7334            boolean forAutofill) {
7335        final int id = mID;
7336        if (id != NO_ID && !isViewIdGenerated(id)) {
7337            String pkg, type, entry;
7338            try {
7339                final Resources res = getResources();
7340                entry = res.getResourceEntryName(id);
7341                type = res.getResourceTypeName(id);
7342                pkg = res.getResourcePackageName(id);
7343            } catch (Resources.NotFoundException e) {
7344                entry = type = pkg = null;
7345            }
7346            structure.setId(id, pkg, type, entry);
7347        } else {
7348            structure.setId(id, null, null, null);
7349        }
7350
7351        if (forAutofill) {
7352            final @AutofillType int autofillType = getAutofillType();
7353            // Don't need to fill autofill info if view does not support it.
7354            // For example, only TextViews that are editable support autofill
7355            if (autofillType != AUTOFILL_TYPE_NONE) {
7356                structure.setAutofillType(autofillType);
7357                structure.setAutofillHints(getAutofillHints());
7358                structure.setAutofillValue(getAutofillValue());
7359            }
7360        }
7361
7362        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
7363        if (!forAutofill) {
7364            if (!hasIdentityMatrix()) {
7365                structure.setTransformation(getMatrix());
7366            }
7367            structure.setElevation(getZ());
7368        }
7369        structure.setVisibility(getVisibility());
7370        structure.setEnabled(isEnabled());
7371        if (isClickable()) {
7372            structure.setClickable(true);
7373        }
7374        if (isFocusable()) {
7375            structure.setFocusable(true);
7376        }
7377        if (isFocused()) {
7378            structure.setFocused(true);
7379        }
7380        if (isAccessibilityFocused()) {
7381            structure.setAccessibilityFocused(true);
7382        }
7383        if (isSelected()) {
7384            structure.setSelected(true);
7385        }
7386        if (isActivated()) {
7387            structure.setActivated(true);
7388        }
7389        if (isLongClickable()) {
7390            structure.setLongClickable(true);
7391        }
7392        if (this instanceof Checkable) {
7393            structure.setCheckable(true);
7394            if (((Checkable)this).isChecked()) {
7395                structure.setChecked(true);
7396            }
7397        }
7398        if (isOpaque()) {
7399            structure.setOpaque(true);
7400        }
7401        if (isContextClickable()) {
7402            structure.setContextClickable(true);
7403        }
7404        structure.setClassName(getAccessibilityClassName().toString());
7405        structure.setContentDescription(getContentDescription());
7406    }
7407
7408    /**
7409     * Called when assist structure is being retrieved from a view as part of
7410     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7411     * generate additional virtual structure under this view.  The defaullt implementation
7412     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7413     * view's virtual accessibility nodes, if any.  You can override this for a more
7414     * optimal implementation providing this data.
7415     */
7416    public void onProvideVirtualStructure(ViewStructure structure) {
7417        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7418        if (provider != null) {
7419            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7420            structure.setChildCount(1);
7421            ViewStructure root = structure.newChild(0);
7422            populateVirtualStructure(root, provider, info);
7423            info.recycle();
7424        }
7425    }
7426
7427    /**
7428     * Called when assist structure is being retrieved from a view as part of an autofill request
7429     * to generate additional virtual structure under this view.
7430     *
7431     * <p>When implementing this method, subclasses must follow the rules below:
7432     *
7433     * <ol>
7434     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7435     * children.
7436     * <li>Call
7437     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7438     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7439     * when the focus inside the view changed.
7440     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7441     * AutofillValue)} when the value of a child changed.
7442     * <li>Call {@link AutofillManager#commit()} when the autofill context
7443     * of the view structure changed and you want the current autofill interaction if such
7444     * to be commited.
7445     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7446     * of the view structure changed and you want the current autofill interaction if such
7447     * to be cancelled.
7448     * </ol>
7449     *
7450     * @param structure Fill in with structured view data.
7451     * @param flags optional flags (currently {@code 0}).
7452     */
7453    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7454    }
7455
7456    /**
7457     * Automatically fills the content of this view with the {@code value}.
7458     *
7459     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7460     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7461     * to support the Autofill Framework.
7462     *
7463     * <p>Typically, it is implemented by:
7464     *
7465     * <ol>
7466     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7467     * <li>Passing the actual value to the equivalent setter in the view.
7468     * </ol>
7469     *
7470     * <p>For example, a text-field view would call:
7471     * <pre class="prettyprint">
7472     * CharSequence text = value.getTextValue();
7473     * if (text != null) {
7474     *     setText(text);
7475     * }
7476     * </pre>
7477     *
7478     * <p>If the value is updated asyncronously the next call to
7479     * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
7480     * changed to the autofilled value. If not, the view will not be considered autofilled.
7481     *
7482     * @param value value to be autofilled.
7483     */
7484    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7485    }
7486
7487    /**
7488     * Automatically fills the content of a virtual views.
7489     *
7490     * <p>See {@link #autofill(AutofillValue)} and
7491     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7492     * <p>To indicate that a virtual view was autofilled
7493     * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7494     * changes.
7495     *
7496     * @param values map of values to be autofilled, keyed by virtual child id.
7497     *
7498     * @attr ref android.R.styleable#Theme_autofilledHighlight
7499     */
7500    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7501    }
7502
7503    /**
7504     * Gets the unique identifier of this view on the screen for Autofill purposes.
7505     *
7506     * @return The View's Autofill id.
7507     */
7508    public final AutofillId getAutofillId() {
7509        if (mAutofillId == null) {
7510            // The autofill id needs to be unique, but its value doesn't matter,
7511            // so it's better to reuse the accessibility id to save space.
7512            mAutofillId = new AutofillId(getAccessibilityViewId());
7513        }
7514        return mAutofillId;
7515    }
7516
7517    /**
7518     * Describes the autofill type that should be used on calls to
7519     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7520     *
7521     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7522     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7523     */
7524    public @AutofillType int getAutofillType() {
7525        return AUTOFILL_TYPE_NONE;
7526    }
7527
7528    /**
7529     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7530     *
7531     * @return The hints set via the attribute or {@code null} if no hint it set.
7532     *
7533     * @attr ref android.R.styleable#View_autofillHints
7534     */
7535    @ViewDebug.ExportedProperty()
7536    @Nullable public String[] getAutofillHints() {
7537        return mAutofillHints;
7538    }
7539
7540    /**
7541     * @hide
7542     */
7543    public boolean isAutofilled() {
7544        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7545    }
7546
7547    /**
7548     * Gets the {@link View}'s current autofill value.
7549     *
7550     * <p>By default returns {@code null}, but views should override it (and
7551     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7552     * Framework.
7553     */
7554    @Nullable
7555    public AutofillValue getAutofillValue() {
7556        return null;
7557    }
7558
7559    /**
7560     * Gets the mode for determining whether this View is important for autofill.
7561     *
7562     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7563     *
7564     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7565     * {@link #setImportantForAutofill(int)}.
7566     *
7567     * @attr ref android.R.styleable#View_importantForAutofill
7568     */
7569    @ViewDebug.ExportedProperty(mapping = {
7570            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7571            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7572            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7573            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7574                to = "yesExcludeDescendants"),
7575            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7576                to = "noExcludeDescendants")})
7577    public @AutofillImportance int getImportantForAutofill() {
7578        return (mPrivateFlags3
7579                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7580    }
7581
7582    /**
7583     * Sets the mode for determining whether this View is important for autofill.
7584     *
7585     * <p>This property controls how this view is presented to the autofill components
7586     * which help users to fill credentials, addresses, etc. For example, views
7587     * that contain labels and input fields are useful for autofill components to
7588     * determine the user context and provide values for the inputs. Note that the
7589     * user can always override this by manually triggering autotill which would
7590     * expose the view to the autofill provider.
7591     *
7592     * <p>The platform determines the importance for autofill automatically but you
7593     * can use this method to customize the behavior. See the autofill modes below
7594     * for more details.
7595     *
7596     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7597     *
7598     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7599     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7600     * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7601     *
7602     * @attr ref android.R.styleable#View_importantForAutofill
7603     */
7604    public void setImportantForAutofill(@AutofillImportance int mode) {
7605        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7606        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7607                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7608    }
7609
7610    /**
7611     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7612     * associated with this View should be included in a {@link ViewStructure} used for
7613     * autofill purposes.
7614     *
7615     * <p>Generally speaking, a view is important for autofill if:
7616     * <ol>
7617     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7618     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7619     * autofill other views.
7620     * <ol>
7621     *
7622     * <p>For example, view containers should typically return {@code false} for performance reasons
7623     * (since the important info is provided by their children), but if the container is actually
7624     * whose children are part of a compound view, it should return {@code true} (and then override
7625     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7626     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7627     * the structure). On the other hand, views representing labels or editable fields should
7628     * typically return {@code true}, but in some cases they could return {@code false} (for
7629     * example, if they're part of a "Captcha" mechanism).
7630     *
7631     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7632     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7633     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7634     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7635     * should use {@link #setImportantForAutofill(int)} instead.
7636     *
7637     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7638     * excluded from the structure; for example, if the user explicitly requested autofill, the
7639     * View might be always included.
7640     *
7641     * <p>This decision applies just for the view, not its children - if the view children are not
7642     * important for autofill, the view should override
7643     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7644     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7645     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7646     *
7647     * @return whether the view is considered important for autofill.
7648     *
7649     * @see #setImportantForAutofill(int)
7650     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7651     * @see #IMPORTANT_FOR_AUTOFILL_YES
7652     * @see #IMPORTANT_FOR_AUTOFILL_NO
7653     * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7654     * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7655     */
7656    public final boolean isImportantForAutofill() {
7657        // Check parent mode to ensure we're not hidden.
7658        ViewParent parent = mParent;
7659        while (parent instanceof View) {
7660            final int parentImportance = ((View) parent).getImportantForAutofill();
7661            if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7662                    || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7663                return false;
7664            }
7665            parent = parent.getParent();
7666        }
7667
7668        final int importance = getImportantForAutofill();
7669
7670        // First, check the explicit states.
7671        if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7672                || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7673            return true;
7674        }
7675        if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7676                || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7677            return false;
7678        }
7679
7680        // Then use some heuristics to handle AUTO.
7681
7682        // Always include views that have an explicit resource id.
7683        final int id = mID;
7684        if (id != NO_ID && !isViewIdGenerated(id)) {
7685            final Resources res = getResources();
7686            String entry = null;
7687            String pkg = null;
7688            try {
7689                entry = res.getResourceEntryName(id);
7690                pkg = res.getResourcePackageName(id);
7691            } catch (Resources.NotFoundException e) {
7692                // ignore
7693            }
7694            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7695                return true;
7696            }
7697        }
7698
7699        // Otherwise, assume it's not important...
7700        return false;
7701    }
7702
7703    @Nullable
7704    private AutofillManager getAutofillManager() {
7705        return mContext.getSystemService(AutofillManager.class);
7706    }
7707
7708    private boolean isAutofillable() {
7709        return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill();
7710    }
7711
7712    private void populateVirtualStructure(ViewStructure structure,
7713            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
7714        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7715                null, null, null);
7716        Rect rect = structure.getTempRect();
7717        info.getBoundsInParent(rect);
7718        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7719        structure.setVisibility(VISIBLE);
7720        structure.setEnabled(info.isEnabled());
7721        if (info.isClickable()) {
7722            structure.setClickable(true);
7723        }
7724        if (info.isFocusable()) {
7725            structure.setFocusable(true);
7726        }
7727        if (info.isFocused()) {
7728            structure.setFocused(true);
7729        }
7730        if (info.isAccessibilityFocused()) {
7731            structure.setAccessibilityFocused(true);
7732        }
7733        if (info.isSelected()) {
7734            structure.setSelected(true);
7735        }
7736        if (info.isLongClickable()) {
7737            structure.setLongClickable(true);
7738        }
7739        if (info.isCheckable()) {
7740            structure.setCheckable(true);
7741            if (info.isChecked()) {
7742                structure.setChecked(true);
7743            }
7744        }
7745        if (info.isContextClickable()) {
7746            structure.setContextClickable(true);
7747        }
7748        CharSequence cname = info.getClassName();
7749        structure.setClassName(cname != null ? cname.toString() : null);
7750        structure.setContentDescription(info.getContentDescription());
7751        if ((info.getText() != null || info.getError() != null)) {
7752            structure.setText(info.getText(), info.getTextSelectionStart(),
7753                    info.getTextSelectionEnd());
7754        }
7755        final int NCHILDREN = info.getChildCount();
7756        if (NCHILDREN > 0) {
7757            structure.setChildCount(NCHILDREN);
7758            for (int i=0; i<NCHILDREN; i++) {
7759                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7760                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7761                ViewStructure child = structure.newChild(i);
7762                populateVirtualStructure(child, provider, cinfo);
7763                cinfo.recycle();
7764            }
7765        }
7766    }
7767
7768    /**
7769     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7770     * implementation calls {@link #onProvideStructure} and
7771     * {@link #onProvideVirtualStructure}.
7772     */
7773    public void dispatchProvideStructure(ViewStructure structure) {
7774        dispatchProvideStructureForAssistOrAutofill(structure, false);
7775    }
7776
7777    /**
7778     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7779     *
7780     * <p>The default implementation does the following:
7781     *
7782     * <ul>
7783     *   <li>Sets the {@link AutofillId} in the structure.
7784     *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
7785     *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7786     * </ul>
7787     *
7788     * <p>When overridden, it must either call
7789     * {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
7790     * set the {@link AutofillId} in the structure (for example, by calling
7791     * {@code structure.setAutofillId(getAutofillId())}).
7792     *
7793     * <p>When providing your implementation you need to decide how to handle
7794     * the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag which instructs you
7795     * to report all views to the structure regardless if {@link #isImportantForAutofill()}
7796     * returns true. We encourage you respect the importance property for a better
7797     * user experience in your app. If the flag is not set then you should filter out
7798     * not important views to optimize autofill performance in your app.
7799     *
7800     * @param structure Fill in with structured view data.
7801     * @param flags optional flags.
7802     *
7803     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7804     */
7805    public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
7806            @AutofillFlags int flags) {
7807        dispatchProvideStructureForAssistOrAutofill(structure, true);
7808    }
7809
7810    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7811            boolean forAutofill) {
7812        if (forAutofill) {
7813            structure.setAutofillId(getAutofillId());
7814            // NOTE: flags are not currently supported, hence 0
7815            onProvideAutofillStructure(structure, 0);
7816            onProvideAutofillVirtualStructure(structure, 0);
7817        } else if (!isAssistBlocked()) {
7818            onProvideStructure(structure);
7819            onProvideVirtualStructure(structure);
7820        } else {
7821            structure.setClassName(getAccessibilityClassName().toString());
7822            structure.setAssistBlocked(true);
7823        }
7824    }
7825
7826    /**
7827     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7828     *
7829     * Note: Called from the default {@link AccessibilityDelegate}.
7830     *
7831     * @hide
7832     */
7833    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7834        if (mAttachInfo == null) {
7835            return;
7836        }
7837
7838        Rect bounds = mAttachInfo.mTmpInvalRect;
7839
7840        getDrawingRect(bounds);
7841        info.setBoundsInParent(bounds);
7842
7843        getBoundsOnScreen(bounds, true);
7844        info.setBoundsInScreen(bounds);
7845
7846        ViewParent parent = getParentForAccessibility();
7847        if (parent instanceof View) {
7848            info.setParent((View) parent);
7849        }
7850
7851        if (mID != View.NO_ID) {
7852            View rootView = getRootView();
7853            if (rootView == null) {
7854                rootView = this;
7855            }
7856
7857            View label = rootView.findLabelForView(this, mID);
7858            if (label != null) {
7859                info.setLabeledBy(label);
7860            }
7861
7862            if ((mAttachInfo.mAccessibilityFetchFlags
7863                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7864                    && Resources.resourceHasPackage(mID)) {
7865                try {
7866                    String viewId = getResources().getResourceName(mID);
7867                    info.setViewIdResourceName(viewId);
7868                } catch (Resources.NotFoundException nfe) {
7869                    /* ignore */
7870                }
7871            }
7872        }
7873
7874        if (mLabelForId != View.NO_ID) {
7875            View rootView = getRootView();
7876            if (rootView == null) {
7877                rootView = this;
7878            }
7879            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7880            if (labeled != null) {
7881                info.setLabelFor(labeled);
7882            }
7883        }
7884
7885        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7886            View rootView = getRootView();
7887            if (rootView == null) {
7888                rootView = this;
7889            }
7890            View next = rootView.findViewInsideOutShouldExist(this,
7891                    mAccessibilityTraversalBeforeId);
7892            if (next != null && next.includeForAccessibility()) {
7893                info.setTraversalBefore(next);
7894            }
7895        }
7896
7897        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7898            View rootView = getRootView();
7899            if (rootView == null) {
7900                rootView = this;
7901            }
7902            View next = rootView.findViewInsideOutShouldExist(this,
7903                    mAccessibilityTraversalAfterId);
7904            if (next != null && next.includeForAccessibility()) {
7905                info.setTraversalAfter(next);
7906            }
7907        }
7908
7909        info.setVisibleToUser(isVisibleToUser());
7910
7911        info.setImportantForAccessibility(isImportantForAccessibility());
7912        info.setPackageName(mContext.getPackageName());
7913        info.setClassName(getAccessibilityClassName());
7914        info.setContentDescription(getContentDescription());
7915
7916        info.setEnabled(isEnabled());
7917        info.setClickable(isClickable());
7918        info.setFocusable(isFocusable());
7919        info.setFocused(isFocused());
7920        info.setAccessibilityFocused(isAccessibilityFocused());
7921        info.setSelected(isSelected());
7922        info.setLongClickable(isLongClickable());
7923        info.setContextClickable(isContextClickable());
7924        info.setLiveRegion(getAccessibilityLiveRegion());
7925
7926        // TODO: These make sense only if we are in an AdapterView but all
7927        // views can be selected. Maybe from accessibility perspective
7928        // we should report as selectable view in an AdapterView.
7929        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7930        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7931
7932        if (isFocusable()) {
7933            if (isFocused()) {
7934                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7935            } else {
7936                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7937            }
7938        }
7939
7940        if (!isAccessibilityFocused()) {
7941            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7942        } else {
7943            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7944        }
7945
7946        if (isClickable() && isEnabled()) {
7947            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7948        }
7949
7950        if (isLongClickable() && isEnabled()) {
7951            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7952        }
7953
7954        if (isContextClickable() && isEnabled()) {
7955            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7956        }
7957
7958        CharSequence text = getIterableTextForAccessibility();
7959        if (text != null && text.length() > 0) {
7960            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7961
7962            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7963            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7964            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7965            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7966                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7967                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7968        }
7969
7970        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7971        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7972    }
7973
7974    /**
7975     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7976     * additional data.
7977     * <p>
7978     * This method only needs overloading if the node is marked as having extra data available.
7979     * </p>
7980     *
7981     * @param info The info to which to add the extra data. Never {@code null}.
7982     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7983     *                     extra data should be added to the {@link Bundle} returned by
7984     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7985     *                     {@code null}.
7986     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7987     *                  {@code null} if the service provided no arguments.
7988     *
7989     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
7990     */
7991    public void addExtraDataToAccessibilityNodeInfo(
7992            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7993            @Nullable Bundle arguments) {
7994    }
7995
7996    /**
7997     * Determine the order in which this view will be drawn relative to its siblings for a11y
7998     *
7999     * @param info The info whose drawing order should be populated
8000     */
8001    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8002        /*
8003         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8004         * drawing order may not be well-defined, and some Views with custom drawing order may
8005         * not be initialized sufficiently to respond properly getChildDrawingOrder.
8006         */
8007        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8008            info.setDrawingOrder(0);
8009            return;
8010        }
8011        int drawingOrderInParent = 1;
8012        // Iterate up the hierarchy if parents are not important for a11y
8013        View viewAtDrawingLevel = this;
8014        final ViewParent parent = getParentForAccessibility();
8015        while (viewAtDrawingLevel != parent) {
8016            final ViewParent currentParent = viewAtDrawingLevel.getParent();
8017            if (!(currentParent instanceof ViewGroup)) {
8018                // Should only happen for the Decor
8019                drawingOrderInParent = 0;
8020                break;
8021            } else {
8022                final ViewGroup parentGroup = (ViewGroup) currentParent;
8023                final int childCount = parentGroup.getChildCount();
8024                if (childCount > 1) {
8025                    List<View> preorderedList = parentGroup.buildOrderedChildList();
8026                    if (preorderedList != null) {
8027                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8028                        for (int i = 0; i < childDrawIndex; i++) {
8029                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8030                        }
8031                    } else {
8032                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8033                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8034                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8035                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
8036                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8037                        if (childDrawIndex != 0) {
8038                            for (int i = 0; i < numChildrenToIterate; i++) {
8039                                final int otherDrawIndex = (customOrder ?
8040                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
8041                                if (otherDrawIndex < childDrawIndex) {
8042                                    drawingOrderInParent +=
8043                                            numViewsForAccessibility(parentGroup.getChildAt(i));
8044                                }
8045                            }
8046                        }
8047                    }
8048                }
8049            }
8050            viewAtDrawingLevel = (View) currentParent;
8051        }
8052        info.setDrawingOrder(drawingOrderInParent);
8053    }
8054
8055    private static int numViewsForAccessibility(View view) {
8056        if (view != null) {
8057            if (view.includeForAccessibility()) {
8058                return 1;
8059            } else if (view instanceof ViewGroup) {
8060                return ((ViewGroup) view).getNumChildrenForAccessibility();
8061            }
8062        }
8063        return 0;
8064    }
8065
8066    private View findLabelForView(View view, int labeledId) {
8067        if (mMatchLabelForPredicate == null) {
8068            mMatchLabelForPredicate = new MatchLabelForPredicate();
8069        }
8070        mMatchLabelForPredicate.mLabeledId = labeledId;
8071        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8072    }
8073
8074    /**
8075     * Computes whether this view is visible to the user. Such a view is
8076     * attached, visible, all its predecessors are visible, it is not clipped
8077     * entirely by its predecessors, and has an alpha greater than zero.
8078     *
8079     * @return Whether the view is visible on the screen.
8080     *
8081     * @hide
8082     */
8083    protected boolean isVisibleToUser() {
8084        return isVisibleToUser(null);
8085    }
8086
8087    /**
8088     * Computes whether the given portion of this view is visible to the user.
8089     * Such a view is attached, visible, all its predecessors are visible,
8090     * has an alpha greater than zero, and the specified portion is not
8091     * clipped entirely by its predecessors.
8092     *
8093     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8094     *                    <code>null</code>, and the entire view will be tested in this case.
8095     *                    When <code>true</code> is returned by the function, the actual visible
8096     *                    region will be stored in this parameter; that is, if boundInView is fully
8097     *                    contained within the view, no modification will be made, otherwise regions
8098     *                    outside of the visible area of the view will be clipped.
8099     *
8100     * @return Whether the specified portion of the view is visible on the screen.
8101     *
8102     * @hide
8103     */
8104    protected boolean isVisibleToUser(Rect boundInView) {
8105        if (mAttachInfo != null) {
8106            // Attached to invisible window means this view is not visible.
8107            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8108                return false;
8109            }
8110            // An invisible predecessor or one with alpha zero means
8111            // that this view is not visible to the user.
8112            Object current = this;
8113            while (current instanceof View) {
8114                View view = (View) current;
8115                // We have attach info so this view is attached and there is no
8116                // need to check whether we reach to ViewRootImpl on the way up.
8117                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8118                        view.getVisibility() != VISIBLE) {
8119                    return false;
8120                }
8121                current = view.mParent;
8122            }
8123            // Check if the view is entirely covered by its predecessors.
8124            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8125            Point offset = mAttachInfo.mPoint;
8126            if (!getGlobalVisibleRect(visibleRect, offset)) {
8127                return false;
8128            }
8129            // Check if the visible portion intersects the rectangle of interest.
8130            if (boundInView != null) {
8131                visibleRect.offset(-offset.x, -offset.y);
8132                return boundInView.intersect(visibleRect);
8133            }
8134            return true;
8135        }
8136        return false;
8137    }
8138
8139    /**
8140     * Returns the delegate for implementing accessibility support via
8141     * composition. For more details see {@link AccessibilityDelegate}.
8142     *
8143     * @return The delegate, or null if none set.
8144     *
8145     * @hide
8146     */
8147    public AccessibilityDelegate getAccessibilityDelegate() {
8148        return mAccessibilityDelegate;
8149    }
8150
8151    /**
8152     * Sets a delegate for implementing accessibility support via composition
8153     * (as opposed to inheritance). For more details, see
8154     * {@link AccessibilityDelegate}.
8155     * <p>
8156     * <strong>Note:</strong> On platform versions prior to
8157     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8158     * views in the {@code android.widget.*} package are called <i>before</i>
8159     * host methods. This prevents certain properties such as class name from
8160     * being modified by overriding
8161     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8162     * as any changes will be overwritten by the host class.
8163     * <p>
8164     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8165     * methods are called <i>after</i> host methods, which all properties to be
8166     * modified without being overwritten by the host class.
8167     *
8168     * @param delegate the object to which accessibility method calls should be
8169     *                 delegated
8170     * @see AccessibilityDelegate
8171     */
8172    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8173        mAccessibilityDelegate = delegate;
8174    }
8175
8176    /**
8177     * Gets the provider for managing a virtual view hierarchy rooted at this View
8178     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8179     * that explore the window content.
8180     * <p>
8181     * If this method returns an instance, this instance is responsible for managing
8182     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8183     * View including the one representing the View itself. Similarly the returned
8184     * instance is responsible for performing accessibility actions on any virtual
8185     * view or the root view itself.
8186     * </p>
8187     * <p>
8188     * If an {@link AccessibilityDelegate} has been specified via calling
8189     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8190     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8191     * is responsible for handling this call.
8192     * </p>
8193     *
8194     * @return The provider.
8195     *
8196     * @see AccessibilityNodeProvider
8197     */
8198    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8199        if (mAccessibilityDelegate != null) {
8200            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8201        } else {
8202            return null;
8203        }
8204    }
8205
8206    /**
8207     * Gets the unique identifier of this view on the screen for accessibility purposes.
8208     *
8209     * @return The view accessibility id.
8210     *
8211     * @hide
8212     */
8213    public int getAccessibilityViewId() {
8214        if (mAccessibilityViewId == NO_ID) {
8215            mAccessibilityViewId = mContext.getNextAccessibilityId();
8216        }
8217        return mAccessibilityViewId;
8218    }
8219
8220    /**
8221     * Gets the unique identifier of the window in which this View reseides.
8222     *
8223     * @return The window accessibility id.
8224     *
8225     * @hide
8226     */
8227    public int getAccessibilityWindowId() {
8228        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8229                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8230    }
8231
8232    /**
8233     * Returns the {@link View}'s content description.
8234     * <p>
8235     * <strong>Note:</strong> Do not override this method, as it will have no
8236     * effect on the content description presented to accessibility services.
8237     * You must call {@link #setContentDescription(CharSequence)} to modify the
8238     * content description.
8239     *
8240     * @return the content description
8241     * @see #setContentDescription(CharSequence)
8242     * @attr ref android.R.styleable#View_contentDescription
8243     */
8244    @ViewDebug.ExportedProperty(category = "accessibility")
8245    public CharSequence getContentDescription() {
8246        return mContentDescription;
8247    }
8248
8249    /**
8250     * Sets the {@link View}'s content description.
8251     * <p>
8252     * A content description briefly describes the view and is primarily used
8253     * for accessibility support to determine how a view should be presented to
8254     * the user. In the case of a view with no textual representation, such as
8255     * {@link android.widget.ImageButton}, a useful content description
8256     * explains what the view does. For example, an image button with a phone
8257     * icon that is used to place a call may use "Call" as its content
8258     * description. An image of a floppy disk that is used to save a file may
8259     * use "Save".
8260     *
8261     * @param contentDescription The content description.
8262     * @see #getContentDescription()
8263     * @attr ref android.R.styleable#View_contentDescription
8264     */
8265    @RemotableViewMethod
8266    public void setContentDescription(CharSequence contentDescription) {
8267        if (mContentDescription == null) {
8268            if (contentDescription == null) {
8269                return;
8270            }
8271        } else if (mContentDescription.equals(contentDescription)) {
8272            return;
8273        }
8274        mContentDescription = contentDescription;
8275        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8276        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8277            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8278            notifySubtreeAccessibilityStateChangedIfNeeded();
8279        } else {
8280            notifyViewAccessibilityStateChangedIfNeeded(
8281                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8282        }
8283    }
8284
8285    /**
8286     * Sets the id of a view before which this one is visited in accessibility traversal.
8287     * A screen-reader must visit the content of this view before the content of the one
8288     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8289     * will traverse the entire content of B before traversing the entire content of A,
8290     * regardles of what traversal strategy it is using.
8291     * <p>
8292     * Views that do not have specified before/after relationships are traversed in order
8293     * determined by the screen-reader.
8294     * </p>
8295     * <p>
8296     * Setting that this view is before a view that is not important for accessibility
8297     * or if this view is not important for accessibility will have no effect as the
8298     * screen-reader is not aware of unimportant views.
8299     * </p>
8300     *
8301     * @param beforeId The id of a view this one precedes in accessibility traversal.
8302     *
8303     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8304     *
8305     * @see #setImportantForAccessibility(int)
8306     */
8307    @RemotableViewMethod
8308    public void setAccessibilityTraversalBefore(int beforeId) {
8309        if (mAccessibilityTraversalBeforeId == beforeId) {
8310            return;
8311        }
8312        mAccessibilityTraversalBeforeId = beforeId;
8313        notifyViewAccessibilityStateChangedIfNeeded(
8314                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8315    }
8316
8317    /**
8318     * Gets the id of a view before which this one is visited in accessibility traversal.
8319     *
8320     * @return The id of a view this one precedes in accessibility traversal if
8321     *         specified, otherwise {@link #NO_ID}.
8322     *
8323     * @see #setAccessibilityTraversalBefore(int)
8324     */
8325    public int getAccessibilityTraversalBefore() {
8326        return mAccessibilityTraversalBeforeId;
8327    }
8328
8329    /**
8330     * Sets the id of a view after which this one is visited in accessibility traversal.
8331     * A screen-reader must visit the content of the other view before the content of this
8332     * one. For example, if view B is set to be after view A, then a screen-reader
8333     * will traverse the entire content of A before traversing the entire content of B,
8334     * regardles of what traversal strategy it is using.
8335     * <p>
8336     * Views that do not have specified before/after relationships are traversed in order
8337     * determined by the screen-reader.
8338     * </p>
8339     * <p>
8340     * Setting that this view is after a view that is not important for accessibility
8341     * or if this view is not important for accessibility will have no effect as the
8342     * screen-reader is not aware of unimportant views.
8343     * </p>
8344     *
8345     * @param afterId The id of a view this one succedees in accessibility traversal.
8346     *
8347     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8348     *
8349     * @see #setImportantForAccessibility(int)
8350     */
8351    @RemotableViewMethod
8352    public void setAccessibilityTraversalAfter(int afterId) {
8353        if (mAccessibilityTraversalAfterId == afterId) {
8354            return;
8355        }
8356        mAccessibilityTraversalAfterId = afterId;
8357        notifyViewAccessibilityStateChangedIfNeeded(
8358                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8359    }
8360
8361    /**
8362     * Gets the id of a view after which this one is visited in accessibility traversal.
8363     *
8364     * @return The id of a view this one succeedes in accessibility traversal if
8365     *         specified, otherwise {@link #NO_ID}.
8366     *
8367     * @see #setAccessibilityTraversalAfter(int)
8368     */
8369    public int getAccessibilityTraversalAfter() {
8370        return mAccessibilityTraversalAfterId;
8371    }
8372
8373    /**
8374     * Gets the id of a view for which this view serves as a label for
8375     * accessibility purposes.
8376     *
8377     * @return The labeled view id.
8378     */
8379    @ViewDebug.ExportedProperty(category = "accessibility")
8380    public int getLabelFor() {
8381        return mLabelForId;
8382    }
8383
8384    /**
8385     * Sets the id of a view for which this view serves as a label for
8386     * accessibility purposes.
8387     *
8388     * @param id The labeled view id.
8389     */
8390    @RemotableViewMethod
8391    public void setLabelFor(@IdRes int id) {
8392        if (mLabelForId == id) {
8393            return;
8394        }
8395        mLabelForId = id;
8396        if (mLabelForId != View.NO_ID
8397                && mID == View.NO_ID) {
8398            mID = generateViewId();
8399        }
8400        notifyViewAccessibilityStateChangedIfNeeded(
8401                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8402    }
8403
8404    /**
8405     * Invoked whenever this view loses focus, either by losing window focus or by losing
8406     * focus within its window. This method can be used to clear any state tied to the
8407     * focus. For instance, if a button is held pressed with the trackball and the window
8408     * loses focus, this method can be used to cancel the press.
8409     *
8410     * Subclasses of View overriding this method should always call super.onFocusLost().
8411     *
8412     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8413     * @see #onWindowFocusChanged(boolean)
8414     *
8415     * @hide pending API council approval
8416     */
8417    @CallSuper
8418    protected void onFocusLost() {
8419        resetPressedState();
8420    }
8421
8422    private void resetPressedState() {
8423        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8424            return;
8425        }
8426
8427        if (isPressed()) {
8428            setPressed(false);
8429
8430            if (!mHasPerformedLongPress) {
8431                removeLongPressCallback();
8432            }
8433        }
8434    }
8435
8436    /**
8437     * Returns true if this view has focus
8438     *
8439     * @return True if this view has focus, false otherwise.
8440     */
8441    @ViewDebug.ExportedProperty(category = "focus")
8442    public boolean isFocused() {
8443        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8444    }
8445
8446    /**
8447     * Find the view in the hierarchy rooted at this view that currently has
8448     * focus.
8449     *
8450     * @return The view that currently has focus, or null if no focused view can
8451     *         be found.
8452     */
8453    public View findFocus() {
8454        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8455    }
8456
8457    /**
8458     * Indicates whether this view is one of the set of scrollable containers in
8459     * its window.
8460     *
8461     * @return whether this view is one of the set of scrollable containers in
8462     * its window
8463     *
8464     * @attr ref android.R.styleable#View_isScrollContainer
8465     */
8466    public boolean isScrollContainer() {
8467        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8468    }
8469
8470    /**
8471     * Change whether this view is one of the set of scrollable containers in
8472     * its window.  This will be used to determine whether the window can
8473     * resize or must pan when a soft input area is open -- scrollable
8474     * containers allow the window to use resize mode since the container
8475     * will appropriately shrink.
8476     *
8477     * @attr ref android.R.styleable#View_isScrollContainer
8478     */
8479    public void setScrollContainer(boolean isScrollContainer) {
8480        if (isScrollContainer) {
8481            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8482                mAttachInfo.mScrollContainers.add(this);
8483                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8484            }
8485            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8486        } else {
8487            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8488                mAttachInfo.mScrollContainers.remove(this);
8489            }
8490            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8491        }
8492    }
8493
8494    /**
8495     * Returns the quality of the drawing cache.
8496     *
8497     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8498     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8499     *
8500     * @see #setDrawingCacheQuality(int)
8501     * @see #setDrawingCacheEnabled(boolean)
8502     * @see #isDrawingCacheEnabled()
8503     *
8504     * @attr ref android.R.styleable#View_drawingCacheQuality
8505     */
8506    @DrawingCacheQuality
8507    public int getDrawingCacheQuality() {
8508        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8509    }
8510
8511    /**
8512     * Set the drawing cache quality of this view. This value is used only when the
8513     * drawing cache is enabled
8514     *
8515     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8516     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8517     *
8518     * @see #getDrawingCacheQuality()
8519     * @see #setDrawingCacheEnabled(boolean)
8520     * @see #isDrawingCacheEnabled()
8521     *
8522     * @attr ref android.R.styleable#View_drawingCacheQuality
8523     */
8524    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8525        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8526    }
8527
8528    /**
8529     * Returns whether the screen should remain on, corresponding to the current
8530     * value of {@link #KEEP_SCREEN_ON}.
8531     *
8532     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8533     *
8534     * @see #setKeepScreenOn(boolean)
8535     *
8536     * @attr ref android.R.styleable#View_keepScreenOn
8537     */
8538    public boolean getKeepScreenOn() {
8539        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8540    }
8541
8542    /**
8543     * Controls whether the screen should remain on, modifying the
8544     * value of {@link #KEEP_SCREEN_ON}.
8545     *
8546     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8547     *
8548     * @see #getKeepScreenOn()
8549     *
8550     * @attr ref android.R.styleable#View_keepScreenOn
8551     */
8552    public void setKeepScreenOn(boolean keepScreenOn) {
8553        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8554    }
8555
8556    /**
8557     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8558     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8559     *
8560     * @attr ref android.R.styleable#View_nextFocusLeft
8561     */
8562    public int getNextFocusLeftId() {
8563        return mNextFocusLeftId;
8564    }
8565
8566    /**
8567     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8568     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8569     * decide automatically.
8570     *
8571     * @attr ref android.R.styleable#View_nextFocusLeft
8572     */
8573    public void setNextFocusLeftId(int nextFocusLeftId) {
8574        mNextFocusLeftId = nextFocusLeftId;
8575    }
8576
8577    /**
8578     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8579     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8580     *
8581     * @attr ref android.R.styleable#View_nextFocusRight
8582     */
8583    public int getNextFocusRightId() {
8584        return mNextFocusRightId;
8585    }
8586
8587    /**
8588     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8589     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8590     * decide automatically.
8591     *
8592     * @attr ref android.R.styleable#View_nextFocusRight
8593     */
8594    public void setNextFocusRightId(int nextFocusRightId) {
8595        mNextFocusRightId = nextFocusRightId;
8596    }
8597
8598    /**
8599     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8600     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8601     *
8602     * @attr ref android.R.styleable#View_nextFocusUp
8603     */
8604    public int getNextFocusUpId() {
8605        return mNextFocusUpId;
8606    }
8607
8608    /**
8609     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8610     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8611     * decide automatically.
8612     *
8613     * @attr ref android.R.styleable#View_nextFocusUp
8614     */
8615    public void setNextFocusUpId(int nextFocusUpId) {
8616        mNextFocusUpId = nextFocusUpId;
8617    }
8618
8619    /**
8620     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8621     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8622     *
8623     * @attr ref android.R.styleable#View_nextFocusDown
8624     */
8625    public int getNextFocusDownId() {
8626        return mNextFocusDownId;
8627    }
8628
8629    /**
8630     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8631     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8632     * decide automatically.
8633     *
8634     * @attr ref android.R.styleable#View_nextFocusDown
8635     */
8636    public void setNextFocusDownId(int nextFocusDownId) {
8637        mNextFocusDownId = nextFocusDownId;
8638    }
8639
8640    /**
8641     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8642     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8643     *
8644     * @attr ref android.R.styleable#View_nextFocusForward
8645     */
8646    public int getNextFocusForwardId() {
8647        return mNextFocusForwardId;
8648    }
8649
8650    /**
8651     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8652     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8653     * decide automatically.
8654     *
8655     * @attr ref android.R.styleable#View_nextFocusForward
8656     */
8657    public void setNextFocusForwardId(int nextFocusForwardId) {
8658        mNextFocusForwardId = nextFocusForwardId;
8659    }
8660
8661    /**
8662     * Gets the id of the root of the next keyboard navigation cluster.
8663     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8664     * decide automatically.
8665     *
8666     * @attr ref android.R.styleable#View_nextClusterForward
8667     */
8668    public int getNextClusterForwardId() {
8669        return mNextClusterForwardId;
8670    }
8671
8672    /**
8673     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8674     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8675     * decide automatically.
8676     *
8677     * @attr ref android.R.styleable#View_nextClusterForward
8678     */
8679    public void setNextClusterForwardId(int nextClusterForwardId) {
8680        mNextClusterForwardId = nextClusterForwardId;
8681    }
8682
8683    /**
8684     * Returns the visibility of this view and all of its ancestors
8685     *
8686     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8687     */
8688    public boolean isShown() {
8689        View current = this;
8690        //noinspection ConstantConditions
8691        do {
8692            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8693                return false;
8694            }
8695            ViewParent parent = current.mParent;
8696            if (parent == null) {
8697                return false; // We are not attached to the view root
8698            }
8699            if (!(parent instanceof View)) {
8700                return true;
8701            }
8702            current = (View) parent;
8703        } while (current != null);
8704
8705        return false;
8706    }
8707
8708    /**
8709     * Called by the view hierarchy when the content insets for a window have
8710     * changed, to allow it to adjust its content to fit within those windows.
8711     * The content insets tell you the space that the status bar, input method,
8712     * and other system windows infringe on the application's window.
8713     *
8714     * <p>You do not normally need to deal with this function, since the default
8715     * window decoration given to applications takes care of applying it to the
8716     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8717     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8718     * and your content can be placed under those system elements.  You can then
8719     * use this method within your view hierarchy if you have parts of your UI
8720     * which you would like to ensure are not being covered.
8721     *
8722     * <p>The default implementation of this method simply applies the content
8723     * insets to the view's padding, consuming that content (modifying the
8724     * insets to be 0), and returning true.  This behavior is off by default, but can
8725     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8726     *
8727     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8728     * insets object is propagated down the hierarchy, so any changes made to it will
8729     * be seen by all following views (including potentially ones above in
8730     * the hierarchy since this is a depth-first traversal).  The first view
8731     * that returns true will abort the entire traversal.
8732     *
8733     * <p>The default implementation works well for a situation where it is
8734     * used with a container that covers the entire window, allowing it to
8735     * apply the appropriate insets to its content on all edges.  If you need
8736     * a more complicated layout (such as two different views fitting system
8737     * windows, one on the top of the window, and one on the bottom),
8738     * you can override the method and handle the insets however you would like.
8739     * Note that the insets provided by the framework are always relative to the
8740     * far edges of the window, not accounting for the location of the called view
8741     * within that window.  (In fact when this method is called you do not yet know
8742     * where the layout will place the view, as it is done before layout happens.)
8743     *
8744     * <p>Note: unlike many View methods, there is no dispatch phase to this
8745     * call.  If you are overriding it in a ViewGroup and want to allow the
8746     * call to continue to your children, you must be sure to call the super
8747     * implementation.
8748     *
8749     * <p>Here is a sample layout that makes use of fitting system windows
8750     * to have controls for a video view placed inside of the window decorations
8751     * that it hides and shows.  This can be used with code like the second
8752     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8753     *
8754     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8755     *
8756     * @param insets Current content insets of the window.  Prior to
8757     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8758     * the insets or else you and Android will be unhappy.
8759     *
8760     * @return {@code true} if this view applied the insets and it should not
8761     * continue propagating further down the hierarchy, {@code false} otherwise.
8762     * @see #getFitsSystemWindows()
8763     * @see #setFitsSystemWindows(boolean)
8764     * @see #setSystemUiVisibility(int)
8765     *
8766     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8767     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8768     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8769     * to implement handling their own insets.
8770     */
8771    @Deprecated
8772    protected boolean fitSystemWindows(Rect insets) {
8773        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8774            if (insets == null) {
8775                // Null insets by definition have already been consumed.
8776                // This call cannot apply insets since there are none to apply,
8777                // so return false.
8778                return false;
8779            }
8780            // If we're not in the process of dispatching the newer apply insets call,
8781            // that means we're not in the compatibility path. Dispatch into the newer
8782            // apply insets path and take things from there.
8783            try {
8784                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8785                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8786            } finally {
8787                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8788            }
8789        } else {
8790            // We're being called from the newer apply insets path.
8791            // Perform the standard fallback behavior.
8792            return fitSystemWindowsInt(insets);
8793        }
8794    }
8795
8796    private boolean fitSystemWindowsInt(Rect insets) {
8797        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8798            mUserPaddingStart = UNDEFINED_PADDING;
8799            mUserPaddingEnd = UNDEFINED_PADDING;
8800            Rect localInsets = sThreadLocal.get();
8801            if (localInsets == null) {
8802                localInsets = new Rect();
8803                sThreadLocal.set(localInsets);
8804            }
8805            boolean res = computeFitSystemWindows(insets, localInsets);
8806            mUserPaddingLeftInitial = localInsets.left;
8807            mUserPaddingRightInitial = localInsets.right;
8808            internalSetPadding(localInsets.left, localInsets.top,
8809                    localInsets.right, localInsets.bottom);
8810            return res;
8811        }
8812        return false;
8813    }
8814
8815    /**
8816     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8817     *
8818     * <p>This method should be overridden by views that wish to apply a policy different from or
8819     * in addition to the default behavior. Clients that wish to force a view subtree
8820     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8821     *
8822     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8823     * it will be called during dispatch instead of this method. The listener may optionally
8824     * call this method from its own implementation if it wishes to apply the view's default
8825     * insets policy in addition to its own.</p>
8826     *
8827     * <p>Implementations of this method should either return the insets parameter unchanged
8828     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8829     * that this view applied itself. This allows new inset types added in future platform
8830     * versions to pass through existing implementations unchanged without being erroneously
8831     * consumed.</p>
8832     *
8833     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8834     * property is set then the view will consume the system window insets and apply them
8835     * as padding for the view.</p>
8836     *
8837     * @param insets Insets to apply
8838     * @return The supplied insets with any applied insets consumed
8839     */
8840    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8841        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8842            // We weren't called from within a direct call to fitSystemWindows,
8843            // call into it as a fallback in case we're in a class that overrides it
8844            // and has logic to perform.
8845            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8846                return insets.consumeSystemWindowInsets();
8847            }
8848        } else {
8849            // We were called from within a direct call to fitSystemWindows.
8850            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8851                return insets.consumeSystemWindowInsets();
8852            }
8853        }
8854        return insets;
8855    }
8856
8857    /**
8858     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8859     * window insets to this view. The listener's
8860     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8861     * method will be called instead of the view's
8862     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8863     *
8864     * @param listener Listener to set
8865     *
8866     * @see #onApplyWindowInsets(WindowInsets)
8867     */
8868    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8869        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8870    }
8871
8872    /**
8873     * Request to apply the given window insets to this view or another view in its subtree.
8874     *
8875     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8876     * obscured by window decorations or overlays. This can include the status and navigation bars,
8877     * action bars, input methods and more. New inset categories may be added in the future.
8878     * The method returns the insets provided minus any that were applied by this view or its
8879     * children.</p>
8880     *
8881     * <p>Clients wishing to provide custom behavior should override the
8882     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8883     * {@link OnApplyWindowInsetsListener} via the
8884     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8885     * method.</p>
8886     *
8887     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8888     * </p>
8889     *
8890     * @param insets Insets to apply
8891     * @return The provided insets minus the insets that were consumed
8892     */
8893    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8894        try {
8895            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8896            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8897                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8898            } else {
8899                return onApplyWindowInsets(insets);
8900            }
8901        } finally {
8902            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8903        }
8904    }
8905
8906    /**
8907     * Compute the view's coordinate within the surface.
8908     *
8909     * <p>Computes the coordinates of this view in its surface. The argument
8910     * must be an array of two integers. After the method returns, the array
8911     * contains the x and y location in that order.</p>
8912     * @hide
8913     * @param location an array of two integers in which to hold the coordinates
8914     */
8915    public void getLocationInSurface(@Size(2) int[] location) {
8916        getLocationInWindow(location);
8917        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8918            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8919            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8920        }
8921    }
8922
8923    /**
8924     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8925     * only available if the view is attached.
8926     *
8927     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8928     */
8929    public WindowInsets getRootWindowInsets() {
8930        if (mAttachInfo != null) {
8931            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8932        }
8933        return null;
8934    }
8935
8936    /**
8937     * @hide Compute the insets that should be consumed by this view and the ones
8938     * that should propagate to those under it.
8939     */
8940    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8941        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8942                || mAttachInfo == null
8943                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8944                        && !mAttachInfo.mOverscanRequested)) {
8945            outLocalInsets.set(inoutInsets);
8946            inoutInsets.set(0, 0, 0, 0);
8947            return true;
8948        } else {
8949            // The application wants to take care of fitting system window for
8950            // the content...  however we still need to take care of any overscan here.
8951            final Rect overscan = mAttachInfo.mOverscanInsets;
8952            outLocalInsets.set(overscan);
8953            inoutInsets.left -= overscan.left;
8954            inoutInsets.top -= overscan.top;
8955            inoutInsets.right -= overscan.right;
8956            inoutInsets.bottom -= overscan.bottom;
8957            return false;
8958        }
8959    }
8960
8961    /**
8962     * Compute insets that should be consumed by this view and the ones that should propagate
8963     * to those under it.
8964     *
8965     * @param in Insets currently being processed by this View, likely received as a parameter
8966     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8967     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8968     *                       by this view
8969     * @return Insets that should be passed along to views under this one
8970     */
8971    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8972        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8973                || mAttachInfo == null
8974                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8975            outLocalInsets.set(in.getSystemWindowInsets());
8976            return in.consumeSystemWindowInsets();
8977        } else {
8978            outLocalInsets.set(0, 0, 0, 0);
8979            return in;
8980        }
8981    }
8982
8983    /**
8984     * Sets whether or not this view should account for system screen decorations
8985     * such as the status bar and inset its content; that is, controlling whether
8986     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8987     * executed.  See that method for more details.
8988     *
8989     * <p>Note that if you are providing your own implementation of
8990     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8991     * flag to true -- your implementation will be overriding the default
8992     * implementation that checks this flag.
8993     *
8994     * @param fitSystemWindows If true, then the default implementation of
8995     * {@link #fitSystemWindows(Rect)} will be executed.
8996     *
8997     * @attr ref android.R.styleable#View_fitsSystemWindows
8998     * @see #getFitsSystemWindows()
8999     * @see #fitSystemWindows(Rect)
9000     * @see #setSystemUiVisibility(int)
9001     */
9002    public void setFitsSystemWindows(boolean fitSystemWindows) {
9003        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9004    }
9005
9006    /**
9007     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9008     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9009     * will be executed.
9010     *
9011     * @return {@code true} if the default implementation of
9012     * {@link #fitSystemWindows(Rect)} will be executed.
9013     *
9014     * @attr ref android.R.styleable#View_fitsSystemWindows
9015     * @see #setFitsSystemWindows(boolean)
9016     * @see #fitSystemWindows(Rect)
9017     * @see #setSystemUiVisibility(int)
9018     */
9019    @ViewDebug.ExportedProperty
9020    public boolean getFitsSystemWindows() {
9021        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9022    }
9023
9024    /** @hide */
9025    public boolean fitsSystemWindows() {
9026        return getFitsSystemWindows();
9027    }
9028
9029    /**
9030     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9031     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9032     */
9033    @Deprecated
9034    public void requestFitSystemWindows() {
9035        if (mParent != null) {
9036            mParent.requestFitSystemWindows();
9037        }
9038    }
9039
9040    /**
9041     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9042     */
9043    public void requestApplyInsets() {
9044        requestFitSystemWindows();
9045    }
9046
9047    /**
9048     * For use by PhoneWindow to make its own system window fitting optional.
9049     * @hide
9050     */
9051    public void makeOptionalFitsSystemWindows() {
9052        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9053    }
9054
9055    /**
9056     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9057     * treat them as such.
9058     * @hide
9059     */
9060    public void getOutsets(Rect outOutsetRect) {
9061        if (mAttachInfo != null) {
9062            outOutsetRect.set(mAttachInfo.mOutsets);
9063        } else {
9064            outOutsetRect.setEmpty();
9065        }
9066    }
9067
9068    /**
9069     * Returns the visibility status for this view.
9070     *
9071     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9072     * @attr ref android.R.styleable#View_visibility
9073     */
9074    @ViewDebug.ExportedProperty(mapping = {
9075        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9076        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9077        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9078    })
9079    @Visibility
9080    public int getVisibility() {
9081        return mViewFlags & VISIBILITY_MASK;
9082    }
9083
9084    /**
9085     * Set the visibility state of this view.
9086     *
9087     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9088     * @attr ref android.R.styleable#View_visibility
9089     */
9090    @RemotableViewMethod
9091    public void setVisibility(@Visibility int visibility) {
9092        setFlags(visibility, VISIBILITY_MASK);
9093    }
9094
9095    /**
9096     * Returns the enabled status for this view. The interpretation of the
9097     * enabled state varies by subclass.
9098     *
9099     * @return True if this view is enabled, false otherwise.
9100     */
9101    @ViewDebug.ExportedProperty
9102    public boolean isEnabled() {
9103        return (mViewFlags & ENABLED_MASK) == ENABLED;
9104    }
9105
9106    /**
9107     * Set the enabled state of this view. The interpretation of the enabled
9108     * state varies by subclass.
9109     *
9110     * @param enabled True if this view is enabled, false otherwise.
9111     */
9112    @RemotableViewMethod
9113    public void setEnabled(boolean enabled) {
9114        if (enabled == isEnabled()) return;
9115
9116        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9117
9118        /*
9119         * The View most likely has to change its appearance, so refresh
9120         * the drawable state.
9121         */
9122        refreshDrawableState();
9123
9124        // Invalidate too, since the default behavior for views is to be
9125        // be drawn at 50% alpha rather than to change the drawable.
9126        invalidate(true);
9127
9128        if (!enabled) {
9129            cancelPendingInputEvents();
9130        }
9131    }
9132
9133    /**
9134     * Set whether this view can receive the focus.
9135     * <p>
9136     * Setting this to false will also ensure that this view is not focusable
9137     * in touch mode.
9138     *
9139     * @param focusable If true, this view can receive the focus.
9140     *
9141     * @see #setFocusableInTouchMode(boolean)
9142     * @see #setFocusable(int)
9143     * @attr ref android.R.styleable#View_focusable
9144     */
9145    public void setFocusable(boolean focusable) {
9146        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9147    }
9148
9149    /**
9150     * Sets whether this view can receive focus.
9151     * <p>
9152     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9153     * automatically based on the view's interactivity. This is the default.
9154     * <p>
9155     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9156     * in touch mode.
9157     *
9158     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9159     *                  or {@link #FOCUSABLE_AUTO}.
9160     * @see #setFocusableInTouchMode(boolean)
9161     * @attr ref android.R.styleable#View_focusable
9162     */
9163    public void setFocusable(@Focusable int focusable) {
9164        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9165            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9166        }
9167        setFlags(focusable, FOCUSABLE_MASK);
9168    }
9169
9170    /**
9171     * Set whether this view can receive focus while in touch mode.
9172     *
9173     * Setting this to true will also ensure that this view is focusable.
9174     *
9175     * @param focusableInTouchMode If true, this view can receive the focus while
9176     *   in touch mode.
9177     *
9178     * @see #setFocusable(boolean)
9179     * @attr ref android.R.styleable#View_focusableInTouchMode
9180     */
9181    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9182        // Focusable in touch mode should always be set before the focusable flag
9183        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9184        // which, in touch mode, will not successfully request focus on this view
9185        // because the focusable in touch mode flag is not set
9186        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9187
9188        // Clear FOCUSABLE_AUTO if set.
9189        if (focusableInTouchMode) {
9190            // Clears FOCUSABLE_AUTO if set.
9191            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9192        }
9193    }
9194
9195    /**
9196     * Sets the hints that helps the autofill service to select the appropriate data to fill the
9197     * view.
9198     *
9199     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9200     * @attr ref android.R.styleable#View_autofillHints
9201     */
9202    public void setAutofillHints(@Nullable String... autofillHints) {
9203        if (autofillHints == null || autofillHints.length == 0) {
9204            mAutofillHints = null;
9205        } else {
9206            mAutofillHints = autofillHints;
9207        }
9208    }
9209
9210    /**
9211     * @hide
9212     */
9213    @TestApi
9214    public void setAutofilled(boolean isAutofilled) {
9215        boolean wasChanged = isAutofilled != isAutofilled();
9216
9217        if (wasChanged) {
9218            if (isAutofilled) {
9219                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9220            } else {
9221                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9222            }
9223
9224            invalidate();
9225        }
9226    }
9227
9228    /**
9229     * Set whether this view should have sound effects enabled for events such as
9230     * clicking and touching.
9231     *
9232     * <p>You may wish to disable sound effects for a view if you already play sounds,
9233     * for instance, a dial key that plays dtmf tones.
9234     *
9235     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9236     * @see #isSoundEffectsEnabled()
9237     * @see #playSoundEffect(int)
9238     * @attr ref android.R.styleable#View_soundEffectsEnabled
9239     */
9240    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9241        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9242    }
9243
9244    /**
9245     * @return whether this view should have sound effects enabled for events such as
9246     *     clicking and touching.
9247     *
9248     * @see #setSoundEffectsEnabled(boolean)
9249     * @see #playSoundEffect(int)
9250     * @attr ref android.R.styleable#View_soundEffectsEnabled
9251     */
9252    @ViewDebug.ExportedProperty
9253    public boolean isSoundEffectsEnabled() {
9254        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9255    }
9256
9257    /**
9258     * Set whether this view should have haptic feedback for events such as
9259     * long presses.
9260     *
9261     * <p>You may wish to disable haptic feedback if your view already controls
9262     * its own haptic feedback.
9263     *
9264     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9265     * @see #isHapticFeedbackEnabled()
9266     * @see #performHapticFeedback(int)
9267     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9268     */
9269    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9270        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9271    }
9272
9273    /**
9274     * @return whether this view should have haptic feedback enabled for events
9275     * long presses.
9276     *
9277     * @see #setHapticFeedbackEnabled(boolean)
9278     * @see #performHapticFeedback(int)
9279     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9280     */
9281    @ViewDebug.ExportedProperty
9282    public boolean isHapticFeedbackEnabled() {
9283        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9284    }
9285
9286    /**
9287     * Returns the layout direction for this view.
9288     *
9289     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9290     *   {@link #LAYOUT_DIRECTION_RTL},
9291     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9292     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9293     *
9294     * @attr ref android.R.styleable#View_layoutDirection
9295     *
9296     * @hide
9297     */
9298    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9299        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9300        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9301        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9302        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9303    })
9304    @LayoutDir
9305    public int getRawLayoutDirection() {
9306        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9307    }
9308
9309    /**
9310     * Set the layout direction for this view. This will propagate a reset of layout direction
9311     * resolution to the view's children and resolve layout direction for this view.
9312     *
9313     * @param layoutDirection the layout direction to set. Should be one of:
9314     *
9315     * {@link #LAYOUT_DIRECTION_LTR},
9316     * {@link #LAYOUT_DIRECTION_RTL},
9317     * {@link #LAYOUT_DIRECTION_INHERIT},
9318     * {@link #LAYOUT_DIRECTION_LOCALE}.
9319     *
9320     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9321     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9322     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9323     *
9324     * @attr ref android.R.styleable#View_layoutDirection
9325     */
9326    @RemotableViewMethod
9327    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9328        if (getRawLayoutDirection() != layoutDirection) {
9329            // Reset the current layout direction and the resolved one
9330            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9331            resetRtlProperties();
9332            // Set the new layout direction (filtered)
9333            mPrivateFlags2 |=
9334                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9335            // We need to resolve all RTL properties as they all depend on layout direction
9336            resolveRtlPropertiesIfNeeded();
9337            requestLayout();
9338            invalidate(true);
9339        }
9340    }
9341
9342    /**
9343     * Returns the resolved layout direction for this view.
9344     *
9345     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9346     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9347     *
9348     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9349     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9350     *
9351     * @attr ref android.R.styleable#View_layoutDirection
9352     */
9353    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9354        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9355        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9356    })
9357    @ResolvedLayoutDir
9358    public int getLayoutDirection() {
9359        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9360        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9361            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9362            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9363        }
9364        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9365                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9366    }
9367
9368    /**
9369     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9370     * layout attribute and/or the inherited value from the parent
9371     *
9372     * @return true if the layout is right-to-left.
9373     *
9374     * @hide
9375     */
9376    @ViewDebug.ExportedProperty(category = "layout")
9377    public boolean isLayoutRtl() {
9378        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9379    }
9380
9381    /**
9382     * Indicates whether the view is currently tracking transient state that the
9383     * app should not need to concern itself with saving and restoring, but that
9384     * the framework should take special note to preserve when possible.
9385     *
9386     * <p>A view with transient state cannot be trivially rebound from an external
9387     * data source, such as an adapter binding item views in a list. This may be
9388     * because the view is performing an animation, tracking user selection
9389     * of content, or similar.</p>
9390     *
9391     * @return true if the view has transient state
9392     */
9393    @ViewDebug.ExportedProperty(category = "layout")
9394    public boolean hasTransientState() {
9395        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9396    }
9397
9398    /**
9399     * Set whether this view is currently tracking transient state that the
9400     * framework should attempt to preserve when possible. This flag is reference counted,
9401     * so every call to setHasTransientState(true) should be paired with a later call
9402     * to setHasTransientState(false).
9403     *
9404     * <p>A view with transient state cannot be trivially rebound from an external
9405     * data source, such as an adapter binding item views in a list. This may be
9406     * because the view is performing an animation, tracking user selection
9407     * of content, or similar.</p>
9408     *
9409     * @param hasTransientState true if this view has transient state
9410     */
9411    public void setHasTransientState(boolean hasTransientState) {
9412        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9413                mTransientStateCount - 1;
9414        if (mTransientStateCount < 0) {
9415            mTransientStateCount = 0;
9416            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9417                    "unmatched pair of setHasTransientState calls");
9418        } else if ((hasTransientState && mTransientStateCount == 1) ||
9419                (!hasTransientState && mTransientStateCount == 0)) {
9420            // update flag if we've just incremented up from 0 or decremented down to 0
9421            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9422                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9423            if (mParent != null) {
9424                try {
9425                    mParent.childHasTransientStateChanged(this, hasTransientState);
9426                } catch (AbstractMethodError e) {
9427                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9428                            " does not fully implement ViewParent", e);
9429                }
9430            }
9431        }
9432    }
9433
9434    /**
9435     * Returns true if this view is currently attached to a window.
9436     */
9437    public boolean isAttachedToWindow() {
9438        return mAttachInfo != null;
9439    }
9440
9441    /**
9442     * Returns true if this view has been through at least one layout since it
9443     * was last attached to or detached from a window.
9444     */
9445    public boolean isLaidOut() {
9446        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9447    }
9448
9449    /**
9450     * If this view doesn't do any drawing on its own, set this flag to
9451     * allow further optimizations. By default, this flag is not set on
9452     * View, but could be set on some View subclasses such as ViewGroup.
9453     *
9454     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9455     * you should clear this flag.
9456     *
9457     * @param willNotDraw whether or not this View draw on its own
9458     */
9459    public void setWillNotDraw(boolean willNotDraw) {
9460        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9461    }
9462
9463    /**
9464     * Returns whether or not this View draws on its own.
9465     *
9466     * @return true if this view has nothing to draw, false otherwise
9467     */
9468    @ViewDebug.ExportedProperty(category = "drawing")
9469    public boolean willNotDraw() {
9470        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9471    }
9472
9473    /**
9474     * When a View's drawing cache is enabled, drawing is redirected to an
9475     * offscreen bitmap. Some views, like an ImageView, must be able to
9476     * bypass this mechanism if they already draw a single bitmap, to avoid
9477     * unnecessary usage of the memory.
9478     *
9479     * @param willNotCacheDrawing true if this view does not cache its
9480     *        drawing, false otherwise
9481     */
9482    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9483        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9484    }
9485
9486    /**
9487     * Returns whether or not this View can cache its drawing or not.
9488     *
9489     * @return true if this view does not cache its drawing, false otherwise
9490     */
9491    @ViewDebug.ExportedProperty(category = "drawing")
9492    public boolean willNotCacheDrawing() {
9493        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9494    }
9495
9496    /**
9497     * Indicates whether this view reacts to click events or not.
9498     *
9499     * @return true if the view is clickable, false otherwise
9500     *
9501     * @see #setClickable(boolean)
9502     * @attr ref android.R.styleable#View_clickable
9503     */
9504    @ViewDebug.ExportedProperty
9505    public boolean isClickable() {
9506        return (mViewFlags & CLICKABLE) == CLICKABLE;
9507    }
9508
9509    /**
9510     * Enables or disables click events for this view. When a view
9511     * is clickable it will change its state to "pressed" on every click.
9512     * Subclasses should set the view clickable to visually react to
9513     * user's clicks.
9514     *
9515     * @param clickable true to make the view clickable, false otherwise
9516     *
9517     * @see #isClickable()
9518     * @attr ref android.R.styleable#View_clickable
9519     */
9520    public void setClickable(boolean clickable) {
9521        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9522    }
9523
9524    /**
9525     * Indicates whether this view reacts to long click events or not.
9526     *
9527     * @return true if the view is long clickable, false otherwise
9528     *
9529     * @see #setLongClickable(boolean)
9530     * @attr ref android.R.styleable#View_longClickable
9531     */
9532    public boolean isLongClickable() {
9533        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9534    }
9535
9536    /**
9537     * Enables or disables long click events for this view. When a view is long
9538     * clickable it reacts to the user holding down the button for a longer
9539     * duration than a tap. This event can either launch the listener or a
9540     * context menu.
9541     *
9542     * @param longClickable true to make the view long clickable, false otherwise
9543     * @see #isLongClickable()
9544     * @attr ref android.R.styleable#View_longClickable
9545     */
9546    public void setLongClickable(boolean longClickable) {
9547        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9548    }
9549
9550    /**
9551     * Indicates whether this view reacts to context clicks or not.
9552     *
9553     * @return true if the view is context clickable, false otherwise
9554     * @see #setContextClickable(boolean)
9555     * @attr ref android.R.styleable#View_contextClickable
9556     */
9557    public boolean isContextClickable() {
9558        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9559    }
9560
9561    /**
9562     * Enables or disables context clicking for this view. This event can launch the listener.
9563     *
9564     * @param contextClickable true to make the view react to a context click, false otherwise
9565     * @see #isContextClickable()
9566     * @attr ref android.R.styleable#View_contextClickable
9567     */
9568    public void setContextClickable(boolean contextClickable) {
9569        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9570    }
9571
9572    /**
9573     * Sets the pressed state for this view and provides a touch coordinate for
9574     * animation hinting.
9575     *
9576     * @param pressed Pass true to set the View's internal state to "pressed",
9577     *            or false to reverts the View's internal state from a
9578     *            previously set "pressed" state.
9579     * @param x The x coordinate of the touch that caused the press
9580     * @param y The y coordinate of the touch that caused the press
9581     */
9582    private void setPressed(boolean pressed, float x, float y) {
9583        if (pressed) {
9584            drawableHotspotChanged(x, y);
9585        }
9586
9587        setPressed(pressed);
9588    }
9589
9590    /**
9591     * Sets the pressed state for this view.
9592     *
9593     * @see #isClickable()
9594     * @see #setClickable(boolean)
9595     *
9596     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9597     *        the View's internal state from a previously set "pressed" state.
9598     */
9599    public void setPressed(boolean pressed) {
9600        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9601
9602        if (pressed) {
9603            mPrivateFlags |= PFLAG_PRESSED;
9604        } else {
9605            mPrivateFlags &= ~PFLAG_PRESSED;
9606        }
9607
9608        if (needsRefresh) {
9609            refreshDrawableState();
9610        }
9611        dispatchSetPressed(pressed);
9612    }
9613
9614    /**
9615     * Dispatch setPressed to all of this View's children.
9616     *
9617     * @see #setPressed(boolean)
9618     *
9619     * @param pressed The new pressed state
9620     */
9621    protected void dispatchSetPressed(boolean pressed) {
9622    }
9623
9624    /**
9625     * Indicates whether the view is currently in pressed state. Unless
9626     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9627     * the pressed state.
9628     *
9629     * @see #setPressed(boolean)
9630     * @see #isClickable()
9631     * @see #setClickable(boolean)
9632     *
9633     * @return true if the view is currently pressed, false otherwise
9634     */
9635    @ViewDebug.ExportedProperty
9636    public boolean isPressed() {
9637        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9638    }
9639
9640    /**
9641     * @hide
9642     * Indicates whether this view will participate in data collection through
9643     * {@link ViewStructure}.  If true, it will not provide any data
9644     * for itself or its children.  If false, the normal data collection will be allowed.
9645     *
9646     * @return Returns false if assist data collection is not blocked, else true.
9647     *
9648     * @see #setAssistBlocked(boolean)
9649     * @attr ref android.R.styleable#View_assistBlocked
9650     */
9651    public boolean isAssistBlocked() {
9652        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9653    }
9654
9655    /**
9656     * @hide
9657     * Controls whether assist data collection from this view and its children is enabled
9658     * (that is, whether {@link #onProvideStructure} and
9659     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9660     * allowing normal assist collection.  Setting this to false will disable assist collection.
9661     *
9662     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9663     * (the default) to allow it.
9664     *
9665     * @see #isAssistBlocked()
9666     * @see #onProvideStructure
9667     * @see #onProvideVirtualStructure
9668     * @attr ref android.R.styleable#View_assistBlocked
9669     */
9670    public void setAssistBlocked(boolean enabled) {
9671        if (enabled) {
9672            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9673        } else {
9674            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9675        }
9676    }
9677
9678    /**
9679     * Indicates whether this view will save its state (that is,
9680     * whether its {@link #onSaveInstanceState} method will be called).
9681     *
9682     * @return Returns true if the view state saving is enabled, else false.
9683     *
9684     * @see #setSaveEnabled(boolean)
9685     * @attr ref android.R.styleable#View_saveEnabled
9686     */
9687    public boolean isSaveEnabled() {
9688        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9689    }
9690
9691    /**
9692     * Controls whether the saving of this view's state is
9693     * enabled (that is, whether its {@link #onSaveInstanceState} method
9694     * will be called).  Note that even if freezing is enabled, the
9695     * view still must have an id assigned to it (via {@link #setId(int)})
9696     * for its state to be saved.  This flag can only disable the
9697     * saving of this view; any child views may still have their state saved.
9698     *
9699     * @param enabled Set to false to <em>disable</em> state saving, or true
9700     * (the default) to allow it.
9701     *
9702     * @see #isSaveEnabled()
9703     * @see #setId(int)
9704     * @see #onSaveInstanceState()
9705     * @attr ref android.R.styleable#View_saveEnabled
9706     */
9707    public void setSaveEnabled(boolean enabled) {
9708        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9709    }
9710
9711    /**
9712     * Gets whether the framework should discard touches when the view's
9713     * window is obscured by another visible window.
9714     * Refer to the {@link View} security documentation for more details.
9715     *
9716     * @return True if touch filtering is enabled.
9717     *
9718     * @see #setFilterTouchesWhenObscured(boolean)
9719     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9720     */
9721    @ViewDebug.ExportedProperty
9722    public boolean getFilterTouchesWhenObscured() {
9723        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9724    }
9725
9726    /**
9727     * Sets whether the framework should discard touches when the view's
9728     * window is obscured by another visible window.
9729     * Refer to the {@link View} security documentation for more details.
9730     *
9731     * @param enabled True if touch filtering should be enabled.
9732     *
9733     * @see #getFilterTouchesWhenObscured
9734     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9735     */
9736    public void setFilterTouchesWhenObscured(boolean enabled) {
9737        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9738                FILTER_TOUCHES_WHEN_OBSCURED);
9739    }
9740
9741    /**
9742     * Indicates whether the entire hierarchy under this view will save its
9743     * state when a state saving traversal occurs from its parent.  The default
9744     * is true; if false, these views will not be saved unless
9745     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9746     *
9747     * @return Returns true if the view state saving from parent is enabled, else false.
9748     *
9749     * @see #setSaveFromParentEnabled(boolean)
9750     */
9751    public boolean isSaveFromParentEnabled() {
9752        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9753    }
9754
9755    /**
9756     * Controls whether the entire hierarchy under this view will save its
9757     * state when a state saving traversal occurs from its parent.  The default
9758     * is true; if false, these views will not be saved unless
9759     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9760     *
9761     * @param enabled Set to false to <em>disable</em> state saving, or true
9762     * (the default) to allow it.
9763     *
9764     * @see #isSaveFromParentEnabled()
9765     * @see #setId(int)
9766     * @see #onSaveInstanceState()
9767     */
9768    public void setSaveFromParentEnabled(boolean enabled) {
9769        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9770    }
9771
9772
9773    /**
9774     * Returns whether this View is currently able to take focus.
9775     *
9776     * @return True if this view can take focus, or false otherwise.
9777     */
9778    @ViewDebug.ExportedProperty(category = "focus")
9779    public final boolean isFocusable() {
9780        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9781    }
9782
9783    /**
9784     * Returns the focusable setting for this view.
9785     *
9786     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9787     * @attr ref android.R.styleable#View_focusable
9788     */
9789    @ViewDebug.ExportedProperty(mapping = {
9790            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9791            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9792            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9793            }, category = "focus")
9794    @Focusable
9795    public int getFocusable() {
9796        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9797    }
9798
9799    /**
9800     * When a view is focusable, it may not want to take focus when in touch mode.
9801     * For example, a button would like focus when the user is navigating via a D-pad
9802     * so that the user can click on it, but once the user starts touching the screen,
9803     * the button shouldn't take focus
9804     * @return Whether the view is focusable in touch mode.
9805     * @attr ref android.R.styleable#View_focusableInTouchMode
9806     */
9807    @ViewDebug.ExportedProperty(category = "focus")
9808    public final boolean isFocusableInTouchMode() {
9809        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9810    }
9811
9812    /**
9813     * Find the nearest view in the specified direction that can take focus.
9814     * This does not actually give focus to that view.
9815     *
9816     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9817     *
9818     * @return The nearest focusable in the specified direction, or null if none
9819     *         can be found.
9820     */
9821    public View focusSearch(@FocusRealDirection int direction) {
9822        if (mParent != null) {
9823            return mParent.focusSearch(this, direction);
9824        } else {
9825            return null;
9826        }
9827    }
9828
9829    /**
9830     * Returns whether this View is a root of a keyboard navigation cluster.
9831     *
9832     * @return True if this view is a root of a cluster, or false otherwise.
9833     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9834     */
9835    @ViewDebug.ExportedProperty(category = "focus")
9836    public final boolean isKeyboardNavigationCluster() {
9837        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9838    }
9839
9840    /**
9841     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
9842     * will be ignored.
9843     *
9844     * @return the keyboard navigation cluster that this view is in (can be this view)
9845     *         or {@code null} if not in one
9846     */
9847    View findKeyboardNavigationCluster() {
9848        if (mParent instanceof View) {
9849            View cluster = ((View) mParent).findKeyboardNavigationCluster();
9850            if (cluster != null) {
9851                return cluster;
9852            } else if (isKeyboardNavigationCluster()) {
9853                return this;
9854            }
9855        }
9856        return null;
9857    }
9858
9859    /**
9860     * Set whether this view is a root of a keyboard navigation cluster.
9861     *
9862     * @param isCluster If true, this view is a root of a cluster.
9863     *
9864     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9865     */
9866    public void setKeyboardNavigationCluster(boolean isCluster) {
9867        if (isCluster) {
9868            mPrivateFlags3 |= PFLAG3_CLUSTER;
9869        } else {
9870            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9871        }
9872    }
9873
9874    /**
9875     * Sets this View as the one which receives focus the next time cluster navigation jumps
9876     * to the cluster containing this View. This does NOT change focus even if the cluster
9877     * containing this view is current.
9878     *
9879     * @hide
9880     */
9881    public final void setFocusedInCluster() {
9882        View top = findKeyboardNavigationCluster();
9883        if (top == this) {
9884            return;
9885        }
9886        ViewParent parent = mParent;
9887        View child = this;
9888        while (parent instanceof ViewGroup) {
9889            ((ViewGroup) parent).setFocusedInCluster(child);
9890            if (parent == top) {
9891                return;
9892            }
9893            child = (View) parent;
9894            parent = parent.getParent();
9895        }
9896    }
9897
9898    /**
9899     * Returns whether this View should receive focus when the focus is restored for the view
9900     * hierarchy containing this view.
9901     * <p>
9902     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9903     * window or serves as a target of cluster navigation.
9904     *
9905     * @see #restoreDefaultFocus()
9906     *
9907     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9908     * @attr ref android.R.styleable#View_focusedByDefault
9909     */
9910    @ViewDebug.ExportedProperty(category = "focus")
9911    public final boolean isFocusedByDefault() {
9912        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9913    }
9914
9915    /**
9916     * Sets whether this View should receive focus when the focus is restored for the view
9917     * hierarchy containing this view.
9918     * <p>
9919     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9920     * window or serves as a target of cluster navigation.
9921     *
9922     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9923     *                           {@code false} otherwise.
9924     *
9925     * @see #restoreDefaultFocus()
9926     *
9927     * @attr ref android.R.styleable#View_focusedByDefault
9928     */
9929    public void setFocusedByDefault(boolean isFocusedByDefault) {
9930        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9931            return;
9932        }
9933
9934        if (isFocusedByDefault) {
9935            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9936        } else {
9937            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9938        }
9939
9940        if (mParent instanceof ViewGroup) {
9941            if (isFocusedByDefault) {
9942                ((ViewGroup) mParent).setDefaultFocus(this);
9943            } else {
9944                ((ViewGroup) mParent).clearDefaultFocus(this);
9945            }
9946        }
9947    }
9948
9949    /**
9950     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9951     *
9952     * @return {@code true} if this view has default focus, {@code false} otherwise
9953     */
9954    boolean hasDefaultFocus() {
9955        return isFocusedByDefault();
9956    }
9957
9958    /**
9959     * Find the nearest keyboard navigation cluster in the specified direction.
9960     * This does not actually give focus to that cluster.
9961     *
9962     * @param currentCluster The starting point of the search. Null means the current cluster is not
9963     *                       found yet
9964     * @param direction Direction to look
9965     *
9966     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9967     *         can be found
9968     */
9969    public View keyboardNavigationClusterSearch(View currentCluster,
9970            @FocusDirection int direction) {
9971        if (isKeyboardNavigationCluster()) {
9972            currentCluster = this;
9973        }
9974        if (isRootNamespace()) {
9975            // Root namespace means we should consider ourselves the top of the
9976            // tree for group searching; otherwise we could be group searching
9977            // into other tabs.  see LocalActivityManager and TabHost for more info.
9978            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9979                    this, currentCluster, direction);
9980        } else if (mParent != null) {
9981            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9982        }
9983        return null;
9984    }
9985
9986    /**
9987     * This method is the last chance for the focused view and its ancestors to
9988     * respond to an arrow key. This is called when the focused view did not
9989     * consume the key internally, nor could the view system find a new view in
9990     * the requested direction to give focus to.
9991     *
9992     * @param focused The currently focused view.
9993     * @param direction The direction focus wants to move. One of FOCUS_UP,
9994     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9995     * @return True if the this view consumed this unhandled move.
9996     */
9997    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9998        return false;
9999    }
10000
10001    /**
10002     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10003     * have {@link android.R.attr#state_focused} defined in its background.
10004     *
10005     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10006     *                                      highlight, {@code false} otherwise.
10007     *
10008     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10009     */
10010    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10011        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10012    }
10013
10014    /**
10015
10016    /**
10017     * Returns whether this View should use a default focus highlight when it gets focused but
10018     * doesn't have {@link android.R.attr#state_focused} defined in its background.
10019     *
10020     * @return True if this View should use a default focus highlight.
10021     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10022     */
10023    @ViewDebug.ExportedProperty(category = "focus")
10024    public final boolean getDefaultFocusHighlightEnabled() {
10025        return mDefaultFocusHighlightEnabled;
10026    }
10027
10028    /**
10029     * If a user manually specified the next view id for a particular direction,
10030     * use the root to look up the view.
10031     * @param root The root view of the hierarchy containing this view.
10032     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10033     * or FOCUS_BACKWARD.
10034     * @return The user specified next view, or null if there is none.
10035     */
10036    View findUserSetNextFocus(View root, @FocusDirection int direction) {
10037        switch (direction) {
10038            case FOCUS_LEFT:
10039                if (mNextFocusLeftId == View.NO_ID) return null;
10040                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10041            case FOCUS_RIGHT:
10042                if (mNextFocusRightId == View.NO_ID) return null;
10043                return findViewInsideOutShouldExist(root, mNextFocusRightId);
10044            case FOCUS_UP:
10045                if (mNextFocusUpId == View.NO_ID) return null;
10046                return findViewInsideOutShouldExist(root, mNextFocusUpId);
10047            case FOCUS_DOWN:
10048                if (mNextFocusDownId == View.NO_ID) return null;
10049                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10050            case FOCUS_FORWARD:
10051                if (mNextFocusForwardId == View.NO_ID) return null;
10052                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10053            case FOCUS_BACKWARD: {
10054                if (mID == View.NO_ID) return null;
10055                final int id = mID;
10056                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10057                    @Override
10058                    public boolean test(View t) {
10059                        return t.mNextFocusForwardId == id;
10060                    }
10061                });
10062            }
10063        }
10064        return null;
10065    }
10066
10067    /**
10068     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10069     * use the root to look up the view.
10070     *
10071     * @param root the root view of the hierarchy containing this view
10072     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10073     * @return the user-specified next cluster, or {@code null} if there is none
10074     */
10075    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10076        switch (direction) {
10077            case FOCUS_FORWARD:
10078                if (mNextClusterForwardId == View.NO_ID) return null;
10079                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10080            case FOCUS_BACKWARD: {
10081                if (mID == View.NO_ID) return null;
10082                final int id = mID;
10083                return root.findViewByPredicateInsideOut(this,
10084                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10085            }
10086        }
10087        return null;
10088    }
10089
10090    private View findViewInsideOutShouldExist(View root, int id) {
10091        if (mMatchIdPredicate == null) {
10092            mMatchIdPredicate = new MatchIdPredicate();
10093        }
10094        mMatchIdPredicate.mId = id;
10095        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10096        if (result == null) {
10097            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10098        }
10099        return result;
10100    }
10101
10102    /**
10103     * Find and return all focusable views that are descendants of this view,
10104     * possibly including this view if it is focusable itself.
10105     *
10106     * @param direction The direction of the focus
10107     * @return A list of focusable views
10108     */
10109    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10110        ArrayList<View> result = new ArrayList<View>(24);
10111        addFocusables(result, direction);
10112        return result;
10113    }
10114
10115    /**
10116     * Add any focusable views that are descendants of this view (possibly
10117     * including this view if it is focusable itself) to views.  If we are in touch mode,
10118     * only add views that are also focusable in touch mode.
10119     *
10120     * @param views Focusable views found so far
10121     * @param direction The direction of the focus
10122     */
10123    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10124        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10125    }
10126
10127    /**
10128     * Adds any focusable views that are descendants of this view (possibly
10129     * including this view if it is focusable itself) to views. This method
10130     * adds all focusable views regardless if we are in touch mode or
10131     * only views focusable in touch mode if we are in touch mode or
10132     * only views that can take accessibility focus if accessibility is enabled
10133     * depending on the focusable mode parameter.
10134     *
10135     * @param views Focusable views found so far or null if all we are interested is
10136     *        the number of focusables.
10137     * @param direction The direction of the focus.
10138     * @param focusableMode The type of focusables to be added.
10139     *
10140     * @see #FOCUSABLES_ALL
10141     * @see #FOCUSABLES_TOUCH_MODE
10142     */
10143    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10144            @FocusableMode int focusableMode) {
10145        if (views == null) {
10146            return;
10147        }
10148        if (!isFocusable()) {
10149            return;
10150        }
10151        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10152                && !isFocusableInTouchMode()) {
10153            return;
10154        }
10155        views.add(this);
10156    }
10157
10158    /**
10159     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10160     * including this view if it is a cluster root itself) to views.
10161     *
10162     * @param views Keyboard navigation cluster roots found so far
10163     * @param direction Direction to look
10164     */
10165    public void addKeyboardNavigationClusters(
10166            @NonNull Collection<View> views,
10167            int direction) {
10168        if (!isKeyboardNavigationCluster()) {
10169            return;
10170        }
10171        if (!hasFocusable()) {
10172            return;
10173        }
10174        views.add(this);
10175    }
10176
10177    /**
10178     * Finds the Views that contain given text. The containment is case insensitive.
10179     * The search is performed by either the text that the View renders or the content
10180     * description that describes the view for accessibility purposes and the view does
10181     * not render or both. Clients can specify how the search is to be performed via
10182     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10183     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10184     *
10185     * @param outViews The output list of matching Views.
10186     * @param searched The text to match against.
10187     *
10188     * @see #FIND_VIEWS_WITH_TEXT
10189     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10190     * @see #setContentDescription(CharSequence)
10191     */
10192    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10193            @FindViewFlags int flags) {
10194        if (getAccessibilityNodeProvider() != null) {
10195            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10196                outViews.add(this);
10197            }
10198        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10199                && (searched != null && searched.length() > 0)
10200                && (mContentDescription != null && mContentDescription.length() > 0)) {
10201            String searchedLowerCase = searched.toString().toLowerCase();
10202            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10203            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10204                outViews.add(this);
10205            }
10206        }
10207    }
10208
10209    /**
10210     * Find and return all touchable views that are descendants of this view,
10211     * possibly including this view if it is touchable itself.
10212     *
10213     * @return A list of touchable views
10214     */
10215    public ArrayList<View> getTouchables() {
10216        ArrayList<View> result = new ArrayList<View>();
10217        addTouchables(result);
10218        return result;
10219    }
10220
10221    /**
10222     * Add any touchable views that are descendants of this view (possibly
10223     * including this view if it is touchable itself) to views.
10224     *
10225     * @param views Touchable views found so far
10226     */
10227    public void addTouchables(ArrayList<View> views) {
10228        final int viewFlags = mViewFlags;
10229
10230        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10231                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10232                && (viewFlags & ENABLED_MASK) == ENABLED) {
10233            views.add(this);
10234        }
10235    }
10236
10237    /**
10238     * Returns whether this View is accessibility focused.
10239     *
10240     * @return True if this View is accessibility focused.
10241     */
10242    public boolean isAccessibilityFocused() {
10243        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10244    }
10245
10246    /**
10247     * Call this to try to give accessibility focus to this view.
10248     *
10249     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10250     * returns false or the view is no visible or the view already has accessibility
10251     * focus.
10252     *
10253     * See also {@link #focusSearch(int)}, which is what you call to say that you
10254     * have focus, and you want your parent to look for the next one.
10255     *
10256     * @return Whether this view actually took accessibility focus.
10257     *
10258     * @hide
10259     */
10260    public boolean requestAccessibilityFocus() {
10261        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10262        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10263            return false;
10264        }
10265        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10266            return false;
10267        }
10268        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10269            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10270            ViewRootImpl viewRootImpl = getViewRootImpl();
10271            if (viewRootImpl != null) {
10272                viewRootImpl.setAccessibilityFocus(this, null);
10273            }
10274            invalidate();
10275            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10276            return true;
10277        }
10278        return false;
10279    }
10280
10281    /**
10282     * Call this to try to clear accessibility focus of this view.
10283     *
10284     * See also {@link #focusSearch(int)}, which is what you call to say that you
10285     * have focus, and you want your parent to look for the next one.
10286     *
10287     * @hide
10288     */
10289    public void clearAccessibilityFocus() {
10290        clearAccessibilityFocusNoCallbacks(0);
10291
10292        // Clear the global reference of accessibility focus if this view or
10293        // any of its descendants had accessibility focus. This will NOT send
10294        // an event or update internal state if focus is cleared from a
10295        // descendant view, which may leave views in inconsistent states.
10296        final ViewRootImpl viewRootImpl = getViewRootImpl();
10297        if (viewRootImpl != null) {
10298            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10299            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10300                viewRootImpl.setAccessibilityFocus(null, null);
10301            }
10302        }
10303    }
10304
10305    private void sendAccessibilityHoverEvent(int eventType) {
10306        // Since we are not delivering to a client accessibility events from not
10307        // important views (unless the clinet request that) we need to fire the
10308        // event from the deepest view exposed to the client. As a consequence if
10309        // the user crosses a not exposed view the client will see enter and exit
10310        // of the exposed predecessor followed by and enter and exit of that same
10311        // predecessor when entering and exiting the not exposed descendant. This
10312        // is fine since the client has a clear idea which view is hovered at the
10313        // price of a couple more events being sent. This is a simple and
10314        // working solution.
10315        View source = this;
10316        while (true) {
10317            if (source.includeForAccessibility()) {
10318                source.sendAccessibilityEvent(eventType);
10319                return;
10320            }
10321            ViewParent parent = source.getParent();
10322            if (parent instanceof View) {
10323                source = (View) parent;
10324            } else {
10325                return;
10326            }
10327        }
10328    }
10329
10330    /**
10331     * Clears accessibility focus without calling any callback methods
10332     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10333     * is used separately from that one for clearing accessibility focus when
10334     * giving this focus to another view.
10335     *
10336     * @param action The action, if any, that led to focus being cleared. Set to
10337     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10338     * the window.
10339     */
10340    void clearAccessibilityFocusNoCallbacks(int action) {
10341        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10342            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10343            invalidate();
10344            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10345                AccessibilityEvent event = AccessibilityEvent.obtain(
10346                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10347                event.setAction(action);
10348                if (mAccessibilityDelegate != null) {
10349                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10350                } else {
10351                    sendAccessibilityEventUnchecked(event);
10352                }
10353            }
10354        }
10355    }
10356
10357    /**
10358     * Call this to try to give focus to a specific view or to one of its
10359     * descendants.
10360     *
10361     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10362     * false), or if it is focusable and it is not focusable in touch mode
10363     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10364     *
10365     * See also {@link #focusSearch(int)}, which is what you call to say that you
10366     * have focus, and you want your parent to look for the next one.
10367     *
10368     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10369     * {@link #FOCUS_DOWN} and <code>null</code>.
10370     *
10371     * @return Whether this view or one of its descendants actually took focus.
10372     */
10373    public final boolean requestFocus() {
10374        return requestFocus(View.FOCUS_DOWN);
10375    }
10376
10377    /**
10378     * This will request focus for whichever View was last focused within this
10379     * cluster before a focus-jump out of it.
10380     *
10381     * @hide
10382     */
10383    @TestApi
10384    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10385        // Prioritize focusableByDefault over algorithmic focus selection.
10386        if (restoreDefaultFocus()) {
10387            return true;
10388        }
10389        return requestFocus(direction);
10390    }
10391
10392    /**
10393     * This will request focus for whichever View not in a cluster was last focused before a
10394     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10395     * the "first" focusable view it finds.
10396     *
10397     * @hide
10398     */
10399    @TestApi
10400    public boolean restoreFocusNotInCluster() {
10401        return requestFocus(View.FOCUS_DOWN);
10402    }
10403
10404    /**
10405     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10406     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10407     *
10408     * @return Whether this view or one of its descendants actually took focus
10409     */
10410    public boolean restoreDefaultFocus() {
10411        return requestFocus(View.FOCUS_DOWN);
10412    }
10413
10414    /**
10415     * Call this to try to give focus to a specific view or to one of its
10416     * descendants and give it a hint about what direction focus is heading.
10417     *
10418     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10419     * false), or if it is focusable and it is not focusable in touch mode
10420     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10421     *
10422     * See also {@link #focusSearch(int)}, which is what you call to say that you
10423     * have focus, and you want your parent to look for the next one.
10424     *
10425     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10426     * <code>null</code> set for the previously focused rectangle.
10427     *
10428     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10429     * @return Whether this view or one of its descendants actually took focus.
10430     */
10431    public final boolean requestFocus(int direction) {
10432        return requestFocus(direction, null);
10433    }
10434
10435    /**
10436     * Call this to try to give focus to a specific view or to one of its descendants
10437     * and give it hints about the direction and a specific rectangle that the focus
10438     * is coming from.  The rectangle can help give larger views a finer grained hint
10439     * about where focus is coming from, and therefore, where to show selection, or
10440     * forward focus change internally.
10441     *
10442     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10443     * false), or if it is focusable and it is not focusable in touch mode
10444     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10445     *
10446     * A View will not take focus if it is not visible.
10447     *
10448     * A View will not take focus if one of its parents has
10449     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10450     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10451     *
10452     * See also {@link #focusSearch(int)}, which is what you call to say that you
10453     * have focus, and you want your parent to look for the next one.
10454     *
10455     * You may wish to override this method if your custom {@link View} has an internal
10456     * {@link View} that it wishes to forward the request to.
10457     *
10458     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10459     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10460     *        to give a finer grained hint about where focus is coming from.  May be null
10461     *        if there is no hint.
10462     * @return Whether this view or one of its descendants actually took focus.
10463     */
10464    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10465        return requestFocusNoSearch(direction, previouslyFocusedRect);
10466    }
10467
10468    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10469        // need to be focusable
10470        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10471                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10472            return false;
10473        }
10474
10475        // need to be focusable in touch mode if in touch mode
10476        if (isInTouchMode() &&
10477            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10478               return false;
10479        }
10480
10481        // need to not have any parents blocking us
10482        if (hasAncestorThatBlocksDescendantFocus()) {
10483            return false;
10484        }
10485
10486        handleFocusGainInternal(direction, previouslyFocusedRect);
10487        return true;
10488    }
10489
10490    /**
10491     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10492     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10493     * touch mode to request focus when they are touched.
10494     *
10495     * @return Whether this view or one of its descendants actually took focus.
10496     *
10497     * @see #isInTouchMode()
10498     *
10499     */
10500    public final boolean requestFocusFromTouch() {
10501        // Leave touch mode if we need to
10502        if (isInTouchMode()) {
10503            ViewRootImpl viewRoot = getViewRootImpl();
10504            if (viewRoot != null) {
10505                viewRoot.ensureTouchMode(false);
10506            }
10507        }
10508        return requestFocus(View.FOCUS_DOWN);
10509    }
10510
10511    /**
10512     * @return Whether any ancestor of this view blocks descendant focus.
10513     */
10514    private boolean hasAncestorThatBlocksDescendantFocus() {
10515        final boolean focusableInTouchMode = isFocusableInTouchMode();
10516        ViewParent ancestor = mParent;
10517        while (ancestor instanceof ViewGroup) {
10518            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10519            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10520                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10521                return true;
10522            } else {
10523                ancestor = vgAncestor.getParent();
10524            }
10525        }
10526        return false;
10527    }
10528
10529    /**
10530     * Gets the mode for determining whether this View is important for accessibility.
10531     * A view is important for accessibility if it fires accessibility events and if it
10532     * is reported to accessibility services that query the screen.
10533     *
10534     * @return The mode for determining whether a view is important for accessibility, one
10535     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10536     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10537     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10538     *
10539     * @attr ref android.R.styleable#View_importantForAccessibility
10540     *
10541     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10542     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10543     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10544     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10545     */
10546    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10547            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10548            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10549            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10550            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10551                    to = "noHideDescendants")
10552        })
10553    public int getImportantForAccessibility() {
10554        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10555                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10556    }
10557
10558    /**
10559     * Sets the live region mode for this view. This indicates to accessibility
10560     * services whether they should automatically notify the user about changes
10561     * to the view's content description or text, or to the content descriptions
10562     * or text of the view's children (where applicable).
10563     * <p>
10564     * For example, in a login screen with a TextView that displays an "incorrect
10565     * password" notification, that view should be marked as a live region with
10566     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10567     * <p>
10568     * To disable change notifications for this view, use
10569     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10570     * mode for most views.
10571     * <p>
10572     * To indicate that the user should be notified of changes, use
10573     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10574     * <p>
10575     * If the view's changes should interrupt ongoing speech and notify the user
10576     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10577     *
10578     * @param mode The live region mode for this view, one of:
10579     *        <ul>
10580     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10581     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10582     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10583     *        </ul>
10584     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10585     */
10586    public void setAccessibilityLiveRegion(int mode) {
10587        if (mode != getAccessibilityLiveRegion()) {
10588            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10589            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10590                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10591            notifyViewAccessibilityStateChangedIfNeeded(
10592                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10593        }
10594    }
10595
10596    /**
10597     * Gets the live region mode for this View.
10598     *
10599     * @return The live region mode for the view.
10600     *
10601     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10602     *
10603     * @see #setAccessibilityLiveRegion(int)
10604     */
10605    public int getAccessibilityLiveRegion() {
10606        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10607                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10608    }
10609
10610    /**
10611     * Sets how to determine whether this view is important for accessibility
10612     * which is if it fires accessibility events and if it is reported to
10613     * accessibility services that query the screen.
10614     *
10615     * @param mode How to determine whether this view is important for accessibility.
10616     *
10617     * @attr ref android.R.styleable#View_importantForAccessibility
10618     *
10619     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10620     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10621     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10622     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10623     */
10624    public void setImportantForAccessibility(int mode) {
10625        final int oldMode = getImportantForAccessibility();
10626        if (mode != oldMode) {
10627            final boolean hideDescendants =
10628                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10629
10630            // If this node or its descendants are no longer important, try to
10631            // clear accessibility focus.
10632            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10633                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10634                if (focusHost != null) {
10635                    focusHost.clearAccessibilityFocus();
10636                }
10637            }
10638
10639            // If we're moving between AUTO and another state, we might not need
10640            // to send a subtree changed notification. We'll store the computed
10641            // importance, since we'll need to check it later to make sure.
10642            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10643                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10644            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10645            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10646            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10647                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10648            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10649                notifySubtreeAccessibilityStateChangedIfNeeded();
10650            } else {
10651                notifyViewAccessibilityStateChangedIfNeeded(
10652                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10653            }
10654        }
10655    }
10656
10657    /**
10658     * Returns the view within this view's hierarchy that is hosting
10659     * accessibility focus.
10660     *
10661     * @param searchDescendants whether to search for focus in descendant views
10662     * @return the view hosting accessibility focus, or {@code null}
10663     */
10664    private View findAccessibilityFocusHost(boolean searchDescendants) {
10665        if (isAccessibilityFocusedViewOrHost()) {
10666            return this;
10667        }
10668
10669        if (searchDescendants) {
10670            final ViewRootImpl viewRoot = getViewRootImpl();
10671            if (viewRoot != null) {
10672                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10673                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10674                    return focusHost;
10675                }
10676            }
10677        }
10678
10679        return null;
10680    }
10681
10682    /**
10683     * Computes whether this view should be exposed for accessibility. In
10684     * general, views that are interactive or provide information are exposed
10685     * while views that serve only as containers are hidden.
10686     * <p>
10687     * If an ancestor of this view has importance
10688     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10689     * returns <code>false</code>.
10690     * <p>
10691     * Otherwise, the value is computed according to the view's
10692     * {@link #getImportantForAccessibility()} value:
10693     * <ol>
10694     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10695     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10696     * </code>
10697     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10698     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10699     * view satisfies any of the following:
10700     * <ul>
10701     * <li>Is actionable, e.g. {@link #isClickable()},
10702     * {@link #isLongClickable()}, or {@link #isFocusable()}
10703     * <li>Has an {@link AccessibilityDelegate}
10704     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10705     * {@link OnKeyListener}, etc.
10706     * <li>Is an accessibility live region, e.g.
10707     * {@link #getAccessibilityLiveRegion()} is not
10708     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10709     * </ul>
10710     * </ol>
10711     *
10712     * @return Whether the view is exposed for accessibility.
10713     * @see #setImportantForAccessibility(int)
10714     * @see #getImportantForAccessibility()
10715     */
10716    public boolean isImportantForAccessibility() {
10717        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10718                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10719        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10720                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10721            return false;
10722        }
10723
10724        // Check parent mode to ensure we're not hidden.
10725        ViewParent parent = mParent;
10726        while (parent instanceof View) {
10727            if (((View) parent).getImportantForAccessibility()
10728                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10729                return false;
10730            }
10731            parent = parent.getParent();
10732        }
10733
10734        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10735                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10736                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10737    }
10738
10739    /**
10740     * Gets the parent for accessibility purposes. Note that the parent for
10741     * accessibility is not necessary the immediate parent. It is the first
10742     * predecessor that is important for accessibility.
10743     *
10744     * @return The parent for accessibility purposes.
10745     */
10746    public ViewParent getParentForAccessibility() {
10747        if (mParent instanceof View) {
10748            View parentView = (View) mParent;
10749            if (parentView.includeForAccessibility()) {
10750                return mParent;
10751            } else {
10752                return mParent.getParentForAccessibility();
10753            }
10754        }
10755        return null;
10756    }
10757
10758    /**
10759     * Adds the children of this View relevant for accessibility to the given list
10760     * as output. Since some Views are not important for accessibility the added
10761     * child views are not necessarily direct children of this view, rather they are
10762     * the first level of descendants important for accessibility.
10763     *
10764     * @param outChildren The output list that will receive children for accessibility.
10765     */
10766    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10767
10768    }
10769
10770    /**
10771     * Whether to regard this view for accessibility. A view is regarded for
10772     * accessibility if it is important for accessibility or the querying
10773     * accessibility service has explicitly requested that view not
10774     * important for accessibility are regarded.
10775     *
10776     * @return Whether to regard the view for accessibility.
10777     *
10778     * @hide
10779     */
10780    public boolean includeForAccessibility() {
10781        if (mAttachInfo != null) {
10782            return (mAttachInfo.mAccessibilityFetchFlags
10783                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10784                    || isImportantForAccessibility();
10785        }
10786        return false;
10787    }
10788
10789    /**
10790     * Returns whether the View is considered actionable from
10791     * accessibility perspective. Such view are important for
10792     * accessibility.
10793     *
10794     * @return True if the view is actionable for accessibility.
10795     *
10796     * @hide
10797     */
10798    public boolean isActionableForAccessibility() {
10799        return (isClickable() || isLongClickable() || isFocusable());
10800    }
10801
10802    /**
10803     * Returns whether the View has registered callbacks which makes it
10804     * important for accessibility.
10805     *
10806     * @return True if the view is actionable for accessibility.
10807     */
10808    private boolean hasListenersForAccessibility() {
10809        ListenerInfo info = getListenerInfo();
10810        return mTouchDelegate != null || info.mOnKeyListener != null
10811                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10812                || info.mOnHoverListener != null || info.mOnDragListener != null;
10813    }
10814
10815    /**
10816     * Notifies that the accessibility state of this view changed. The change
10817     * is local to this view and does not represent structural changes such
10818     * as children and parent. For example, the view became focusable. The
10819     * notification is at at most once every
10820     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10821     * to avoid unnecessary load to the system. Also once a view has a pending
10822     * notification this method is a NOP until the notification has been sent.
10823     *
10824     * @hide
10825     */
10826    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10827        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10828            return;
10829        }
10830        if (mSendViewStateChangedAccessibilityEvent == null) {
10831            mSendViewStateChangedAccessibilityEvent =
10832                    new SendViewStateChangedAccessibilityEvent();
10833        }
10834        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10835    }
10836
10837    /**
10838     * Notifies that the accessibility state of this view changed. The change
10839     * is *not* local to this view and does represent structural changes such
10840     * as children and parent. For example, the view size changed. The
10841     * notification is at at most once every
10842     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10843     * to avoid unnecessary load to the system. Also once a view has a pending
10844     * notification this method is a NOP until the notification has been sent.
10845     *
10846     * @hide
10847     */
10848    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10849        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10850            return;
10851        }
10852        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10853            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10854            if (mParent != null) {
10855                try {
10856                    mParent.notifySubtreeAccessibilityStateChanged(
10857                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10858                } catch (AbstractMethodError e) {
10859                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10860                            " does not fully implement ViewParent", e);
10861                }
10862            }
10863        }
10864    }
10865
10866    /**
10867     * Change the visibility of the View without triggering any other changes. This is
10868     * important for transitions, where visibility changes should not adjust focus or
10869     * trigger a new layout. This is only used when the visibility has already been changed
10870     * and we need a transient value during an animation. When the animation completes,
10871     * the original visibility value is always restored.
10872     *
10873     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10874     * @hide
10875     */
10876    public void setTransitionVisibility(@Visibility int visibility) {
10877        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10878    }
10879
10880    /**
10881     * Reset the flag indicating the accessibility state of the subtree rooted
10882     * at this view changed.
10883     */
10884    void resetSubtreeAccessibilityStateChanged() {
10885        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10886    }
10887
10888    /**
10889     * Report an accessibility action to this view's parents for delegated processing.
10890     *
10891     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10892     * call this method to delegate an accessibility action to a supporting parent. If the parent
10893     * returns true from its
10894     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10895     * method this method will return true to signify that the action was consumed.</p>
10896     *
10897     * <p>This method is useful for implementing nested scrolling child views. If
10898     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10899     * a custom view implementation may invoke this method to allow a parent to consume the
10900     * scroll first. If this method returns true the custom view should skip its own scrolling
10901     * behavior.</p>
10902     *
10903     * @param action Accessibility action to delegate
10904     * @param arguments Optional action arguments
10905     * @return true if the action was consumed by a parent
10906     */
10907    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10908        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10909            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10910                return true;
10911            }
10912        }
10913        return false;
10914    }
10915
10916    /**
10917     * Performs the specified accessibility action on the view. For
10918     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10919     * <p>
10920     * If an {@link AccessibilityDelegate} has been specified via calling
10921     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10922     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10923     * is responsible for handling this call.
10924     * </p>
10925     *
10926     * <p>The default implementation will delegate
10927     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10928     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10929     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10930     *
10931     * @param action The action to perform.
10932     * @param arguments Optional action arguments.
10933     * @return Whether the action was performed.
10934     */
10935    public boolean performAccessibilityAction(int action, Bundle arguments) {
10936      if (mAccessibilityDelegate != null) {
10937          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10938      } else {
10939          return performAccessibilityActionInternal(action, arguments);
10940      }
10941    }
10942
10943   /**
10944    * @see #performAccessibilityAction(int, Bundle)
10945    *
10946    * Note: Called from the default {@link AccessibilityDelegate}.
10947    *
10948    * @hide
10949    */
10950    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10951        if (isNestedScrollingEnabled()
10952                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10953                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10954                || action == R.id.accessibilityActionScrollUp
10955                || action == R.id.accessibilityActionScrollLeft
10956                || action == R.id.accessibilityActionScrollDown
10957                || action == R.id.accessibilityActionScrollRight)) {
10958            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10959                return true;
10960            }
10961        }
10962
10963        switch (action) {
10964            case AccessibilityNodeInfo.ACTION_CLICK: {
10965                if (isClickable()) {
10966                    performClick();
10967                    return true;
10968                }
10969            } break;
10970            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10971                if (isLongClickable()) {
10972                    performLongClick();
10973                    return true;
10974                }
10975            } break;
10976            case AccessibilityNodeInfo.ACTION_FOCUS: {
10977                if (!hasFocus()) {
10978                    // Get out of touch mode since accessibility
10979                    // wants to move focus around.
10980                    getViewRootImpl().ensureTouchMode(false);
10981                    return requestFocus();
10982                }
10983            } break;
10984            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10985                if (hasFocus()) {
10986                    clearFocus();
10987                    return !isFocused();
10988                }
10989            } break;
10990            case AccessibilityNodeInfo.ACTION_SELECT: {
10991                if (!isSelected()) {
10992                    setSelected(true);
10993                    return isSelected();
10994                }
10995            } break;
10996            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10997                if (isSelected()) {
10998                    setSelected(false);
10999                    return !isSelected();
11000                }
11001            } break;
11002            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11003                if (!isAccessibilityFocused()) {
11004                    return requestAccessibilityFocus();
11005                }
11006            } break;
11007            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11008                if (isAccessibilityFocused()) {
11009                    clearAccessibilityFocus();
11010                    return true;
11011                }
11012            } break;
11013            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11014                if (arguments != null) {
11015                    final int granularity = arguments.getInt(
11016                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11017                    final boolean extendSelection = arguments.getBoolean(
11018                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11019                    return traverseAtGranularity(granularity, true, extendSelection);
11020                }
11021            } break;
11022            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11023                if (arguments != null) {
11024                    final int granularity = arguments.getInt(
11025                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11026                    final boolean extendSelection = arguments.getBoolean(
11027                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11028                    return traverseAtGranularity(granularity, false, extendSelection);
11029                }
11030            } break;
11031            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11032                CharSequence text = getIterableTextForAccessibility();
11033                if (text == null) {
11034                    return false;
11035                }
11036                final int start = (arguments != null) ? arguments.getInt(
11037                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11038                final int end = (arguments != null) ? arguments.getInt(
11039                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11040                // Only cursor position can be specified (selection length == 0)
11041                if ((getAccessibilitySelectionStart() != start
11042                        || getAccessibilitySelectionEnd() != end)
11043                        && (start == end)) {
11044                    setAccessibilitySelection(start, end);
11045                    notifyViewAccessibilityStateChangedIfNeeded(
11046                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11047                    return true;
11048                }
11049            } break;
11050            case R.id.accessibilityActionShowOnScreen: {
11051                if (mAttachInfo != null) {
11052                    final Rect r = mAttachInfo.mTmpInvalRect;
11053                    getDrawingRect(r);
11054                    return requestRectangleOnScreen(r, true);
11055                }
11056            } break;
11057            case R.id.accessibilityActionContextClick: {
11058                if (isContextClickable()) {
11059                    performContextClick();
11060                    return true;
11061                }
11062            } break;
11063        }
11064        return false;
11065    }
11066
11067    private boolean traverseAtGranularity(int granularity, boolean forward,
11068            boolean extendSelection) {
11069        CharSequence text = getIterableTextForAccessibility();
11070        if (text == null || text.length() == 0) {
11071            return false;
11072        }
11073        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11074        if (iterator == null) {
11075            return false;
11076        }
11077        int current = getAccessibilitySelectionEnd();
11078        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11079            current = forward ? 0 : text.length();
11080        }
11081        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11082        if (range == null) {
11083            return false;
11084        }
11085        final int segmentStart = range[0];
11086        final int segmentEnd = range[1];
11087        int selectionStart;
11088        int selectionEnd;
11089        if (extendSelection && isAccessibilitySelectionExtendable()) {
11090            selectionStart = getAccessibilitySelectionStart();
11091            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11092                selectionStart = forward ? segmentStart : segmentEnd;
11093            }
11094            selectionEnd = forward ? segmentEnd : segmentStart;
11095        } else {
11096            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11097        }
11098        setAccessibilitySelection(selectionStart, selectionEnd);
11099        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11100                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11101        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11102        return true;
11103    }
11104
11105    /**
11106     * Gets the text reported for accessibility purposes.
11107     *
11108     * @return The accessibility text.
11109     *
11110     * @hide
11111     */
11112    public CharSequence getIterableTextForAccessibility() {
11113        return getContentDescription();
11114    }
11115
11116    /**
11117     * Gets whether accessibility selection can be extended.
11118     *
11119     * @return If selection is extensible.
11120     *
11121     * @hide
11122     */
11123    public boolean isAccessibilitySelectionExtendable() {
11124        return false;
11125    }
11126
11127    /**
11128     * @hide
11129     */
11130    public int getAccessibilitySelectionStart() {
11131        return mAccessibilityCursorPosition;
11132    }
11133
11134    /**
11135     * @hide
11136     */
11137    public int getAccessibilitySelectionEnd() {
11138        return getAccessibilitySelectionStart();
11139    }
11140
11141    /**
11142     * @hide
11143     */
11144    public void setAccessibilitySelection(int start, int end) {
11145        if (start ==  end && end == mAccessibilityCursorPosition) {
11146            return;
11147        }
11148        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11149            mAccessibilityCursorPosition = start;
11150        } else {
11151            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11152        }
11153        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11154    }
11155
11156    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11157            int fromIndex, int toIndex) {
11158        if (mParent == null) {
11159            return;
11160        }
11161        AccessibilityEvent event = AccessibilityEvent.obtain(
11162                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11163        onInitializeAccessibilityEvent(event);
11164        onPopulateAccessibilityEvent(event);
11165        event.setFromIndex(fromIndex);
11166        event.setToIndex(toIndex);
11167        event.setAction(action);
11168        event.setMovementGranularity(granularity);
11169        mParent.requestSendAccessibilityEvent(this, event);
11170    }
11171
11172    /**
11173     * @hide
11174     */
11175    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11176        switch (granularity) {
11177            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11178                CharSequence text = getIterableTextForAccessibility();
11179                if (text != null && text.length() > 0) {
11180                    CharacterTextSegmentIterator iterator =
11181                        CharacterTextSegmentIterator.getInstance(
11182                                mContext.getResources().getConfiguration().locale);
11183                    iterator.initialize(text.toString());
11184                    return iterator;
11185                }
11186            } break;
11187            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11188                CharSequence text = getIterableTextForAccessibility();
11189                if (text != null && text.length() > 0) {
11190                    WordTextSegmentIterator iterator =
11191                        WordTextSegmentIterator.getInstance(
11192                                mContext.getResources().getConfiguration().locale);
11193                    iterator.initialize(text.toString());
11194                    return iterator;
11195                }
11196            } break;
11197            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11198                CharSequence text = getIterableTextForAccessibility();
11199                if (text != null && text.length() > 0) {
11200                    ParagraphTextSegmentIterator iterator =
11201                        ParagraphTextSegmentIterator.getInstance();
11202                    iterator.initialize(text.toString());
11203                    return iterator;
11204                }
11205            } break;
11206        }
11207        return null;
11208    }
11209
11210    /**
11211     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11212     * and {@link #onFinishTemporaryDetach()}.
11213     *
11214     * <p>This method always returns {@code true} when called directly or indirectly from
11215     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11216     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11217     * <ul>
11218     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11219     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11220     * </ul>
11221     * </p>
11222     *
11223     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11224     * and {@link #onFinishTemporaryDetach()}.
11225     */
11226    public final boolean isTemporarilyDetached() {
11227        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11228    }
11229
11230    /**
11231     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11232     * a container View.
11233     */
11234    @CallSuper
11235    public void dispatchStartTemporaryDetach() {
11236        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11237        notifyEnterOrExitForAutoFillIfNeeded(false);
11238        onStartTemporaryDetach();
11239    }
11240
11241    /**
11242     * This is called when a container is going to temporarily detach a child, with
11243     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11244     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11245     * {@link #onDetachedFromWindow()} when the container is done.
11246     */
11247    public void onStartTemporaryDetach() {
11248        removeUnsetPressCallback();
11249        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11250    }
11251
11252    /**
11253     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11254     * a container View.
11255     */
11256    @CallSuper
11257    public void dispatchFinishTemporaryDetach() {
11258        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11259        onFinishTemporaryDetach();
11260        if (hasWindowFocus() && hasFocus()) {
11261            InputMethodManager.getInstance().focusIn(this);
11262        }
11263        notifyEnterOrExitForAutoFillIfNeeded(true);
11264    }
11265
11266    /**
11267     * Called after {@link #onStartTemporaryDetach} when the container is done
11268     * changing the view.
11269     */
11270    public void onFinishTemporaryDetach() {
11271    }
11272
11273    /**
11274     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11275     * for this view's window.  Returns null if the view is not currently attached
11276     * to the window.  Normally you will not need to use this directly, but
11277     * just use the standard high-level event callbacks like
11278     * {@link #onKeyDown(int, KeyEvent)}.
11279     */
11280    public KeyEvent.DispatcherState getKeyDispatcherState() {
11281        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11282    }
11283
11284    /**
11285     * Dispatch a key event before it is processed by any input method
11286     * associated with the view hierarchy.  This can be used to intercept
11287     * key events in special situations before the IME consumes them; a
11288     * typical example would be handling the BACK key to update the application's
11289     * UI instead of allowing the IME to see it and close itself.
11290     *
11291     * @param event The key event to be dispatched.
11292     * @return True if the event was handled, false otherwise.
11293     */
11294    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11295        return onKeyPreIme(event.getKeyCode(), event);
11296    }
11297
11298    /**
11299     * Dispatch a key event to the next view on the focus path. This path runs
11300     * from the top of the view tree down to the currently focused view. If this
11301     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11302     * the next node down the focus path. This method also fires any key
11303     * listeners.
11304     *
11305     * @param event The key event to be dispatched.
11306     * @return True if the event was handled, false otherwise.
11307     */
11308    public boolean dispatchKeyEvent(KeyEvent event) {
11309        if (mInputEventConsistencyVerifier != null) {
11310            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11311        }
11312
11313        // Give any attached key listener a first crack at the event.
11314        //noinspection SimplifiableIfStatement
11315        ListenerInfo li = mListenerInfo;
11316        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11317                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11318            return true;
11319        }
11320
11321        if (event.dispatch(this, mAttachInfo != null
11322                ? mAttachInfo.mKeyDispatchState : null, this)) {
11323            return true;
11324        }
11325
11326        if (mInputEventConsistencyVerifier != null) {
11327            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11328        }
11329        return false;
11330    }
11331
11332    /**
11333     * Dispatches a key shortcut event.
11334     *
11335     * @param event The key event to be dispatched.
11336     * @return True if the event was handled by the view, false otherwise.
11337     */
11338    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11339        return onKeyShortcut(event.getKeyCode(), event);
11340    }
11341
11342    /**
11343     * Pass the touch screen motion event down to the target view, or this
11344     * view if it is the target.
11345     *
11346     * @param event The motion event to be dispatched.
11347     * @return True if the event was handled by the view, false otherwise.
11348     */
11349    public boolean dispatchTouchEvent(MotionEvent event) {
11350        // If the event should be handled by accessibility focus first.
11351        if (event.isTargetAccessibilityFocus()) {
11352            // We don't have focus or no virtual descendant has it, do not handle the event.
11353            if (!isAccessibilityFocusedViewOrHost()) {
11354                return false;
11355            }
11356            // We have focus and got the event, then use normal event dispatch.
11357            event.setTargetAccessibilityFocus(false);
11358        }
11359
11360        boolean result = false;
11361
11362        if (mInputEventConsistencyVerifier != null) {
11363            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11364        }
11365
11366        final int actionMasked = event.getActionMasked();
11367        if (actionMasked == MotionEvent.ACTION_DOWN) {
11368            // Defensive cleanup for new gesture
11369            stopNestedScroll();
11370        }
11371
11372        if (onFilterTouchEventForSecurity(event)) {
11373            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11374                result = true;
11375            }
11376            //noinspection SimplifiableIfStatement
11377            ListenerInfo li = mListenerInfo;
11378            if (li != null && li.mOnTouchListener != null
11379                    && (mViewFlags & ENABLED_MASK) == ENABLED
11380                    && li.mOnTouchListener.onTouch(this, event)) {
11381                result = true;
11382            }
11383
11384            if (!result && onTouchEvent(event)) {
11385                result = true;
11386            }
11387        }
11388
11389        if (!result && mInputEventConsistencyVerifier != null) {
11390            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11391        }
11392
11393        // Clean up after nested scrolls if this is the end of a gesture;
11394        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11395        // of the gesture.
11396        if (actionMasked == MotionEvent.ACTION_UP ||
11397                actionMasked == MotionEvent.ACTION_CANCEL ||
11398                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11399            stopNestedScroll();
11400        }
11401
11402        return result;
11403    }
11404
11405    boolean isAccessibilityFocusedViewOrHost() {
11406        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11407                .getAccessibilityFocusedHost() == this);
11408    }
11409
11410    /**
11411     * Filter the touch event to apply security policies.
11412     *
11413     * @param event The motion event to be filtered.
11414     * @return True if the event should be dispatched, false if the event should be dropped.
11415     *
11416     * @see #getFilterTouchesWhenObscured
11417     */
11418    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11419        //noinspection RedundantIfStatement
11420        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11421                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11422            // Window is obscured, drop this touch.
11423            return false;
11424        }
11425        return true;
11426    }
11427
11428    /**
11429     * Pass a trackball motion event down to the focused view.
11430     *
11431     * @param event The motion event to be dispatched.
11432     * @return True if the event was handled by the view, false otherwise.
11433     */
11434    public boolean dispatchTrackballEvent(MotionEvent event) {
11435        if (mInputEventConsistencyVerifier != null) {
11436            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11437        }
11438
11439        return onTrackballEvent(event);
11440    }
11441
11442    /**
11443     * Pass a captured pointer event down to the focused view.
11444     *
11445     * @param event The motion event to be dispatched.
11446     * @return True if the event was handled by the view, false otherwise.
11447     */
11448    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11449        if (!hasPointerCapture()) {
11450            return false;
11451        }
11452        //noinspection SimplifiableIfStatement
11453        ListenerInfo li = mListenerInfo;
11454        if (li != null && li.mOnCapturedPointerListener != null
11455                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11456            return true;
11457        }
11458        return onCapturedPointerEvent(event);
11459    }
11460
11461    /**
11462     * Dispatch a generic motion event.
11463     * <p>
11464     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11465     * are delivered to the view under the pointer.  All other generic motion events are
11466     * delivered to the focused view.  Hover events are handled specially and are delivered
11467     * to {@link #onHoverEvent(MotionEvent)}.
11468     * </p>
11469     *
11470     * @param event The motion event to be dispatched.
11471     * @return True if the event was handled by the view, false otherwise.
11472     */
11473    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11474        if (mInputEventConsistencyVerifier != null) {
11475            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11476        }
11477
11478        final int source = event.getSource();
11479        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11480            final int action = event.getAction();
11481            if (action == MotionEvent.ACTION_HOVER_ENTER
11482                    || action == MotionEvent.ACTION_HOVER_MOVE
11483                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11484                if (dispatchHoverEvent(event)) {
11485                    return true;
11486                }
11487            } else if (dispatchGenericPointerEvent(event)) {
11488                return true;
11489            }
11490        } else if (dispatchGenericFocusedEvent(event)) {
11491            return true;
11492        }
11493
11494        if (dispatchGenericMotionEventInternal(event)) {
11495            return true;
11496        }
11497
11498        if (mInputEventConsistencyVerifier != null) {
11499            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11500        }
11501        return false;
11502    }
11503
11504    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11505        //noinspection SimplifiableIfStatement
11506        ListenerInfo li = mListenerInfo;
11507        if (li != null && li.mOnGenericMotionListener != null
11508                && (mViewFlags & ENABLED_MASK) == ENABLED
11509                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11510            return true;
11511        }
11512
11513        if (onGenericMotionEvent(event)) {
11514            return true;
11515        }
11516
11517        final int actionButton = event.getActionButton();
11518        switch (event.getActionMasked()) {
11519            case MotionEvent.ACTION_BUTTON_PRESS:
11520                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11521                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11522                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11523                    if (performContextClick(event.getX(), event.getY())) {
11524                        mInContextButtonPress = true;
11525                        setPressed(true, event.getX(), event.getY());
11526                        removeTapCallback();
11527                        removeLongPressCallback();
11528                        return true;
11529                    }
11530                }
11531                break;
11532
11533            case MotionEvent.ACTION_BUTTON_RELEASE:
11534                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11535                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11536                    mInContextButtonPress = false;
11537                    mIgnoreNextUpEvent = true;
11538                }
11539                break;
11540        }
11541
11542        if (mInputEventConsistencyVerifier != null) {
11543            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11544        }
11545        return false;
11546    }
11547
11548    /**
11549     * Dispatch a hover event.
11550     * <p>
11551     * Do not call this method directly.
11552     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11553     * </p>
11554     *
11555     * @param event The motion event to be dispatched.
11556     * @return True if the event was handled by the view, false otherwise.
11557     */
11558    protected boolean dispatchHoverEvent(MotionEvent event) {
11559        ListenerInfo li = mListenerInfo;
11560        //noinspection SimplifiableIfStatement
11561        if (li != null && li.mOnHoverListener != null
11562                && (mViewFlags & ENABLED_MASK) == ENABLED
11563                && li.mOnHoverListener.onHover(this, event)) {
11564            return true;
11565        }
11566
11567        return onHoverEvent(event);
11568    }
11569
11570    /**
11571     * Returns true if the view has a child to which it has recently sent
11572     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11573     * it does not have a hovered child, then it must be the innermost hovered view.
11574     * @hide
11575     */
11576    protected boolean hasHoveredChild() {
11577        return false;
11578    }
11579
11580    /**
11581     * Dispatch a generic motion event to the view under the first pointer.
11582     * <p>
11583     * Do not call this method directly.
11584     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11585     * </p>
11586     *
11587     * @param event The motion event to be dispatched.
11588     * @return True if the event was handled by the view, false otherwise.
11589     */
11590    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11591        return false;
11592    }
11593
11594    /**
11595     * Dispatch a generic motion event to the currently focused view.
11596     * <p>
11597     * Do not call this method directly.
11598     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11599     * </p>
11600     *
11601     * @param event The motion event to be dispatched.
11602     * @return True if the event was handled by the view, false otherwise.
11603     */
11604    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11605        return false;
11606    }
11607
11608    /**
11609     * Dispatch a pointer event.
11610     * <p>
11611     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11612     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11613     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11614     * and should not be expected to handle other pointing device features.
11615     * </p>
11616     *
11617     * @param event The motion event to be dispatched.
11618     * @return True if the event was handled by the view, false otherwise.
11619     * @hide
11620     */
11621    public final boolean dispatchPointerEvent(MotionEvent event) {
11622        if (event.isTouchEvent()) {
11623            return dispatchTouchEvent(event);
11624        } else {
11625            return dispatchGenericMotionEvent(event);
11626        }
11627    }
11628
11629    /**
11630     * Called when the window containing this view gains or loses window focus.
11631     * ViewGroups should override to route to their children.
11632     *
11633     * @param hasFocus True if the window containing this view now has focus,
11634     *        false otherwise.
11635     */
11636    public void dispatchWindowFocusChanged(boolean hasFocus) {
11637        onWindowFocusChanged(hasFocus);
11638    }
11639
11640    /**
11641     * Called when the window containing this view gains or loses focus.  Note
11642     * that this is separate from view focus: to receive key events, both
11643     * your view and its window must have focus.  If a window is displayed
11644     * on top of yours that takes input focus, then your own window will lose
11645     * focus but the view focus will remain unchanged.
11646     *
11647     * @param hasWindowFocus True if the window containing this view now has
11648     *        focus, false otherwise.
11649     */
11650    public void onWindowFocusChanged(boolean hasWindowFocus) {
11651        InputMethodManager imm = InputMethodManager.peekInstance();
11652        if (!hasWindowFocus) {
11653            if (isPressed()) {
11654                setPressed(false);
11655            }
11656            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11657            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11658                imm.focusOut(this);
11659            }
11660            removeLongPressCallback();
11661            removeTapCallback();
11662            onFocusLost();
11663        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11664            imm.focusIn(this);
11665        }
11666
11667        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11668
11669        refreshDrawableState();
11670    }
11671
11672    /**
11673     * Returns true if this view is in a window that currently has window focus.
11674     * Note that this is not the same as the view itself having focus.
11675     *
11676     * @return True if this view is in a window that currently has window focus.
11677     */
11678    public boolean hasWindowFocus() {
11679        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11680    }
11681
11682    /**
11683     * Dispatch a view visibility change down the view hierarchy.
11684     * ViewGroups should override to route to their children.
11685     * @param changedView The view whose visibility changed. Could be 'this' or
11686     * an ancestor view.
11687     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11688     * {@link #INVISIBLE} or {@link #GONE}.
11689     */
11690    protected void dispatchVisibilityChanged(@NonNull View changedView,
11691            @Visibility int visibility) {
11692        onVisibilityChanged(changedView, visibility);
11693    }
11694
11695    /**
11696     * Called when the visibility of the view or an ancestor of the view has
11697     * changed.
11698     *
11699     * @param changedView The view whose visibility changed. May be
11700     *                    {@code this} or an ancestor view.
11701     * @param visibility The new visibility, one of {@link #VISIBLE},
11702     *                   {@link #INVISIBLE} or {@link #GONE}.
11703     */
11704    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11705    }
11706
11707    /**
11708     * Dispatch a hint about whether this view is displayed. For instance, when
11709     * a View moves out of the screen, it might receives a display hint indicating
11710     * the view is not displayed. Applications should not <em>rely</em> on this hint
11711     * as there is no guarantee that they will receive one.
11712     *
11713     * @param hint A hint about whether or not this view is displayed:
11714     * {@link #VISIBLE} or {@link #INVISIBLE}.
11715     */
11716    public void dispatchDisplayHint(@Visibility int hint) {
11717        onDisplayHint(hint);
11718    }
11719
11720    /**
11721     * Gives this view a hint about whether is displayed or not. For instance, when
11722     * a View moves out of the screen, it might receives a display hint indicating
11723     * the view is not displayed. Applications should not <em>rely</em> on this hint
11724     * as there is no guarantee that they will receive one.
11725     *
11726     * @param hint A hint about whether or not this view is displayed:
11727     * {@link #VISIBLE} or {@link #INVISIBLE}.
11728     */
11729    protected void onDisplayHint(@Visibility int hint) {
11730    }
11731
11732    /**
11733     * Dispatch a window visibility change down the view hierarchy.
11734     * ViewGroups should override to route to their children.
11735     *
11736     * @param visibility The new visibility of the window.
11737     *
11738     * @see #onWindowVisibilityChanged(int)
11739     */
11740    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11741        onWindowVisibilityChanged(visibility);
11742    }
11743
11744    /**
11745     * Called when the window containing has change its visibility
11746     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11747     * that this tells you whether or not your window is being made visible
11748     * to the window manager; this does <em>not</em> tell you whether or not
11749     * your window is obscured by other windows on the screen, even if it
11750     * is itself visible.
11751     *
11752     * @param visibility The new visibility of the window.
11753     */
11754    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11755        if (visibility == VISIBLE) {
11756            initialAwakenScrollBars();
11757        }
11758    }
11759
11760    /**
11761     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11762     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11763     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11764     *
11765     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11766     *                  ancestors or by window visibility
11767     * @return true if this view is visible to the user, not counting clipping or overlapping
11768     */
11769    boolean dispatchVisibilityAggregated(boolean isVisible) {
11770        final boolean thisVisible = getVisibility() == VISIBLE;
11771        // If we're not visible but something is telling us we are, ignore it.
11772        if (thisVisible || !isVisible) {
11773            onVisibilityAggregated(isVisible);
11774        }
11775        return thisVisible && isVisible;
11776    }
11777
11778    /**
11779     * Called when the user-visibility of this View is potentially affected by a change
11780     * to this view itself, an ancestor view or the window this view is attached to.
11781     *
11782     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11783     *                  and this view's window is also visible
11784     */
11785    @CallSuper
11786    public void onVisibilityAggregated(boolean isVisible) {
11787        if (isVisible && mAttachInfo != null) {
11788            initialAwakenScrollBars();
11789        }
11790
11791        final Drawable dr = mBackground;
11792        if (dr != null && isVisible != dr.isVisible()) {
11793            dr.setVisible(isVisible, false);
11794        }
11795        final Drawable hl = mDefaultFocusHighlight;
11796        if (hl != null && isVisible != hl.isVisible()) {
11797            hl.setVisible(isVisible, false);
11798        }
11799        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11800        if (fg != null && isVisible != fg.isVisible()) {
11801            fg.setVisible(isVisible, false);
11802        }
11803
11804        if (isAutofillable()) {
11805            AutofillManager afm = getAutofillManager();
11806
11807            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
11808                if (mVisibilityChangeForAutofillHandler != null) {
11809                    mVisibilityChangeForAutofillHandler.removeMessages(0);
11810                }
11811
11812                // If the view is in the background but still part of the hierarchy this is called
11813                // with isVisible=false. Hence visibility==false requires further checks
11814                if (isVisible) {
11815                    afm.notifyViewVisibilityChange(this, true);
11816                } else {
11817                    if (mVisibilityChangeForAutofillHandler == null) {
11818                        mVisibilityChangeForAutofillHandler =
11819                                new VisibilityChangeForAutofillHandler(afm, this);
11820                    }
11821                    // Let current operation (e.g. removal of the view from the hierarchy)
11822                    // finish before checking state
11823                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
11824                }
11825            }
11826        }
11827    }
11828
11829    /**
11830     * Returns the current visibility of the window this view is attached to
11831     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11832     *
11833     * @return Returns the current visibility of the view's window.
11834     */
11835    @Visibility
11836    public int getWindowVisibility() {
11837        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11838    }
11839
11840    /**
11841     * Retrieve the overall visible display size in which the window this view is
11842     * attached to has been positioned in.  This takes into account screen
11843     * decorations above the window, for both cases where the window itself
11844     * is being position inside of them or the window is being placed under
11845     * then and covered insets are used for the window to position its content
11846     * inside.  In effect, this tells you the available area where content can
11847     * be placed and remain visible to users.
11848     *
11849     * <p>This function requires an IPC back to the window manager to retrieve
11850     * the requested information, so should not be used in performance critical
11851     * code like drawing.
11852     *
11853     * @param outRect Filled in with the visible display frame.  If the view
11854     * is not attached to a window, this is simply the raw display size.
11855     */
11856    public void getWindowVisibleDisplayFrame(Rect outRect) {
11857        if (mAttachInfo != null) {
11858            try {
11859                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11860            } catch (RemoteException e) {
11861                return;
11862            }
11863            // XXX This is really broken, and probably all needs to be done
11864            // in the window manager, and we need to know more about whether
11865            // we want the area behind or in front of the IME.
11866            final Rect insets = mAttachInfo.mVisibleInsets;
11867            outRect.left += insets.left;
11868            outRect.top += insets.top;
11869            outRect.right -= insets.right;
11870            outRect.bottom -= insets.bottom;
11871            return;
11872        }
11873        // The view is not attached to a display so we don't have a context.
11874        // Make a best guess about the display size.
11875        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11876        d.getRectSize(outRect);
11877    }
11878
11879    /**
11880     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11881     * is currently in without any insets.
11882     *
11883     * @hide
11884     */
11885    public void getWindowDisplayFrame(Rect outRect) {
11886        if (mAttachInfo != null) {
11887            try {
11888                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11889            } catch (RemoteException e) {
11890                return;
11891            }
11892            return;
11893        }
11894        // The view is not attached to a display so we don't have a context.
11895        // Make a best guess about the display size.
11896        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11897        d.getRectSize(outRect);
11898    }
11899
11900    /**
11901     * Dispatch a notification about a resource configuration change down
11902     * the view hierarchy.
11903     * ViewGroups should override to route to their children.
11904     *
11905     * @param newConfig The new resource configuration.
11906     *
11907     * @see #onConfigurationChanged(android.content.res.Configuration)
11908     */
11909    public void dispatchConfigurationChanged(Configuration newConfig) {
11910        onConfigurationChanged(newConfig);
11911    }
11912
11913    /**
11914     * Called when the current configuration of the resources being used
11915     * by the application have changed.  You can use this to decide when
11916     * to reload resources that can changed based on orientation and other
11917     * configuration characteristics.  You only need to use this if you are
11918     * not relying on the normal {@link android.app.Activity} mechanism of
11919     * recreating the activity instance upon a configuration change.
11920     *
11921     * @param newConfig The new resource configuration.
11922     */
11923    protected void onConfigurationChanged(Configuration newConfig) {
11924    }
11925
11926    /**
11927     * Private function to aggregate all per-view attributes in to the view
11928     * root.
11929     */
11930    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11931        performCollectViewAttributes(attachInfo, visibility);
11932    }
11933
11934    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11935        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11936            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11937                attachInfo.mKeepScreenOn = true;
11938            }
11939            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11940            ListenerInfo li = mListenerInfo;
11941            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11942                attachInfo.mHasSystemUiListeners = true;
11943            }
11944        }
11945    }
11946
11947    void needGlobalAttributesUpdate(boolean force) {
11948        final AttachInfo ai = mAttachInfo;
11949        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11950            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11951                    || ai.mHasSystemUiListeners) {
11952                ai.mRecomputeGlobalAttributes = true;
11953            }
11954        }
11955    }
11956
11957    /**
11958     * Returns whether the device is currently in touch mode.  Touch mode is entered
11959     * once the user begins interacting with the device by touch, and affects various
11960     * things like whether focus is always visible to the user.
11961     *
11962     * @return Whether the device is in touch mode.
11963     */
11964    @ViewDebug.ExportedProperty
11965    public boolean isInTouchMode() {
11966        if (mAttachInfo != null) {
11967            return mAttachInfo.mInTouchMode;
11968        } else {
11969            return ViewRootImpl.isInTouchMode();
11970        }
11971    }
11972
11973    /**
11974     * Returns the context the view is running in, through which it can
11975     * access the current theme, resources, etc.
11976     *
11977     * @return The view's Context.
11978     */
11979    @ViewDebug.CapturedViewProperty
11980    public final Context getContext() {
11981        return mContext;
11982    }
11983
11984    /**
11985     * Handle a key event before it is processed by any input method
11986     * associated with the view hierarchy.  This can be used to intercept
11987     * key events in special situations before the IME consumes them; a
11988     * typical example would be handling the BACK key to update the application's
11989     * UI instead of allowing the IME to see it and close itself.
11990     *
11991     * @param keyCode The value in event.getKeyCode().
11992     * @param event Description of the key event.
11993     * @return If you handled the event, return true. If you want to allow the
11994     *         event to be handled by the next receiver, return false.
11995     */
11996    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11997        return false;
11998    }
11999
12000    /**
12001     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12002     * KeyEvent.Callback.onKeyDown()}: perform press of the view
12003     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12004     * is released, if the view is enabled and clickable.
12005     * <p>
12006     * Key presses in software keyboards will generally NOT trigger this
12007     * listener, although some may elect to do so in some situations. Do not
12008     * rely on this to catch software key presses.
12009     *
12010     * @param keyCode a key code that represents the button pressed, from
12011     *                {@link android.view.KeyEvent}
12012     * @param event the KeyEvent object that defines the button action
12013     */
12014    public boolean onKeyDown(int keyCode, KeyEvent event) {
12015        if (KeyEvent.isConfirmKey(keyCode)) {
12016            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12017                return true;
12018            }
12019
12020            if (event.getRepeatCount() == 0) {
12021                // Long clickable items don't necessarily have to be clickable.
12022                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12023                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12024                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12025                    // For the purposes of menu anchoring and drawable hotspots,
12026                    // key events are considered to be at the center of the view.
12027                    final float x = getWidth() / 2f;
12028                    final float y = getHeight() / 2f;
12029                    if (clickable) {
12030                        setPressed(true, x, y);
12031                    }
12032                    checkForLongClick(0, x, y);
12033                    return true;
12034                }
12035            }
12036        }
12037
12038        return false;
12039    }
12040
12041    /**
12042     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12043     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12044     * the event).
12045     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12046     * although some may elect to do so in some situations. Do not rely on this to
12047     * catch software key presses.
12048     */
12049    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12050        return false;
12051    }
12052
12053    /**
12054     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12055     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12056     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12057     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12058     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12059     * although some may elect to do so in some situations. Do not rely on this to
12060     * catch software key presses.
12061     *
12062     * @param keyCode A key code that represents the button pressed, from
12063     *                {@link android.view.KeyEvent}.
12064     * @param event   The KeyEvent object that defines the button action.
12065     */
12066    public boolean onKeyUp(int keyCode, KeyEvent event) {
12067        if (KeyEvent.isConfirmKey(keyCode)) {
12068            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12069                return true;
12070            }
12071            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12072                setPressed(false);
12073
12074                if (!mHasPerformedLongPress) {
12075                    // This is a tap, so remove the longpress check
12076                    removeLongPressCallback();
12077                    if (!event.isCanceled()) {
12078                        return performClick();
12079                    }
12080                }
12081            }
12082        }
12083        return false;
12084    }
12085
12086    /**
12087     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12088     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12089     * the event).
12090     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12091     * although some may elect to do so in some situations. Do not rely on this to
12092     * catch software key presses.
12093     *
12094     * @param keyCode     A key code that represents the button pressed, from
12095     *                    {@link android.view.KeyEvent}.
12096     * @param repeatCount The number of times the action was made.
12097     * @param event       The KeyEvent object that defines the button action.
12098     */
12099    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12100        return false;
12101    }
12102
12103    /**
12104     * Called on the focused view when a key shortcut event is not handled.
12105     * Override this method to implement local key shortcuts for the View.
12106     * Key shortcuts can also be implemented by setting the
12107     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12108     *
12109     * @param keyCode The value in event.getKeyCode().
12110     * @param event Description of the key event.
12111     * @return If you handled the event, return true. If you want to allow the
12112     *         event to be handled by the next receiver, return false.
12113     */
12114    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12115        return false;
12116    }
12117
12118    /**
12119     * Check whether the called view is a text editor, in which case it
12120     * would make sense to automatically display a soft input window for
12121     * it.  Subclasses should override this if they implement
12122     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12123     * a call on that method would return a non-null InputConnection, and
12124     * they are really a first-class editor that the user would normally
12125     * start typing on when the go into a window containing your view.
12126     *
12127     * <p>The default implementation always returns false.  This does
12128     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12129     * will not be called or the user can not otherwise perform edits on your
12130     * view; it is just a hint to the system that this is not the primary
12131     * purpose of this view.
12132     *
12133     * @return Returns true if this view is a text editor, else false.
12134     */
12135    public boolean onCheckIsTextEditor() {
12136        return false;
12137    }
12138
12139    /**
12140     * Create a new InputConnection for an InputMethod to interact
12141     * with the view.  The default implementation returns null, since it doesn't
12142     * support input methods.  You can override this to implement such support.
12143     * This is only needed for views that take focus and text input.
12144     *
12145     * <p>When implementing this, you probably also want to implement
12146     * {@link #onCheckIsTextEditor()} to indicate you will return a
12147     * non-null InputConnection.</p>
12148     *
12149     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12150     * object correctly and in its entirety, so that the connected IME can rely
12151     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12152     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12153     * must be filled in with the correct cursor position for IMEs to work correctly
12154     * with your application.</p>
12155     *
12156     * @param outAttrs Fill in with attribute information about the connection.
12157     */
12158    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12159        return null;
12160    }
12161
12162    /**
12163     * Called by the {@link android.view.inputmethod.InputMethodManager}
12164     * when a view who is not the current
12165     * input connection target is trying to make a call on the manager.  The
12166     * default implementation returns false; you can override this to return
12167     * true for certain views if you are performing InputConnection proxying
12168     * to them.
12169     * @param view The View that is making the InputMethodManager call.
12170     * @return Return true to allow the call, false to reject.
12171     */
12172    public boolean checkInputConnectionProxy(View view) {
12173        return false;
12174    }
12175
12176    /**
12177     * Show the context menu for this view. It is not safe to hold on to the
12178     * menu after returning from this method.
12179     *
12180     * You should normally not overload this method. Overload
12181     * {@link #onCreateContextMenu(ContextMenu)} or define an
12182     * {@link OnCreateContextMenuListener} to add items to the context menu.
12183     *
12184     * @param menu The context menu to populate
12185     */
12186    public void createContextMenu(ContextMenu menu) {
12187        ContextMenuInfo menuInfo = getContextMenuInfo();
12188
12189        // Sets the current menu info so all items added to menu will have
12190        // my extra info set.
12191        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12192
12193        onCreateContextMenu(menu);
12194        ListenerInfo li = mListenerInfo;
12195        if (li != null && li.mOnCreateContextMenuListener != null) {
12196            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12197        }
12198
12199        // Clear the extra information so subsequent items that aren't mine don't
12200        // have my extra info.
12201        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12202
12203        if (mParent != null) {
12204            mParent.createContextMenu(menu);
12205        }
12206    }
12207
12208    /**
12209     * Views should implement this if they have extra information to associate
12210     * with the context menu. The return result is supplied as a parameter to
12211     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12212     * callback.
12213     *
12214     * @return Extra information about the item for which the context menu
12215     *         should be shown. This information will vary across different
12216     *         subclasses of View.
12217     */
12218    protected ContextMenuInfo getContextMenuInfo() {
12219        return null;
12220    }
12221
12222    /**
12223     * Views should implement this if the view itself is going to add items to
12224     * the context menu.
12225     *
12226     * @param menu the context menu to populate
12227     */
12228    protected void onCreateContextMenu(ContextMenu menu) {
12229    }
12230
12231    /**
12232     * Implement this method to handle trackball motion events.  The
12233     * <em>relative</em> movement of the trackball since the last event
12234     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12235     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12236     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12237     * they will often be fractional values, representing the more fine-grained
12238     * movement information available from a trackball).
12239     *
12240     * @param event The motion event.
12241     * @return True if the event was handled, false otherwise.
12242     */
12243    public boolean onTrackballEvent(MotionEvent event) {
12244        return false;
12245    }
12246
12247    /**
12248     * Implement this method to handle generic motion events.
12249     * <p>
12250     * Generic motion events describe joystick movements, mouse hovers, track pad
12251     * touches, scroll wheel movements and other input events.  The
12252     * {@link MotionEvent#getSource() source} of the motion event specifies
12253     * the class of input that was received.  Implementations of this method
12254     * must examine the bits in the source before processing the event.
12255     * The following code example shows how this is done.
12256     * </p><p>
12257     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12258     * are delivered to the view under the pointer.  All other generic motion events are
12259     * delivered to the focused view.
12260     * </p>
12261     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12262     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12263     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12264     *             // process the joystick movement...
12265     *             return true;
12266     *         }
12267     *     }
12268     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12269     *         switch (event.getAction()) {
12270     *             case MotionEvent.ACTION_HOVER_MOVE:
12271     *                 // process the mouse hover movement...
12272     *                 return true;
12273     *             case MotionEvent.ACTION_SCROLL:
12274     *                 // process the scroll wheel movement...
12275     *                 return true;
12276     *         }
12277     *     }
12278     *     return super.onGenericMotionEvent(event);
12279     * }</pre>
12280     *
12281     * @param event The generic motion event being processed.
12282     * @return True if the event was handled, false otherwise.
12283     */
12284    public boolean onGenericMotionEvent(MotionEvent event) {
12285        return false;
12286    }
12287
12288    /**
12289     * Implement this method to handle hover events.
12290     * <p>
12291     * This method is called whenever a pointer is hovering into, over, or out of the
12292     * bounds of a view and the view is not currently being touched.
12293     * Hover events are represented as pointer events with action
12294     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12295     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12296     * </p>
12297     * <ul>
12298     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12299     * when the pointer enters the bounds of the view.</li>
12300     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12301     * when the pointer has already entered the bounds of the view and has moved.</li>
12302     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12303     * when the pointer has exited the bounds of the view or when the pointer is
12304     * about to go down due to a button click, tap, or similar user action that
12305     * causes the view to be touched.</li>
12306     * </ul>
12307     * <p>
12308     * The view should implement this method to return true to indicate that it is
12309     * handling the hover event, such as by changing its drawable state.
12310     * </p><p>
12311     * The default implementation calls {@link #setHovered} to update the hovered state
12312     * of the view when a hover enter or hover exit event is received, if the view
12313     * is enabled and is clickable.  The default implementation also sends hover
12314     * accessibility events.
12315     * </p>
12316     *
12317     * @param event The motion event that describes the hover.
12318     * @return True if the view handled the hover event.
12319     *
12320     * @see #isHovered
12321     * @see #setHovered
12322     * @see #onHoverChanged
12323     */
12324    public boolean onHoverEvent(MotionEvent event) {
12325        // The root view may receive hover (or touch) events that are outside the bounds of
12326        // the window.  This code ensures that we only send accessibility events for
12327        // hovers that are actually within the bounds of the root view.
12328        final int action = event.getActionMasked();
12329        if (!mSendingHoverAccessibilityEvents) {
12330            if ((action == MotionEvent.ACTION_HOVER_ENTER
12331                    || action == MotionEvent.ACTION_HOVER_MOVE)
12332                    && !hasHoveredChild()
12333                    && pointInView(event.getX(), event.getY())) {
12334                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12335                mSendingHoverAccessibilityEvents = true;
12336            }
12337        } else {
12338            if (action == MotionEvent.ACTION_HOVER_EXIT
12339                    || (action == MotionEvent.ACTION_MOVE
12340                            && !pointInView(event.getX(), event.getY()))) {
12341                mSendingHoverAccessibilityEvents = false;
12342                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12343            }
12344        }
12345
12346        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12347                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12348                && isOnScrollbar(event.getX(), event.getY())) {
12349            awakenScrollBars();
12350        }
12351
12352        // If we consider ourself hoverable, or if we we're already hovered,
12353        // handle changing state in response to ENTER and EXIT events.
12354        if (isHoverable() || isHovered()) {
12355            switch (action) {
12356                case MotionEvent.ACTION_HOVER_ENTER:
12357                    setHovered(true);
12358                    break;
12359                case MotionEvent.ACTION_HOVER_EXIT:
12360                    setHovered(false);
12361                    break;
12362            }
12363
12364            // Dispatch the event to onGenericMotionEvent before returning true.
12365            // This is to provide compatibility with existing applications that
12366            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12367            // break because of the new default handling for hoverable views
12368            // in onHoverEvent.
12369            // Note that onGenericMotionEvent will be called by default when
12370            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12371            dispatchGenericMotionEventInternal(event);
12372            // The event was already handled by calling setHovered(), so always
12373            // return true.
12374            return true;
12375        }
12376
12377        return false;
12378    }
12379
12380    /**
12381     * Returns true if the view should handle {@link #onHoverEvent}
12382     * by calling {@link #setHovered} to change its hovered state.
12383     *
12384     * @return True if the view is hoverable.
12385     */
12386    private boolean isHoverable() {
12387        final int viewFlags = mViewFlags;
12388        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12389            return false;
12390        }
12391
12392        return (viewFlags & CLICKABLE) == CLICKABLE
12393                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12394                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12395    }
12396
12397    /**
12398     * Returns true if the view is currently hovered.
12399     *
12400     * @return True if the view is currently hovered.
12401     *
12402     * @see #setHovered
12403     * @see #onHoverChanged
12404     */
12405    @ViewDebug.ExportedProperty
12406    public boolean isHovered() {
12407        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12408    }
12409
12410    /**
12411     * Sets whether the view is currently hovered.
12412     * <p>
12413     * Calling this method also changes the drawable state of the view.  This
12414     * enables the view to react to hover by using different drawable resources
12415     * to change its appearance.
12416     * </p><p>
12417     * The {@link #onHoverChanged} method is called when the hovered state changes.
12418     * </p>
12419     *
12420     * @param hovered True if the view is hovered.
12421     *
12422     * @see #isHovered
12423     * @see #onHoverChanged
12424     */
12425    public void setHovered(boolean hovered) {
12426        if (hovered) {
12427            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12428                mPrivateFlags |= PFLAG_HOVERED;
12429                refreshDrawableState();
12430                onHoverChanged(true);
12431            }
12432        } else {
12433            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12434                mPrivateFlags &= ~PFLAG_HOVERED;
12435                refreshDrawableState();
12436                onHoverChanged(false);
12437            }
12438        }
12439    }
12440
12441    /**
12442     * Implement this method to handle hover state changes.
12443     * <p>
12444     * This method is called whenever the hover state changes as a result of a
12445     * call to {@link #setHovered}.
12446     * </p>
12447     *
12448     * @param hovered The current hover state, as returned by {@link #isHovered}.
12449     *
12450     * @see #isHovered
12451     * @see #setHovered
12452     */
12453    public void onHoverChanged(boolean hovered) {
12454    }
12455
12456    /**
12457     * Handles scroll bar dragging by mouse input.
12458     *
12459     * @hide
12460     * @param event The motion event.
12461     *
12462     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12463     */
12464    protected boolean handleScrollBarDragging(MotionEvent event) {
12465        if (mScrollCache == null) {
12466            return false;
12467        }
12468        final float x = event.getX();
12469        final float y = event.getY();
12470        final int action = event.getAction();
12471        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12472                && action != MotionEvent.ACTION_DOWN)
12473                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12474                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12475            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12476            return false;
12477        }
12478
12479        switch (action) {
12480            case MotionEvent.ACTION_MOVE:
12481                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12482                    return false;
12483                }
12484                if (mScrollCache.mScrollBarDraggingState
12485                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12486                    final Rect bounds = mScrollCache.mScrollBarBounds;
12487                    getVerticalScrollBarBounds(bounds, null);
12488                    final int range = computeVerticalScrollRange();
12489                    final int offset = computeVerticalScrollOffset();
12490                    final int extent = computeVerticalScrollExtent();
12491
12492                    final int thumbLength = ScrollBarUtils.getThumbLength(
12493                            bounds.height(), bounds.width(), extent, range);
12494                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12495                            bounds.height(), thumbLength, extent, range, offset);
12496
12497                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12498                    final float maxThumbOffset = bounds.height() - thumbLength;
12499                    final float newThumbOffset =
12500                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12501                    final int height = getHeight();
12502                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12503                            && height > 0 && extent > 0) {
12504                        final int newY = Math.round((range - extent)
12505                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12506                        if (newY != getScrollY()) {
12507                            mScrollCache.mScrollBarDraggingPos = y;
12508                            setScrollY(newY);
12509                        }
12510                    }
12511                    return true;
12512                }
12513                if (mScrollCache.mScrollBarDraggingState
12514                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12515                    final Rect bounds = mScrollCache.mScrollBarBounds;
12516                    getHorizontalScrollBarBounds(bounds, null);
12517                    final int range = computeHorizontalScrollRange();
12518                    final int offset = computeHorizontalScrollOffset();
12519                    final int extent = computeHorizontalScrollExtent();
12520
12521                    final int thumbLength = ScrollBarUtils.getThumbLength(
12522                            bounds.width(), bounds.height(), extent, range);
12523                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12524                            bounds.width(), thumbLength, extent, range, offset);
12525
12526                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12527                    final float maxThumbOffset = bounds.width() - thumbLength;
12528                    final float newThumbOffset =
12529                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12530                    final int width = getWidth();
12531                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12532                            && width > 0 && extent > 0) {
12533                        final int newX = Math.round((range - extent)
12534                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12535                        if (newX != getScrollX()) {
12536                            mScrollCache.mScrollBarDraggingPos = x;
12537                            setScrollX(newX);
12538                        }
12539                    }
12540                    return true;
12541                }
12542            case MotionEvent.ACTION_DOWN:
12543                if (mScrollCache.state == ScrollabilityCache.OFF) {
12544                    return false;
12545                }
12546                if (isOnVerticalScrollbarThumb(x, y)) {
12547                    mScrollCache.mScrollBarDraggingState =
12548                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12549                    mScrollCache.mScrollBarDraggingPos = y;
12550                    return true;
12551                }
12552                if (isOnHorizontalScrollbarThumb(x, y)) {
12553                    mScrollCache.mScrollBarDraggingState =
12554                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12555                    mScrollCache.mScrollBarDraggingPos = x;
12556                    return true;
12557                }
12558        }
12559        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12560        return false;
12561    }
12562
12563    /**
12564     * Implement this method to handle touch screen motion events.
12565     * <p>
12566     * If this method is used to detect click actions, it is recommended that
12567     * the actions be performed by implementing and calling
12568     * {@link #performClick()}. This will ensure consistent system behavior,
12569     * including:
12570     * <ul>
12571     * <li>obeying click sound preferences
12572     * <li>dispatching OnClickListener calls
12573     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12574     * accessibility features are enabled
12575     * </ul>
12576     *
12577     * @param event The motion event.
12578     * @return True if the event was handled, false otherwise.
12579     */
12580    public boolean onTouchEvent(MotionEvent event) {
12581        final float x = event.getX();
12582        final float y = event.getY();
12583        final int viewFlags = mViewFlags;
12584        final int action = event.getAction();
12585
12586        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12587                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12588                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12589
12590        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12591            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12592                setPressed(false);
12593            }
12594            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12595            // A disabled view that is clickable still consumes the touch
12596            // events, it just doesn't respond to them.
12597            return clickable;
12598        }
12599        if (mTouchDelegate != null) {
12600            if (mTouchDelegate.onTouchEvent(event)) {
12601                return true;
12602            }
12603        }
12604
12605        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12606            switch (action) {
12607                case MotionEvent.ACTION_UP:
12608                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12609                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12610                        handleTooltipUp();
12611                    }
12612                    if (!clickable) {
12613                        removeTapCallback();
12614                        removeLongPressCallback();
12615                        mInContextButtonPress = false;
12616                        mHasPerformedLongPress = false;
12617                        mIgnoreNextUpEvent = false;
12618                        break;
12619                    }
12620                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12621                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12622                        // take focus if we don't have it already and we should in
12623                        // touch mode.
12624                        boolean focusTaken = false;
12625                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12626                            focusTaken = requestFocus();
12627                        }
12628
12629                        if (prepressed) {
12630                            // The button is being released before we actually
12631                            // showed it as pressed.  Make it show the pressed
12632                            // state now (before scheduling the click) to ensure
12633                            // the user sees it.
12634                            setPressed(true, x, y);
12635                        }
12636
12637                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12638                            // This is a tap, so remove the longpress check
12639                            removeLongPressCallback();
12640
12641                            // Only perform take click actions if we were in the pressed state
12642                            if (!focusTaken) {
12643                                // Use a Runnable and post this rather than calling
12644                                // performClick directly. This lets other visual state
12645                                // of the view update before click actions start.
12646                                if (mPerformClick == null) {
12647                                    mPerformClick = new PerformClick();
12648                                }
12649                                if (!post(mPerformClick)) {
12650                                    performClick();
12651                                }
12652                            }
12653                        }
12654
12655                        if (mUnsetPressedState == null) {
12656                            mUnsetPressedState = new UnsetPressedState();
12657                        }
12658
12659                        if (prepressed) {
12660                            postDelayed(mUnsetPressedState,
12661                                    ViewConfiguration.getPressedStateDuration());
12662                        } else if (!post(mUnsetPressedState)) {
12663                            // If the post failed, unpress right now
12664                            mUnsetPressedState.run();
12665                        }
12666
12667                        removeTapCallback();
12668                    }
12669                    mIgnoreNextUpEvent = false;
12670                    break;
12671
12672                case MotionEvent.ACTION_DOWN:
12673                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12674                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12675                    }
12676                    mHasPerformedLongPress = false;
12677
12678                    if (!clickable) {
12679                        checkForLongClick(0, x, y);
12680                        break;
12681                    }
12682
12683                    if (performButtonActionOnTouchDown(event)) {
12684                        break;
12685                    }
12686
12687                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12688                    boolean isInScrollingContainer = isInScrollingContainer();
12689
12690                    // For views inside a scrolling container, delay the pressed feedback for
12691                    // a short period in case this is a scroll.
12692                    if (isInScrollingContainer) {
12693                        mPrivateFlags |= PFLAG_PREPRESSED;
12694                        if (mPendingCheckForTap == null) {
12695                            mPendingCheckForTap = new CheckForTap();
12696                        }
12697                        mPendingCheckForTap.x = event.getX();
12698                        mPendingCheckForTap.y = event.getY();
12699                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12700                    } else {
12701                        // Not inside a scrolling container, so show the feedback right away
12702                        setPressed(true, x, y);
12703                        checkForLongClick(0, x, y);
12704                    }
12705                    break;
12706
12707                case MotionEvent.ACTION_CANCEL:
12708                    if (clickable) {
12709                        setPressed(false);
12710                    }
12711                    removeTapCallback();
12712                    removeLongPressCallback();
12713                    mInContextButtonPress = false;
12714                    mHasPerformedLongPress = false;
12715                    mIgnoreNextUpEvent = false;
12716                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12717                    break;
12718
12719                case MotionEvent.ACTION_MOVE:
12720                    if (clickable) {
12721                        drawableHotspotChanged(x, y);
12722                    }
12723
12724                    // Be lenient about moving outside of buttons
12725                    if (!pointInView(x, y, mTouchSlop)) {
12726                        // Outside button
12727                        // Remove any future long press/tap checks
12728                        removeTapCallback();
12729                        removeLongPressCallback();
12730                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12731                            setPressed(false);
12732                        }
12733                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12734                    }
12735                    break;
12736            }
12737
12738            return true;
12739        }
12740
12741        return false;
12742    }
12743
12744    /**
12745     * @hide
12746     */
12747    public boolean isInScrollingContainer() {
12748        ViewParent p = getParent();
12749        while (p != null && p instanceof ViewGroup) {
12750            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12751                return true;
12752            }
12753            p = p.getParent();
12754        }
12755        return false;
12756    }
12757
12758    /**
12759     * Remove the longpress detection timer.
12760     */
12761    private void removeLongPressCallback() {
12762        if (mPendingCheckForLongPress != null) {
12763            removeCallbacks(mPendingCheckForLongPress);
12764        }
12765    }
12766
12767    /**
12768     * Remove the pending click action
12769     */
12770    private void removePerformClickCallback() {
12771        if (mPerformClick != null) {
12772            removeCallbacks(mPerformClick);
12773        }
12774    }
12775
12776    /**
12777     * Remove the prepress detection timer.
12778     */
12779    private void removeUnsetPressCallback() {
12780        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12781            setPressed(false);
12782            removeCallbacks(mUnsetPressedState);
12783        }
12784    }
12785
12786    /**
12787     * Remove the tap detection timer.
12788     */
12789    private void removeTapCallback() {
12790        if (mPendingCheckForTap != null) {
12791            mPrivateFlags &= ~PFLAG_PREPRESSED;
12792            removeCallbacks(mPendingCheckForTap);
12793        }
12794    }
12795
12796    /**
12797     * Cancels a pending long press.  Your subclass can use this if you
12798     * want the context menu to come up if the user presses and holds
12799     * at the same place, but you don't want it to come up if they press
12800     * and then move around enough to cause scrolling.
12801     */
12802    public void cancelLongPress() {
12803        removeLongPressCallback();
12804
12805        /*
12806         * The prepressed state handled by the tap callback is a display
12807         * construct, but the tap callback will post a long press callback
12808         * less its own timeout. Remove it here.
12809         */
12810        removeTapCallback();
12811    }
12812
12813    /**
12814     * Remove the pending callback for sending a
12815     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12816     */
12817    private void removeSendViewScrolledAccessibilityEventCallback() {
12818        if (mSendViewScrolledAccessibilityEvent != null) {
12819            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12820            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12821        }
12822    }
12823
12824    /**
12825     * Sets the TouchDelegate for this View.
12826     */
12827    public void setTouchDelegate(TouchDelegate delegate) {
12828        mTouchDelegate = delegate;
12829    }
12830
12831    /**
12832     * Gets the TouchDelegate for this View.
12833     */
12834    public TouchDelegate getTouchDelegate() {
12835        return mTouchDelegate;
12836    }
12837
12838    /**
12839     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12840     *
12841     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12842     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12843     * available. This method should only be called for touch events.
12844     *
12845     * <p class="note">This api is not intended for most applications. Buffered dispatch
12846     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12847     * streams will not improve your input latency. Side effects include: increased latency,
12848     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12849     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12850     * you.</p>
12851     */
12852    public final void requestUnbufferedDispatch(MotionEvent event) {
12853        final int action = event.getAction();
12854        if (mAttachInfo == null
12855                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12856                || !event.isTouchEvent()) {
12857            return;
12858        }
12859        mAttachInfo.mUnbufferedDispatchRequested = true;
12860    }
12861
12862    /**
12863     * Set flags controlling behavior of this view.
12864     *
12865     * @param flags Constant indicating the value which should be set
12866     * @param mask Constant indicating the bit range that should be changed
12867     */
12868    void setFlags(int flags, int mask) {
12869        final boolean accessibilityEnabled =
12870                AccessibilityManager.getInstance(mContext).isEnabled();
12871        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12872
12873        int old = mViewFlags;
12874        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12875
12876        int changed = mViewFlags ^ old;
12877        if (changed == 0) {
12878            return;
12879        }
12880        int privateFlags = mPrivateFlags;
12881
12882        // If focusable is auto, update the FOCUSABLE bit.
12883        int focusableChangedByAuto = 0;
12884        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12885                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12886            // Heuristic only takes into account whether view is clickable.
12887            final int newFocus;
12888            if ((mViewFlags & CLICKABLE) != 0) {
12889                newFocus = FOCUSABLE;
12890            } else {
12891                newFocus = NOT_FOCUSABLE;
12892            }
12893            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12894            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12895            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12896        }
12897
12898        /* Check if the FOCUSABLE bit has changed */
12899        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12900            if (((old & FOCUSABLE) == FOCUSABLE)
12901                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12902                /* Give up focus if we are no longer focusable */
12903                clearFocus();
12904            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12905                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12906                /*
12907                 * Tell the view system that we are now available to take focus
12908                 * if no one else already has it.
12909                 */
12910                if (mParent != null) {
12911                    ViewRootImpl viewRootImpl = getViewRootImpl();
12912                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12913                            || focusableChangedByAuto == 0
12914                            || viewRootImpl == null
12915                            || viewRootImpl.mThread == Thread.currentThread()) {
12916                        mParent.focusableViewAvailable(this);
12917                    }
12918                }
12919            }
12920        }
12921
12922        final int newVisibility = flags & VISIBILITY_MASK;
12923        if (newVisibility == VISIBLE) {
12924            if ((changed & VISIBILITY_MASK) != 0) {
12925                /*
12926                 * If this view is becoming visible, invalidate it in case it changed while
12927                 * it was not visible. Marking it drawn ensures that the invalidation will
12928                 * go through.
12929                 */
12930                mPrivateFlags |= PFLAG_DRAWN;
12931                invalidate(true);
12932
12933                needGlobalAttributesUpdate(true);
12934
12935                // a view becoming visible is worth notifying the parent
12936                // about in case nothing has focus.  even if this specific view
12937                // isn't focusable, it may contain something that is, so let
12938                // the root view try to give this focus if nothing else does.
12939                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12940                    mParent.focusableViewAvailable(this);
12941                }
12942            }
12943        }
12944
12945        /* Check if the GONE bit has changed */
12946        if ((changed & GONE) != 0) {
12947            needGlobalAttributesUpdate(false);
12948            requestLayout();
12949
12950            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12951                if (hasFocus()) clearFocus();
12952                clearAccessibilityFocus();
12953                destroyDrawingCache();
12954                if (mParent instanceof View) {
12955                    // GONE views noop invalidation, so invalidate the parent
12956                    ((View) mParent).invalidate(true);
12957                }
12958                // Mark the view drawn to ensure that it gets invalidated properly the next
12959                // time it is visible and gets invalidated
12960                mPrivateFlags |= PFLAG_DRAWN;
12961            }
12962            if (mAttachInfo != null) {
12963                mAttachInfo.mViewVisibilityChanged = true;
12964            }
12965        }
12966
12967        /* Check if the VISIBLE bit has changed */
12968        if ((changed & INVISIBLE) != 0) {
12969            needGlobalAttributesUpdate(false);
12970            /*
12971             * If this view is becoming invisible, set the DRAWN flag so that
12972             * the next invalidate() will not be skipped.
12973             */
12974            mPrivateFlags |= PFLAG_DRAWN;
12975
12976            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12977                // root view becoming invisible shouldn't clear focus and accessibility focus
12978                if (getRootView() != this) {
12979                    if (hasFocus()) clearFocus();
12980                    clearAccessibilityFocus();
12981                }
12982            }
12983            if (mAttachInfo != null) {
12984                mAttachInfo.mViewVisibilityChanged = true;
12985            }
12986        }
12987
12988        if ((changed & VISIBILITY_MASK) != 0) {
12989            // If the view is invisible, cleanup its display list to free up resources
12990            if (newVisibility != VISIBLE && mAttachInfo != null) {
12991                cleanupDraw();
12992            }
12993
12994            if (mParent instanceof ViewGroup) {
12995                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12996                        (changed & VISIBILITY_MASK), newVisibility);
12997                ((View) mParent).invalidate(true);
12998            } else if (mParent != null) {
12999                mParent.invalidateChild(this, null);
13000            }
13001
13002            if (mAttachInfo != null) {
13003                dispatchVisibilityChanged(this, newVisibility);
13004
13005                // Aggregated visibility changes are dispatched to attached views
13006                // in visible windows where the parent is currently shown/drawn
13007                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13008                // discounting clipping or overlapping. This makes it a good place
13009                // to change animation states.
13010                if (mParent != null && getWindowVisibility() == VISIBLE &&
13011                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13012                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
13013                }
13014                notifySubtreeAccessibilityStateChangedIfNeeded();
13015            }
13016        }
13017
13018        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13019            destroyDrawingCache();
13020        }
13021
13022        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13023            destroyDrawingCache();
13024            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13025            invalidateParentCaches();
13026        }
13027
13028        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13029            destroyDrawingCache();
13030            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13031        }
13032
13033        if ((changed & DRAW_MASK) != 0) {
13034            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13035                if (mBackground != null
13036                        || mDefaultFocusHighlight != null
13037                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13038                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13039                } else {
13040                    mPrivateFlags |= PFLAG_SKIP_DRAW;
13041                }
13042            } else {
13043                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13044            }
13045            requestLayout();
13046            invalidate(true);
13047        }
13048
13049        if ((changed & KEEP_SCREEN_ON) != 0) {
13050            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13051                mParent.recomputeViewAttributes(this);
13052            }
13053        }
13054
13055        if (accessibilityEnabled) {
13056            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13057                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13058                    || (changed & CONTEXT_CLICKABLE) != 0) {
13059                if (oldIncludeForAccessibility != includeForAccessibility()) {
13060                    notifySubtreeAccessibilityStateChangedIfNeeded();
13061                } else {
13062                    notifyViewAccessibilityStateChangedIfNeeded(
13063                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13064                }
13065            } else if ((changed & ENABLED_MASK) != 0) {
13066                notifyViewAccessibilityStateChangedIfNeeded(
13067                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13068            }
13069        }
13070    }
13071
13072    /**
13073     * Change the view's z order in the tree, so it's on top of other sibling
13074     * views. This ordering change may affect layout, if the parent container
13075     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13076     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13077     * method should be followed by calls to {@link #requestLayout()} and
13078     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13079     * with the new child ordering.
13080     *
13081     * @see ViewGroup#bringChildToFront(View)
13082     */
13083    public void bringToFront() {
13084        if (mParent != null) {
13085            mParent.bringChildToFront(this);
13086        }
13087    }
13088
13089    /**
13090     * This is called in response to an internal scroll in this view (i.e., the
13091     * view scrolled its own contents). This is typically as a result of
13092     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13093     * called.
13094     *
13095     * @param l Current horizontal scroll origin.
13096     * @param t Current vertical scroll origin.
13097     * @param oldl Previous horizontal scroll origin.
13098     * @param oldt Previous vertical scroll origin.
13099     */
13100    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13101        notifySubtreeAccessibilityStateChangedIfNeeded();
13102
13103        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13104            postSendViewScrolledAccessibilityEventCallback();
13105        }
13106
13107        mBackgroundSizeChanged = true;
13108        mDefaultFocusHighlightSizeChanged = true;
13109        if (mForegroundInfo != null) {
13110            mForegroundInfo.mBoundsChanged = true;
13111        }
13112
13113        final AttachInfo ai = mAttachInfo;
13114        if (ai != null) {
13115            ai.mViewScrollChanged = true;
13116        }
13117
13118        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13119            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13120        }
13121    }
13122
13123    /**
13124     * Interface definition for a callback to be invoked when the scroll
13125     * X or Y positions of a view change.
13126     * <p>
13127     * <b>Note:</b> Some views handle scrolling independently from View and may
13128     * have their own separate listeners for scroll-type events. For example,
13129     * {@link android.widget.ListView ListView} allows clients to register an
13130     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13131     * to listen for changes in list scroll position.
13132     *
13133     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13134     */
13135    public interface OnScrollChangeListener {
13136        /**
13137         * Called when the scroll position of a view changes.
13138         *
13139         * @param v The view whose scroll position has changed.
13140         * @param scrollX Current horizontal scroll origin.
13141         * @param scrollY Current vertical scroll origin.
13142         * @param oldScrollX Previous horizontal scroll origin.
13143         * @param oldScrollY Previous vertical scroll origin.
13144         */
13145        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13146    }
13147
13148    /**
13149     * Interface definition for a callback to be invoked when the layout bounds of a view
13150     * changes due to layout processing.
13151     */
13152    public interface OnLayoutChangeListener {
13153        /**
13154         * Called when the layout bounds of a view changes due to layout processing.
13155         *
13156         * @param v The view whose bounds have changed.
13157         * @param left The new value of the view's left property.
13158         * @param top The new value of the view's top property.
13159         * @param right The new value of the view's right property.
13160         * @param bottom The new value of the view's bottom property.
13161         * @param oldLeft The previous value of the view's left property.
13162         * @param oldTop The previous value of the view's top property.
13163         * @param oldRight The previous value of the view's right property.
13164         * @param oldBottom The previous value of the view's bottom property.
13165         */
13166        void onLayoutChange(View v, int left, int top, int right, int bottom,
13167            int oldLeft, int oldTop, int oldRight, int oldBottom);
13168    }
13169
13170    /**
13171     * This is called during layout when the size of this view has changed. If
13172     * you were just added to the view hierarchy, you're called with the old
13173     * values of 0.
13174     *
13175     * @param w Current width of this view.
13176     * @param h Current height of this view.
13177     * @param oldw Old width of this view.
13178     * @param oldh Old height of this view.
13179     */
13180    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13181    }
13182
13183    /**
13184     * Called by draw to draw the child views. This may be overridden
13185     * by derived classes to gain control just before its children are drawn
13186     * (but after its own view has been drawn).
13187     * @param canvas the canvas on which to draw the view
13188     */
13189    protected void dispatchDraw(Canvas canvas) {
13190
13191    }
13192
13193    /**
13194     * Gets the parent of this view. Note that the parent is a
13195     * ViewParent and not necessarily a View.
13196     *
13197     * @return Parent of this view.
13198     */
13199    public final ViewParent getParent() {
13200        return mParent;
13201    }
13202
13203    /**
13204     * Set the horizontal scrolled position of your view. This will cause a call to
13205     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13206     * invalidated.
13207     * @param value the x position to scroll to
13208     */
13209    public void setScrollX(int value) {
13210        scrollTo(value, mScrollY);
13211    }
13212
13213    /**
13214     * Set the vertical scrolled position of your view. This will cause a call to
13215     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13216     * invalidated.
13217     * @param value the y position to scroll to
13218     */
13219    public void setScrollY(int value) {
13220        scrollTo(mScrollX, value);
13221    }
13222
13223    /**
13224     * Return the scrolled left position of this view. This is the left edge of
13225     * the displayed part of your view. You do not need to draw any pixels
13226     * farther left, since those are outside of the frame of your view on
13227     * screen.
13228     *
13229     * @return The left edge of the displayed part of your view, in pixels.
13230     */
13231    public final int getScrollX() {
13232        return mScrollX;
13233    }
13234
13235    /**
13236     * Return the scrolled top position of this view. This is the top edge of
13237     * the displayed part of your view. You do not need to draw any pixels above
13238     * it, since those are outside of the frame of your view on screen.
13239     *
13240     * @return The top edge of the displayed part of your view, in pixels.
13241     */
13242    public final int getScrollY() {
13243        return mScrollY;
13244    }
13245
13246    /**
13247     * Return the width of the your view.
13248     *
13249     * @return The width of your view, in pixels.
13250     */
13251    @ViewDebug.ExportedProperty(category = "layout")
13252    public final int getWidth() {
13253        return mRight - mLeft;
13254    }
13255
13256    /**
13257     * Return the height of your view.
13258     *
13259     * @return The height of your view, in pixels.
13260     */
13261    @ViewDebug.ExportedProperty(category = "layout")
13262    public final int getHeight() {
13263        return mBottom - mTop;
13264    }
13265
13266    /**
13267     * Return the visible drawing bounds of your view. Fills in the output
13268     * rectangle with the values from getScrollX(), getScrollY(),
13269     * getWidth(), and getHeight(). These bounds do not account for any
13270     * transformation properties currently set on the view, such as
13271     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13272     *
13273     * @param outRect The (scrolled) drawing bounds of the view.
13274     */
13275    public void getDrawingRect(Rect outRect) {
13276        outRect.left = mScrollX;
13277        outRect.top = mScrollY;
13278        outRect.right = mScrollX + (mRight - mLeft);
13279        outRect.bottom = mScrollY + (mBottom - mTop);
13280    }
13281
13282    /**
13283     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13284     * raw width component (that is the result is masked by
13285     * {@link #MEASURED_SIZE_MASK}).
13286     *
13287     * @return The raw measured width of this view.
13288     */
13289    public final int getMeasuredWidth() {
13290        return mMeasuredWidth & MEASURED_SIZE_MASK;
13291    }
13292
13293    /**
13294     * Return the full width measurement information for this view as computed
13295     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13296     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13297     * This should be used during measurement and layout calculations only. Use
13298     * {@link #getWidth()} to see how wide a view is after layout.
13299     *
13300     * @return The measured width of this view as a bit mask.
13301     */
13302    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13303            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13304                    name = "MEASURED_STATE_TOO_SMALL"),
13305    })
13306    public final int getMeasuredWidthAndState() {
13307        return mMeasuredWidth;
13308    }
13309
13310    /**
13311     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13312     * raw height component (that is the result is masked by
13313     * {@link #MEASURED_SIZE_MASK}).
13314     *
13315     * @return The raw measured height of this view.
13316     */
13317    public final int getMeasuredHeight() {
13318        return mMeasuredHeight & MEASURED_SIZE_MASK;
13319    }
13320
13321    /**
13322     * Return the full height measurement information for this view as computed
13323     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13324     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13325     * This should be used during measurement and layout calculations only. Use
13326     * {@link #getHeight()} to see how wide a view is after layout.
13327     *
13328     * @return The measured height of this view as a bit mask.
13329     */
13330    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13331            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13332                    name = "MEASURED_STATE_TOO_SMALL"),
13333    })
13334    public final int getMeasuredHeightAndState() {
13335        return mMeasuredHeight;
13336    }
13337
13338    /**
13339     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13340     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13341     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13342     * and the height component is at the shifted bits
13343     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13344     */
13345    public final int getMeasuredState() {
13346        return (mMeasuredWidth&MEASURED_STATE_MASK)
13347                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13348                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13349    }
13350
13351    /**
13352     * The transform matrix of this view, which is calculated based on the current
13353     * rotation, scale, and pivot properties.
13354     *
13355     * @see #getRotation()
13356     * @see #getScaleX()
13357     * @see #getScaleY()
13358     * @see #getPivotX()
13359     * @see #getPivotY()
13360     * @return The current transform matrix for the view
13361     */
13362    public Matrix getMatrix() {
13363        ensureTransformationInfo();
13364        final Matrix matrix = mTransformationInfo.mMatrix;
13365        mRenderNode.getMatrix(matrix);
13366        return matrix;
13367    }
13368
13369    /**
13370     * Returns true if the transform matrix is the identity matrix.
13371     * Recomputes the matrix if necessary.
13372     *
13373     * @return True if the transform matrix is the identity matrix, false otherwise.
13374     */
13375    final boolean hasIdentityMatrix() {
13376        return mRenderNode.hasIdentityMatrix();
13377    }
13378
13379    void ensureTransformationInfo() {
13380        if (mTransformationInfo == null) {
13381            mTransformationInfo = new TransformationInfo();
13382        }
13383    }
13384
13385    /**
13386     * Utility method to retrieve the inverse of the current mMatrix property.
13387     * We cache the matrix to avoid recalculating it when transform properties
13388     * have not changed.
13389     *
13390     * @return The inverse of the current matrix of this view.
13391     * @hide
13392     */
13393    public final Matrix getInverseMatrix() {
13394        ensureTransformationInfo();
13395        if (mTransformationInfo.mInverseMatrix == null) {
13396            mTransformationInfo.mInverseMatrix = new Matrix();
13397        }
13398        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13399        mRenderNode.getInverseMatrix(matrix);
13400        return matrix;
13401    }
13402
13403    /**
13404     * Gets the distance along the Z axis from the camera to this view.
13405     *
13406     * @see #setCameraDistance(float)
13407     *
13408     * @return The distance along the Z axis.
13409     */
13410    public float getCameraDistance() {
13411        final float dpi = mResources.getDisplayMetrics().densityDpi;
13412        return -(mRenderNode.getCameraDistance() * dpi);
13413    }
13414
13415    /**
13416     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13417     * views are drawn) from the camera to this view. The camera's distance
13418     * affects 3D transformations, for instance rotations around the X and Y
13419     * axis. If the rotationX or rotationY properties are changed and this view is
13420     * large (more than half the size of the screen), it is recommended to always
13421     * use a camera distance that's greater than the height (X axis rotation) or
13422     * the width (Y axis rotation) of this view.</p>
13423     *
13424     * <p>The distance of the camera from the view plane can have an affect on the
13425     * perspective distortion of the view when it is rotated around the x or y axis.
13426     * For example, a large distance will result in a large viewing angle, and there
13427     * will not be much perspective distortion of the view as it rotates. A short
13428     * distance may cause much more perspective distortion upon rotation, and can
13429     * also result in some drawing artifacts if the rotated view ends up partially
13430     * behind the camera (which is why the recommendation is to use a distance at
13431     * least as far as the size of the view, if the view is to be rotated.)</p>
13432     *
13433     * <p>The distance is expressed in "depth pixels." The default distance depends
13434     * on the screen density. For instance, on a medium density display, the
13435     * default distance is 1280. On a high density display, the default distance
13436     * is 1920.</p>
13437     *
13438     * <p>If you want to specify a distance that leads to visually consistent
13439     * results across various densities, use the following formula:</p>
13440     * <pre>
13441     * float scale = context.getResources().getDisplayMetrics().density;
13442     * view.setCameraDistance(distance * scale);
13443     * </pre>
13444     *
13445     * <p>The density scale factor of a high density display is 1.5,
13446     * and 1920 = 1280 * 1.5.</p>
13447     *
13448     * @param distance The distance in "depth pixels", if negative the opposite
13449     *        value is used
13450     *
13451     * @see #setRotationX(float)
13452     * @see #setRotationY(float)
13453     */
13454    public void setCameraDistance(float distance) {
13455        final float dpi = mResources.getDisplayMetrics().densityDpi;
13456
13457        invalidateViewProperty(true, false);
13458        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13459        invalidateViewProperty(false, false);
13460
13461        invalidateParentIfNeededAndWasQuickRejected();
13462    }
13463
13464    /**
13465     * The degrees that the view is rotated around the pivot point.
13466     *
13467     * @see #setRotation(float)
13468     * @see #getPivotX()
13469     * @see #getPivotY()
13470     *
13471     * @return The degrees of rotation.
13472     */
13473    @ViewDebug.ExportedProperty(category = "drawing")
13474    public float getRotation() {
13475        return mRenderNode.getRotation();
13476    }
13477
13478    /**
13479     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13480     * result in clockwise rotation.
13481     *
13482     * @param rotation The degrees of rotation.
13483     *
13484     * @see #getRotation()
13485     * @see #getPivotX()
13486     * @see #getPivotY()
13487     * @see #setRotationX(float)
13488     * @see #setRotationY(float)
13489     *
13490     * @attr ref android.R.styleable#View_rotation
13491     */
13492    public void setRotation(float rotation) {
13493        if (rotation != getRotation()) {
13494            // Double-invalidation is necessary to capture view's old and new areas
13495            invalidateViewProperty(true, false);
13496            mRenderNode.setRotation(rotation);
13497            invalidateViewProperty(false, true);
13498
13499            invalidateParentIfNeededAndWasQuickRejected();
13500            notifySubtreeAccessibilityStateChangedIfNeeded();
13501        }
13502    }
13503
13504    /**
13505     * The degrees that the view is rotated around the vertical axis through the pivot point.
13506     *
13507     * @see #getPivotX()
13508     * @see #getPivotY()
13509     * @see #setRotationY(float)
13510     *
13511     * @return The degrees of Y rotation.
13512     */
13513    @ViewDebug.ExportedProperty(category = "drawing")
13514    public float getRotationY() {
13515        return mRenderNode.getRotationY();
13516    }
13517
13518    /**
13519     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13520     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13521     * down the y axis.
13522     *
13523     * When rotating large views, it is recommended to adjust the camera distance
13524     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13525     *
13526     * @param rotationY The degrees of Y rotation.
13527     *
13528     * @see #getRotationY()
13529     * @see #getPivotX()
13530     * @see #getPivotY()
13531     * @see #setRotation(float)
13532     * @see #setRotationX(float)
13533     * @see #setCameraDistance(float)
13534     *
13535     * @attr ref android.R.styleable#View_rotationY
13536     */
13537    public void setRotationY(float rotationY) {
13538        if (rotationY != getRotationY()) {
13539            invalidateViewProperty(true, false);
13540            mRenderNode.setRotationY(rotationY);
13541            invalidateViewProperty(false, true);
13542
13543            invalidateParentIfNeededAndWasQuickRejected();
13544            notifySubtreeAccessibilityStateChangedIfNeeded();
13545        }
13546    }
13547
13548    /**
13549     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13550     *
13551     * @see #getPivotX()
13552     * @see #getPivotY()
13553     * @see #setRotationX(float)
13554     *
13555     * @return The degrees of X rotation.
13556     */
13557    @ViewDebug.ExportedProperty(category = "drawing")
13558    public float getRotationX() {
13559        return mRenderNode.getRotationX();
13560    }
13561
13562    /**
13563     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13564     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13565     * x axis.
13566     *
13567     * When rotating large views, it is recommended to adjust the camera distance
13568     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13569     *
13570     * @param rotationX The degrees of X rotation.
13571     *
13572     * @see #getRotationX()
13573     * @see #getPivotX()
13574     * @see #getPivotY()
13575     * @see #setRotation(float)
13576     * @see #setRotationY(float)
13577     * @see #setCameraDistance(float)
13578     *
13579     * @attr ref android.R.styleable#View_rotationX
13580     */
13581    public void setRotationX(float rotationX) {
13582        if (rotationX != getRotationX()) {
13583            invalidateViewProperty(true, false);
13584            mRenderNode.setRotationX(rotationX);
13585            invalidateViewProperty(false, true);
13586
13587            invalidateParentIfNeededAndWasQuickRejected();
13588            notifySubtreeAccessibilityStateChangedIfNeeded();
13589        }
13590    }
13591
13592    /**
13593     * The amount that the view is scaled in x around the pivot point, as a proportion of
13594     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13595     *
13596     * <p>By default, this is 1.0f.
13597     *
13598     * @see #getPivotX()
13599     * @see #getPivotY()
13600     * @return The scaling factor.
13601     */
13602    @ViewDebug.ExportedProperty(category = "drawing")
13603    public float getScaleX() {
13604        return mRenderNode.getScaleX();
13605    }
13606
13607    /**
13608     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13609     * the view's unscaled width. A value of 1 means that no scaling is applied.
13610     *
13611     * @param scaleX The scaling factor.
13612     * @see #getPivotX()
13613     * @see #getPivotY()
13614     *
13615     * @attr ref android.R.styleable#View_scaleX
13616     */
13617    public void setScaleX(float scaleX) {
13618        if (scaleX != getScaleX()) {
13619            invalidateViewProperty(true, false);
13620            mRenderNode.setScaleX(scaleX);
13621            invalidateViewProperty(false, true);
13622
13623            invalidateParentIfNeededAndWasQuickRejected();
13624            notifySubtreeAccessibilityStateChangedIfNeeded();
13625        }
13626    }
13627
13628    /**
13629     * The amount that the view is scaled in y around the pivot point, as a proportion of
13630     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13631     *
13632     * <p>By default, this is 1.0f.
13633     *
13634     * @see #getPivotX()
13635     * @see #getPivotY()
13636     * @return The scaling factor.
13637     */
13638    @ViewDebug.ExportedProperty(category = "drawing")
13639    public float getScaleY() {
13640        return mRenderNode.getScaleY();
13641    }
13642
13643    /**
13644     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13645     * the view's unscaled width. A value of 1 means that no scaling is applied.
13646     *
13647     * @param scaleY The scaling factor.
13648     * @see #getPivotX()
13649     * @see #getPivotY()
13650     *
13651     * @attr ref android.R.styleable#View_scaleY
13652     */
13653    public void setScaleY(float scaleY) {
13654        if (scaleY != getScaleY()) {
13655            invalidateViewProperty(true, false);
13656            mRenderNode.setScaleY(scaleY);
13657            invalidateViewProperty(false, true);
13658
13659            invalidateParentIfNeededAndWasQuickRejected();
13660            notifySubtreeAccessibilityStateChangedIfNeeded();
13661        }
13662    }
13663
13664    /**
13665     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13666     * and {@link #setScaleX(float) scaled}.
13667     *
13668     * @see #getRotation()
13669     * @see #getScaleX()
13670     * @see #getScaleY()
13671     * @see #getPivotY()
13672     * @return The x location of the pivot point.
13673     *
13674     * @attr ref android.R.styleable#View_transformPivotX
13675     */
13676    @ViewDebug.ExportedProperty(category = "drawing")
13677    public float getPivotX() {
13678        return mRenderNode.getPivotX();
13679    }
13680
13681    /**
13682     * Sets the x location of the point around which the view is
13683     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13684     * By default, the pivot point is centered on the object.
13685     * Setting this property disables this behavior and causes the view to use only the
13686     * explicitly set pivotX and pivotY values.
13687     *
13688     * @param pivotX The x location of the pivot point.
13689     * @see #getRotation()
13690     * @see #getScaleX()
13691     * @see #getScaleY()
13692     * @see #getPivotY()
13693     *
13694     * @attr ref android.R.styleable#View_transformPivotX
13695     */
13696    public void setPivotX(float pivotX) {
13697        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13698            invalidateViewProperty(true, false);
13699            mRenderNode.setPivotX(pivotX);
13700            invalidateViewProperty(false, true);
13701
13702            invalidateParentIfNeededAndWasQuickRejected();
13703        }
13704    }
13705
13706    /**
13707     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13708     * and {@link #setScaleY(float) scaled}.
13709     *
13710     * @see #getRotation()
13711     * @see #getScaleX()
13712     * @see #getScaleY()
13713     * @see #getPivotY()
13714     * @return The y location of the pivot point.
13715     *
13716     * @attr ref android.R.styleable#View_transformPivotY
13717     */
13718    @ViewDebug.ExportedProperty(category = "drawing")
13719    public float getPivotY() {
13720        return mRenderNode.getPivotY();
13721    }
13722
13723    /**
13724     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13725     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13726     * Setting this property disables this behavior and causes the view to use only the
13727     * explicitly set pivotX and pivotY values.
13728     *
13729     * @param pivotY The y location of the pivot point.
13730     * @see #getRotation()
13731     * @see #getScaleX()
13732     * @see #getScaleY()
13733     * @see #getPivotY()
13734     *
13735     * @attr ref android.R.styleable#View_transformPivotY
13736     */
13737    public void setPivotY(float pivotY) {
13738        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13739            invalidateViewProperty(true, false);
13740            mRenderNode.setPivotY(pivotY);
13741            invalidateViewProperty(false, true);
13742
13743            invalidateParentIfNeededAndWasQuickRejected();
13744        }
13745    }
13746
13747    /**
13748     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13749     * completely transparent and 1 means the view is completely opaque.
13750     *
13751     * <p>By default this is 1.0f.
13752     * @return The opacity of the view.
13753     */
13754    @ViewDebug.ExportedProperty(category = "drawing")
13755    public float getAlpha() {
13756        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13757    }
13758
13759    /**
13760     * Sets the behavior for overlapping rendering for this view (see {@link
13761     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13762     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13763     * providing the value which is then used internally. That is, when {@link
13764     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13765     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13766     * instead.
13767     *
13768     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13769     * instead of that returned by {@link #hasOverlappingRendering()}.
13770     *
13771     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13772     */
13773    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13774        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13775        if (hasOverlappingRendering) {
13776            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13777        } else {
13778            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13779        }
13780    }
13781
13782    /**
13783     * Returns the value for overlapping rendering that is used internally. This is either
13784     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13785     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13786     *
13787     * @return The value for overlapping rendering being used internally.
13788     */
13789    public final boolean getHasOverlappingRendering() {
13790        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13791                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13792                hasOverlappingRendering();
13793    }
13794
13795    /**
13796     * Returns whether this View has content which overlaps.
13797     *
13798     * <p>This function, intended to be overridden by specific View types, is an optimization when
13799     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13800     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13801     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13802     * directly. An example of overlapping rendering is a TextView with a background image, such as
13803     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13804     * ImageView with only the foreground image. The default implementation returns true; subclasses
13805     * should override if they have cases which can be optimized.</p>
13806     *
13807     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13808     * necessitates that a View return true if it uses the methods internally without passing the
13809     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13810     *
13811     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13812     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13813     *
13814     * @return true if the content in this view might overlap, false otherwise.
13815     */
13816    @ViewDebug.ExportedProperty(category = "drawing")
13817    public boolean hasOverlappingRendering() {
13818        return true;
13819    }
13820
13821    /**
13822     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13823     * completely transparent and 1 means the view is completely opaque.
13824     *
13825     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13826     * can have significant performance implications, especially for large views. It is best to use
13827     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13828     *
13829     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13830     * strongly recommended for performance reasons to either override
13831     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13832     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13833     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13834     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13835     * of rendering cost, even for simple or small views. Starting with
13836     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13837     * applied to the view at the rendering level.</p>
13838     *
13839     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13840     * responsible for applying the opacity itself.</p>
13841     *
13842     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13843     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13844     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13845     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13846     *
13847     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13848     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13849     * {@link #hasOverlappingRendering}.</p>
13850     *
13851     * @param alpha The opacity of the view.
13852     *
13853     * @see #hasOverlappingRendering()
13854     * @see #setLayerType(int, android.graphics.Paint)
13855     *
13856     * @attr ref android.R.styleable#View_alpha
13857     */
13858    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13859        ensureTransformationInfo();
13860        if (mTransformationInfo.mAlpha != alpha) {
13861            // Report visibility changes, which can affect children, to accessibility
13862            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13863                notifySubtreeAccessibilityStateChangedIfNeeded();
13864            }
13865            mTransformationInfo.mAlpha = alpha;
13866            if (onSetAlpha((int) (alpha * 255))) {
13867                mPrivateFlags |= PFLAG_ALPHA_SET;
13868                // subclass is handling alpha - don't optimize rendering cache invalidation
13869                invalidateParentCaches();
13870                invalidate(true);
13871            } else {
13872                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13873                invalidateViewProperty(true, false);
13874                mRenderNode.setAlpha(getFinalAlpha());
13875            }
13876        }
13877    }
13878
13879    /**
13880     * Faster version of setAlpha() which performs the same steps except there are
13881     * no calls to invalidate(). The caller of this function should perform proper invalidation
13882     * on the parent and this object. The return value indicates whether the subclass handles
13883     * alpha (the return value for onSetAlpha()).
13884     *
13885     * @param alpha The new value for the alpha property
13886     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13887     *         the new value for the alpha property is different from the old value
13888     */
13889    boolean setAlphaNoInvalidation(float alpha) {
13890        ensureTransformationInfo();
13891        if (mTransformationInfo.mAlpha != alpha) {
13892            mTransformationInfo.mAlpha = alpha;
13893            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13894            if (subclassHandlesAlpha) {
13895                mPrivateFlags |= PFLAG_ALPHA_SET;
13896                return true;
13897            } else {
13898                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13899                mRenderNode.setAlpha(getFinalAlpha());
13900            }
13901        }
13902        return false;
13903    }
13904
13905    /**
13906     * This property is hidden and intended only for use by the Fade transition, which
13907     * animates it to produce a visual translucency that does not side-effect (or get
13908     * affected by) the real alpha property. This value is composited with the other
13909     * alpha value (and the AlphaAnimation value, when that is present) to produce
13910     * a final visual translucency result, which is what is passed into the DisplayList.
13911     *
13912     * @hide
13913     */
13914    public void setTransitionAlpha(float alpha) {
13915        ensureTransformationInfo();
13916        if (mTransformationInfo.mTransitionAlpha != alpha) {
13917            mTransformationInfo.mTransitionAlpha = alpha;
13918            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13919            invalidateViewProperty(true, false);
13920            mRenderNode.setAlpha(getFinalAlpha());
13921        }
13922    }
13923
13924    /**
13925     * Calculates the visual alpha of this view, which is a combination of the actual
13926     * alpha value and the transitionAlpha value (if set).
13927     */
13928    private float getFinalAlpha() {
13929        if (mTransformationInfo != null) {
13930            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13931        }
13932        return 1;
13933    }
13934
13935    /**
13936     * This property is hidden and intended only for use by the Fade transition, which
13937     * animates it to produce a visual translucency that does not side-effect (or get
13938     * affected by) the real alpha property. This value is composited with the other
13939     * alpha value (and the AlphaAnimation value, when that is present) to produce
13940     * a final visual translucency result, which is what is passed into the DisplayList.
13941     *
13942     * @hide
13943     */
13944    @ViewDebug.ExportedProperty(category = "drawing")
13945    public float getTransitionAlpha() {
13946        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13947    }
13948
13949    /**
13950     * Top position of this view relative to its parent.
13951     *
13952     * @return The top of this view, in pixels.
13953     */
13954    @ViewDebug.CapturedViewProperty
13955    public final int getTop() {
13956        return mTop;
13957    }
13958
13959    /**
13960     * Sets the top position of this view relative to its parent. This method is meant to be called
13961     * by the layout system and should not generally be called otherwise, because the property
13962     * may be changed at any time by the layout.
13963     *
13964     * @param top The top of this view, in pixels.
13965     */
13966    public final void setTop(int top) {
13967        if (top != mTop) {
13968            final boolean matrixIsIdentity = hasIdentityMatrix();
13969            if (matrixIsIdentity) {
13970                if (mAttachInfo != null) {
13971                    int minTop;
13972                    int yLoc;
13973                    if (top < mTop) {
13974                        minTop = top;
13975                        yLoc = top - mTop;
13976                    } else {
13977                        minTop = mTop;
13978                        yLoc = 0;
13979                    }
13980                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13981                }
13982            } else {
13983                // Double-invalidation is necessary to capture view's old and new areas
13984                invalidate(true);
13985            }
13986
13987            int width = mRight - mLeft;
13988            int oldHeight = mBottom - mTop;
13989
13990            mTop = top;
13991            mRenderNode.setTop(mTop);
13992
13993            sizeChange(width, mBottom - mTop, width, oldHeight);
13994
13995            if (!matrixIsIdentity) {
13996                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13997                invalidate(true);
13998            }
13999            mBackgroundSizeChanged = true;
14000            mDefaultFocusHighlightSizeChanged = true;
14001            if (mForegroundInfo != null) {
14002                mForegroundInfo.mBoundsChanged = true;
14003            }
14004            invalidateParentIfNeeded();
14005            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14006                // View was rejected last time it was drawn by its parent; this may have changed
14007                invalidateParentIfNeeded();
14008            }
14009        }
14010    }
14011
14012    /**
14013     * Bottom position of this view relative to its parent.
14014     *
14015     * @return The bottom of this view, in pixels.
14016     */
14017    @ViewDebug.CapturedViewProperty
14018    public final int getBottom() {
14019        return mBottom;
14020    }
14021
14022    /**
14023     * True if this view has changed since the last time being drawn.
14024     *
14025     * @return The dirty state of this view.
14026     */
14027    public boolean isDirty() {
14028        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14029    }
14030
14031    /**
14032     * Sets the bottom position of this view relative to its parent. This method is meant to be
14033     * called by the layout system and should not generally be called otherwise, because the
14034     * property may be changed at any time by the layout.
14035     *
14036     * @param bottom The bottom of this view, in pixels.
14037     */
14038    public final void setBottom(int bottom) {
14039        if (bottom != mBottom) {
14040            final boolean matrixIsIdentity = hasIdentityMatrix();
14041            if (matrixIsIdentity) {
14042                if (mAttachInfo != null) {
14043                    int maxBottom;
14044                    if (bottom < mBottom) {
14045                        maxBottom = mBottom;
14046                    } else {
14047                        maxBottom = bottom;
14048                    }
14049                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14050                }
14051            } else {
14052                // Double-invalidation is necessary to capture view's old and new areas
14053                invalidate(true);
14054            }
14055
14056            int width = mRight - mLeft;
14057            int oldHeight = mBottom - mTop;
14058
14059            mBottom = bottom;
14060            mRenderNode.setBottom(mBottom);
14061
14062            sizeChange(width, mBottom - mTop, width, oldHeight);
14063
14064            if (!matrixIsIdentity) {
14065                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14066                invalidate(true);
14067            }
14068            mBackgroundSizeChanged = true;
14069            mDefaultFocusHighlightSizeChanged = true;
14070            if (mForegroundInfo != null) {
14071                mForegroundInfo.mBoundsChanged = true;
14072            }
14073            invalidateParentIfNeeded();
14074            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14075                // View was rejected last time it was drawn by its parent; this may have changed
14076                invalidateParentIfNeeded();
14077            }
14078        }
14079    }
14080
14081    /**
14082     * Left position of this view relative to its parent.
14083     *
14084     * @return The left edge of this view, in pixels.
14085     */
14086    @ViewDebug.CapturedViewProperty
14087    public final int getLeft() {
14088        return mLeft;
14089    }
14090
14091    /**
14092     * Sets the left position of this view relative to its parent. This method is meant to be called
14093     * by the layout system and should not generally be called otherwise, because the property
14094     * may be changed at any time by the layout.
14095     *
14096     * @param left The left of this view, in pixels.
14097     */
14098    public final void setLeft(int left) {
14099        if (left != mLeft) {
14100            final boolean matrixIsIdentity = hasIdentityMatrix();
14101            if (matrixIsIdentity) {
14102                if (mAttachInfo != null) {
14103                    int minLeft;
14104                    int xLoc;
14105                    if (left < mLeft) {
14106                        minLeft = left;
14107                        xLoc = left - mLeft;
14108                    } else {
14109                        minLeft = mLeft;
14110                        xLoc = 0;
14111                    }
14112                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14113                }
14114            } else {
14115                // Double-invalidation is necessary to capture view's old and new areas
14116                invalidate(true);
14117            }
14118
14119            int oldWidth = mRight - mLeft;
14120            int height = mBottom - mTop;
14121
14122            mLeft = left;
14123            mRenderNode.setLeft(left);
14124
14125            sizeChange(mRight - mLeft, height, oldWidth, height);
14126
14127            if (!matrixIsIdentity) {
14128                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14129                invalidate(true);
14130            }
14131            mBackgroundSizeChanged = true;
14132            mDefaultFocusHighlightSizeChanged = true;
14133            if (mForegroundInfo != null) {
14134                mForegroundInfo.mBoundsChanged = true;
14135            }
14136            invalidateParentIfNeeded();
14137            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14138                // View was rejected last time it was drawn by its parent; this may have changed
14139                invalidateParentIfNeeded();
14140            }
14141        }
14142    }
14143
14144    /**
14145     * Right position of this view relative to its parent.
14146     *
14147     * @return The right edge of this view, in pixels.
14148     */
14149    @ViewDebug.CapturedViewProperty
14150    public final int getRight() {
14151        return mRight;
14152    }
14153
14154    /**
14155     * Sets the right position of this view relative to its parent. This method is meant to be called
14156     * by the layout system and should not generally be called otherwise, because the property
14157     * may be changed at any time by the layout.
14158     *
14159     * @param right The right of this view, in pixels.
14160     */
14161    public final void setRight(int right) {
14162        if (right != mRight) {
14163            final boolean matrixIsIdentity = hasIdentityMatrix();
14164            if (matrixIsIdentity) {
14165                if (mAttachInfo != null) {
14166                    int maxRight;
14167                    if (right < mRight) {
14168                        maxRight = mRight;
14169                    } else {
14170                        maxRight = right;
14171                    }
14172                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14173                }
14174            } else {
14175                // Double-invalidation is necessary to capture view's old and new areas
14176                invalidate(true);
14177            }
14178
14179            int oldWidth = mRight - mLeft;
14180            int height = mBottom - mTop;
14181
14182            mRight = right;
14183            mRenderNode.setRight(mRight);
14184
14185            sizeChange(mRight - mLeft, height, oldWidth, height);
14186
14187            if (!matrixIsIdentity) {
14188                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14189                invalidate(true);
14190            }
14191            mBackgroundSizeChanged = true;
14192            mDefaultFocusHighlightSizeChanged = true;
14193            if (mForegroundInfo != null) {
14194                mForegroundInfo.mBoundsChanged = true;
14195            }
14196            invalidateParentIfNeeded();
14197            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14198                // View was rejected last time it was drawn by its parent; this may have changed
14199                invalidateParentIfNeeded();
14200            }
14201        }
14202    }
14203
14204    /**
14205     * The visual x position of this view, in pixels. This is equivalent to the
14206     * {@link #setTranslationX(float) translationX} property plus the current
14207     * {@link #getLeft() left} property.
14208     *
14209     * @return The visual x position of this view, in pixels.
14210     */
14211    @ViewDebug.ExportedProperty(category = "drawing")
14212    public float getX() {
14213        return mLeft + getTranslationX();
14214    }
14215
14216    /**
14217     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14218     * {@link #setTranslationX(float) translationX} property to be the difference between
14219     * the x value passed in and the current {@link #getLeft() left} property.
14220     *
14221     * @param x The visual x position of this view, in pixels.
14222     */
14223    public void setX(float x) {
14224        setTranslationX(x - mLeft);
14225    }
14226
14227    /**
14228     * The visual y position of this view, in pixels. This is equivalent to the
14229     * {@link #setTranslationY(float) translationY} property plus the current
14230     * {@link #getTop() top} property.
14231     *
14232     * @return The visual y position of this view, in pixels.
14233     */
14234    @ViewDebug.ExportedProperty(category = "drawing")
14235    public float getY() {
14236        return mTop + getTranslationY();
14237    }
14238
14239    /**
14240     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14241     * {@link #setTranslationY(float) translationY} property to be the difference between
14242     * the y value passed in and the current {@link #getTop() top} property.
14243     *
14244     * @param y The visual y position of this view, in pixels.
14245     */
14246    public void setY(float y) {
14247        setTranslationY(y - mTop);
14248    }
14249
14250    /**
14251     * The visual z position of this view, in pixels. This is equivalent to the
14252     * {@link #setTranslationZ(float) translationZ} property plus the current
14253     * {@link #getElevation() elevation} property.
14254     *
14255     * @return The visual z position of this view, in pixels.
14256     */
14257    @ViewDebug.ExportedProperty(category = "drawing")
14258    public float getZ() {
14259        return getElevation() + getTranslationZ();
14260    }
14261
14262    /**
14263     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14264     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14265     * the x value passed in and the current {@link #getElevation() elevation} property.
14266     *
14267     * @param z The visual z position of this view, in pixels.
14268     */
14269    public void setZ(float z) {
14270        setTranslationZ(z - getElevation());
14271    }
14272
14273    /**
14274     * The base elevation of this view relative to its parent, in pixels.
14275     *
14276     * @return The base depth position of the view, in pixels.
14277     */
14278    @ViewDebug.ExportedProperty(category = "drawing")
14279    public float getElevation() {
14280        return mRenderNode.getElevation();
14281    }
14282
14283    /**
14284     * Sets the base elevation of this view, in pixels.
14285     *
14286     * @attr ref android.R.styleable#View_elevation
14287     */
14288    public void setElevation(float elevation) {
14289        if (elevation != getElevation()) {
14290            invalidateViewProperty(true, false);
14291            mRenderNode.setElevation(elevation);
14292            invalidateViewProperty(false, true);
14293
14294            invalidateParentIfNeededAndWasQuickRejected();
14295        }
14296    }
14297
14298    /**
14299     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14300     * This position is post-layout, in addition to wherever the object's
14301     * layout placed it.
14302     *
14303     * @return The horizontal position of this view relative to its left position, in pixels.
14304     */
14305    @ViewDebug.ExportedProperty(category = "drawing")
14306    public float getTranslationX() {
14307        return mRenderNode.getTranslationX();
14308    }
14309
14310    /**
14311     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14312     * This effectively positions the object post-layout, in addition to wherever the object's
14313     * layout placed it.
14314     *
14315     * @param translationX The horizontal position of this view relative to its left position,
14316     * in pixels.
14317     *
14318     * @attr ref android.R.styleable#View_translationX
14319     */
14320    public void setTranslationX(float translationX) {
14321        if (translationX != getTranslationX()) {
14322            invalidateViewProperty(true, false);
14323            mRenderNode.setTranslationX(translationX);
14324            invalidateViewProperty(false, true);
14325
14326            invalidateParentIfNeededAndWasQuickRejected();
14327            notifySubtreeAccessibilityStateChangedIfNeeded();
14328        }
14329    }
14330
14331    /**
14332     * The vertical location of this view relative to its {@link #getTop() top} position.
14333     * This position is post-layout, in addition to wherever the object's
14334     * layout placed it.
14335     *
14336     * @return The vertical position of this view relative to its top position,
14337     * in pixels.
14338     */
14339    @ViewDebug.ExportedProperty(category = "drawing")
14340    public float getTranslationY() {
14341        return mRenderNode.getTranslationY();
14342    }
14343
14344    /**
14345     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14346     * This effectively positions the object post-layout, in addition to wherever the object's
14347     * layout placed it.
14348     *
14349     * @param translationY The vertical position of this view relative to its top position,
14350     * in pixels.
14351     *
14352     * @attr ref android.R.styleable#View_translationY
14353     */
14354    public void setTranslationY(float translationY) {
14355        if (translationY != getTranslationY()) {
14356            invalidateViewProperty(true, false);
14357            mRenderNode.setTranslationY(translationY);
14358            invalidateViewProperty(false, true);
14359
14360            invalidateParentIfNeededAndWasQuickRejected();
14361            notifySubtreeAccessibilityStateChangedIfNeeded();
14362        }
14363    }
14364
14365    /**
14366     * The depth location of this view relative to its {@link #getElevation() elevation}.
14367     *
14368     * @return The depth of this view relative to its elevation.
14369     */
14370    @ViewDebug.ExportedProperty(category = "drawing")
14371    public float getTranslationZ() {
14372        return mRenderNode.getTranslationZ();
14373    }
14374
14375    /**
14376     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14377     *
14378     * @attr ref android.R.styleable#View_translationZ
14379     */
14380    public void setTranslationZ(float translationZ) {
14381        if (translationZ != getTranslationZ()) {
14382            invalidateViewProperty(true, false);
14383            mRenderNode.setTranslationZ(translationZ);
14384            invalidateViewProperty(false, true);
14385
14386            invalidateParentIfNeededAndWasQuickRejected();
14387        }
14388    }
14389
14390    /** @hide */
14391    public void setAnimationMatrix(Matrix matrix) {
14392        invalidateViewProperty(true, false);
14393        mRenderNode.setAnimationMatrix(matrix);
14394        invalidateViewProperty(false, true);
14395
14396        invalidateParentIfNeededAndWasQuickRejected();
14397    }
14398
14399    /**
14400     * Returns the current StateListAnimator if exists.
14401     *
14402     * @return StateListAnimator or null if it does not exists
14403     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14404     */
14405    public StateListAnimator getStateListAnimator() {
14406        return mStateListAnimator;
14407    }
14408
14409    /**
14410     * Attaches the provided StateListAnimator to this View.
14411     * <p>
14412     * Any previously attached StateListAnimator will be detached.
14413     *
14414     * @param stateListAnimator The StateListAnimator to update the view
14415     * @see android.animation.StateListAnimator
14416     */
14417    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14418        if (mStateListAnimator == stateListAnimator) {
14419            return;
14420        }
14421        if (mStateListAnimator != null) {
14422            mStateListAnimator.setTarget(null);
14423        }
14424        mStateListAnimator = stateListAnimator;
14425        if (stateListAnimator != null) {
14426            stateListAnimator.setTarget(this);
14427            if (isAttachedToWindow()) {
14428                stateListAnimator.setState(getDrawableState());
14429            }
14430        }
14431    }
14432
14433    /**
14434     * Returns whether the Outline should be used to clip the contents of the View.
14435     * <p>
14436     * Note that this flag will only be respected if the View's Outline returns true from
14437     * {@link Outline#canClip()}.
14438     *
14439     * @see #setOutlineProvider(ViewOutlineProvider)
14440     * @see #setClipToOutline(boolean)
14441     */
14442    public final boolean getClipToOutline() {
14443        return mRenderNode.getClipToOutline();
14444    }
14445
14446    /**
14447     * Sets whether the View's Outline should be used to clip the contents of the View.
14448     * <p>
14449     * Only a single non-rectangular clip can be applied on a View at any time.
14450     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14451     * circular reveal} animation take priority over Outline clipping, and
14452     * child Outline clipping takes priority over Outline clipping done by a
14453     * parent.
14454     * <p>
14455     * Note that this flag will only be respected if the View's Outline returns true from
14456     * {@link Outline#canClip()}.
14457     *
14458     * @see #setOutlineProvider(ViewOutlineProvider)
14459     * @see #getClipToOutline()
14460     */
14461    public void setClipToOutline(boolean clipToOutline) {
14462        damageInParent();
14463        if (getClipToOutline() != clipToOutline) {
14464            mRenderNode.setClipToOutline(clipToOutline);
14465        }
14466    }
14467
14468    // correspond to the enum values of View_outlineProvider
14469    private static final int PROVIDER_BACKGROUND = 0;
14470    private static final int PROVIDER_NONE = 1;
14471    private static final int PROVIDER_BOUNDS = 2;
14472    private static final int PROVIDER_PADDED_BOUNDS = 3;
14473    private void setOutlineProviderFromAttribute(int providerInt) {
14474        switch (providerInt) {
14475            case PROVIDER_BACKGROUND:
14476                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14477                break;
14478            case PROVIDER_NONE:
14479                setOutlineProvider(null);
14480                break;
14481            case PROVIDER_BOUNDS:
14482                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14483                break;
14484            case PROVIDER_PADDED_BOUNDS:
14485                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14486                break;
14487        }
14488    }
14489
14490    /**
14491     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14492     * the shape of the shadow it casts, and enables outline clipping.
14493     * <p>
14494     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14495     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14496     * outline provider with this method allows this behavior to be overridden.
14497     * <p>
14498     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14499     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14500     * <p>
14501     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14502     *
14503     * @see #setClipToOutline(boolean)
14504     * @see #getClipToOutline()
14505     * @see #getOutlineProvider()
14506     */
14507    public void setOutlineProvider(ViewOutlineProvider provider) {
14508        mOutlineProvider = provider;
14509        invalidateOutline();
14510    }
14511
14512    /**
14513     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14514     * that defines the shape of the shadow it casts, and enables outline clipping.
14515     *
14516     * @see #setOutlineProvider(ViewOutlineProvider)
14517     */
14518    public ViewOutlineProvider getOutlineProvider() {
14519        return mOutlineProvider;
14520    }
14521
14522    /**
14523     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14524     *
14525     * @see #setOutlineProvider(ViewOutlineProvider)
14526     */
14527    public void invalidateOutline() {
14528        rebuildOutline();
14529
14530        notifySubtreeAccessibilityStateChangedIfNeeded();
14531        invalidateViewProperty(false, false);
14532    }
14533
14534    /**
14535     * Internal version of {@link #invalidateOutline()} which invalidates the
14536     * outline without invalidating the view itself. This is intended to be called from
14537     * within methods in the View class itself which are the result of the view being
14538     * invalidated already. For example, when we are drawing the background of a View,
14539     * we invalidate the outline in case it changed in the meantime, but we do not
14540     * need to invalidate the view because we're already drawing the background as part
14541     * of drawing the view in response to an earlier invalidation of the view.
14542     */
14543    private void rebuildOutline() {
14544        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14545        if (mAttachInfo == null) return;
14546
14547        if (mOutlineProvider == null) {
14548            // no provider, remove outline
14549            mRenderNode.setOutline(null);
14550        } else {
14551            final Outline outline = mAttachInfo.mTmpOutline;
14552            outline.setEmpty();
14553            outline.setAlpha(1.0f);
14554
14555            mOutlineProvider.getOutline(this, outline);
14556            mRenderNode.setOutline(outline);
14557        }
14558    }
14559
14560    /**
14561     * HierarchyViewer only
14562     *
14563     * @hide
14564     */
14565    @ViewDebug.ExportedProperty(category = "drawing")
14566    public boolean hasShadow() {
14567        return mRenderNode.hasShadow();
14568    }
14569
14570
14571    /** @hide */
14572    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14573        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14574        invalidateViewProperty(false, false);
14575    }
14576
14577    /**
14578     * Hit rectangle in parent's coordinates
14579     *
14580     * @param outRect The hit rectangle of the view.
14581     */
14582    public void getHitRect(Rect outRect) {
14583        if (hasIdentityMatrix() || mAttachInfo == null) {
14584            outRect.set(mLeft, mTop, mRight, mBottom);
14585        } else {
14586            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14587            tmpRect.set(0, 0, getWidth(), getHeight());
14588            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14589            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14590                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14591        }
14592    }
14593
14594    /**
14595     * Determines whether the given point, in local coordinates is inside the view.
14596     */
14597    /*package*/ final boolean pointInView(float localX, float localY) {
14598        return pointInView(localX, localY, 0);
14599    }
14600
14601    /**
14602     * Utility method to determine whether the given point, in local coordinates,
14603     * is inside the view, where the area of the view is expanded by the slop factor.
14604     * This method is called while processing touch-move events to determine if the event
14605     * is still within the view.
14606     *
14607     * @hide
14608     */
14609    public boolean pointInView(float localX, float localY, float slop) {
14610        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14611                localY < ((mBottom - mTop) + slop);
14612    }
14613
14614    /**
14615     * When a view has focus and the user navigates away from it, the next view is searched for
14616     * starting from the rectangle filled in by this method.
14617     *
14618     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14619     * of the view.  However, if your view maintains some idea of internal selection,
14620     * such as a cursor, or a selected row or column, you should override this method and
14621     * fill in a more specific rectangle.
14622     *
14623     * @param r The rectangle to fill in, in this view's coordinates.
14624     */
14625    public void getFocusedRect(Rect r) {
14626        getDrawingRect(r);
14627    }
14628
14629    /**
14630     * If some part of this view is not clipped by any of its parents, then
14631     * return that area in r in global (root) coordinates. To convert r to local
14632     * coordinates (without taking possible View rotations into account), offset
14633     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14634     * If the view is completely clipped or translated out, return false.
14635     *
14636     * @param r If true is returned, r holds the global coordinates of the
14637     *        visible portion of this view.
14638     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14639     *        between this view and its root. globalOffet may be null.
14640     * @return true if r is non-empty (i.e. part of the view is visible at the
14641     *         root level.
14642     */
14643    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14644        int width = mRight - mLeft;
14645        int height = mBottom - mTop;
14646        if (width > 0 && height > 0) {
14647            r.set(0, 0, width, height);
14648            if (globalOffset != null) {
14649                globalOffset.set(-mScrollX, -mScrollY);
14650            }
14651            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14652        }
14653        return false;
14654    }
14655
14656    public final boolean getGlobalVisibleRect(Rect r) {
14657        return getGlobalVisibleRect(r, null);
14658    }
14659
14660    public final boolean getLocalVisibleRect(Rect r) {
14661        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14662        if (getGlobalVisibleRect(r, offset)) {
14663            r.offset(-offset.x, -offset.y); // make r local
14664            return true;
14665        }
14666        return false;
14667    }
14668
14669    /**
14670     * Offset this view's vertical location by the specified number of pixels.
14671     *
14672     * @param offset the number of pixels to offset the view by
14673     */
14674    public void offsetTopAndBottom(int offset) {
14675        if (offset != 0) {
14676            final boolean matrixIsIdentity = hasIdentityMatrix();
14677            if (matrixIsIdentity) {
14678                if (isHardwareAccelerated()) {
14679                    invalidateViewProperty(false, false);
14680                } else {
14681                    final ViewParent p = mParent;
14682                    if (p != null && mAttachInfo != null) {
14683                        final Rect r = mAttachInfo.mTmpInvalRect;
14684                        int minTop;
14685                        int maxBottom;
14686                        int yLoc;
14687                        if (offset < 0) {
14688                            minTop = mTop + offset;
14689                            maxBottom = mBottom;
14690                            yLoc = offset;
14691                        } else {
14692                            minTop = mTop;
14693                            maxBottom = mBottom + offset;
14694                            yLoc = 0;
14695                        }
14696                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14697                        p.invalidateChild(this, r);
14698                    }
14699                }
14700            } else {
14701                invalidateViewProperty(false, false);
14702            }
14703
14704            mTop += offset;
14705            mBottom += offset;
14706            mRenderNode.offsetTopAndBottom(offset);
14707            if (isHardwareAccelerated()) {
14708                invalidateViewProperty(false, false);
14709                invalidateParentIfNeededAndWasQuickRejected();
14710            } else {
14711                if (!matrixIsIdentity) {
14712                    invalidateViewProperty(false, true);
14713                }
14714                invalidateParentIfNeeded();
14715            }
14716            notifySubtreeAccessibilityStateChangedIfNeeded();
14717        }
14718    }
14719
14720    /**
14721     * Offset this view's horizontal location by the specified amount of pixels.
14722     *
14723     * @param offset the number of pixels to offset the view by
14724     */
14725    public void offsetLeftAndRight(int offset) {
14726        if (offset != 0) {
14727            final boolean matrixIsIdentity = hasIdentityMatrix();
14728            if (matrixIsIdentity) {
14729                if (isHardwareAccelerated()) {
14730                    invalidateViewProperty(false, false);
14731                } else {
14732                    final ViewParent p = mParent;
14733                    if (p != null && mAttachInfo != null) {
14734                        final Rect r = mAttachInfo.mTmpInvalRect;
14735                        int minLeft;
14736                        int maxRight;
14737                        if (offset < 0) {
14738                            minLeft = mLeft + offset;
14739                            maxRight = mRight;
14740                        } else {
14741                            minLeft = mLeft;
14742                            maxRight = mRight + offset;
14743                        }
14744                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14745                        p.invalidateChild(this, r);
14746                    }
14747                }
14748            } else {
14749                invalidateViewProperty(false, false);
14750            }
14751
14752            mLeft += offset;
14753            mRight += offset;
14754            mRenderNode.offsetLeftAndRight(offset);
14755            if (isHardwareAccelerated()) {
14756                invalidateViewProperty(false, false);
14757                invalidateParentIfNeededAndWasQuickRejected();
14758            } else {
14759                if (!matrixIsIdentity) {
14760                    invalidateViewProperty(false, true);
14761                }
14762                invalidateParentIfNeeded();
14763            }
14764            notifySubtreeAccessibilityStateChangedIfNeeded();
14765        }
14766    }
14767
14768    /**
14769     * Get the LayoutParams associated with this view. All views should have
14770     * layout parameters. These supply parameters to the <i>parent</i> of this
14771     * view specifying how it should be arranged. There are many subclasses of
14772     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14773     * of ViewGroup that are responsible for arranging their children.
14774     *
14775     * This method may return null if this View is not attached to a parent
14776     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14777     * was not invoked successfully. When a View is attached to a parent
14778     * ViewGroup, this method must not return null.
14779     *
14780     * @return The LayoutParams associated with this view, or null if no
14781     *         parameters have been set yet
14782     */
14783    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14784    public ViewGroup.LayoutParams getLayoutParams() {
14785        return mLayoutParams;
14786    }
14787
14788    /**
14789     * Set the layout parameters associated with this view. These supply
14790     * parameters to the <i>parent</i> of this view specifying how it should be
14791     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14792     * correspond to the different subclasses of ViewGroup that are responsible
14793     * for arranging their children.
14794     *
14795     * @param params The layout parameters for this view, cannot be null
14796     */
14797    public void setLayoutParams(ViewGroup.LayoutParams params) {
14798        if (params == null) {
14799            throw new NullPointerException("Layout parameters cannot be null");
14800        }
14801        mLayoutParams = params;
14802        resolveLayoutParams();
14803        if (mParent instanceof ViewGroup) {
14804            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14805        }
14806        requestLayout();
14807    }
14808
14809    /**
14810     * Resolve the layout parameters depending on the resolved layout direction
14811     *
14812     * @hide
14813     */
14814    public void resolveLayoutParams() {
14815        if (mLayoutParams != null) {
14816            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14817        }
14818    }
14819
14820    /**
14821     * Set the scrolled position of your view. This will cause a call to
14822     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14823     * invalidated.
14824     * @param x the x position to scroll to
14825     * @param y the y position to scroll to
14826     */
14827    public void scrollTo(int x, int y) {
14828        if (mScrollX != x || mScrollY != y) {
14829            int oldX = mScrollX;
14830            int oldY = mScrollY;
14831            mScrollX = x;
14832            mScrollY = y;
14833            invalidateParentCaches();
14834            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14835            if (!awakenScrollBars()) {
14836                postInvalidateOnAnimation();
14837            }
14838        }
14839    }
14840
14841    /**
14842     * Move the scrolled position of your view. This will cause a call to
14843     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14844     * invalidated.
14845     * @param x the amount of pixels to scroll by horizontally
14846     * @param y the amount of pixels to scroll by vertically
14847     */
14848    public void scrollBy(int x, int y) {
14849        scrollTo(mScrollX + x, mScrollY + y);
14850    }
14851
14852    /**
14853     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14854     * animation to fade the scrollbars out after a default delay. If a subclass
14855     * provides animated scrolling, the start delay should equal the duration
14856     * of the scrolling animation.</p>
14857     *
14858     * <p>The animation starts only if at least one of the scrollbars is
14859     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14860     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14861     * this method returns true, and false otherwise. If the animation is
14862     * started, this method calls {@link #invalidate()}; in that case the
14863     * caller should not call {@link #invalidate()}.</p>
14864     *
14865     * <p>This method should be invoked every time a subclass directly updates
14866     * the scroll parameters.</p>
14867     *
14868     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14869     * and {@link #scrollTo(int, int)}.</p>
14870     *
14871     * @return true if the animation is played, false otherwise
14872     *
14873     * @see #awakenScrollBars(int)
14874     * @see #scrollBy(int, int)
14875     * @see #scrollTo(int, int)
14876     * @see #isHorizontalScrollBarEnabled()
14877     * @see #isVerticalScrollBarEnabled()
14878     * @see #setHorizontalScrollBarEnabled(boolean)
14879     * @see #setVerticalScrollBarEnabled(boolean)
14880     */
14881    protected boolean awakenScrollBars() {
14882        return mScrollCache != null &&
14883                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14884    }
14885
14886    /**
14887     * Trigger the scrollbars to draw.
14888     * This method differs from awakenScrollBars() only in its default duration.
14889     * initialAwakenScrollBars() will show the scroll bars for longer than
14890     * usual to give the user more of a chance to notice them.
14891     *
14892     * @return true if the animation is played, false otherwise.
14893     */
14894    private boolean initialAwakenScrollBars() {
14895        return mScrollCache != null &&
14896                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14897    }
14898
14899    /**
14900     * <p>
14901     * Trigger the scrollbars to draw. When invoked this method starts an
14902     * animation to fade the scrollbars out after a fixed delay. If a subclass
14903     * provides animated scrolling, the start delay should equal the duration of
14904     * the scrolling animation.
14905     * </p>
14906     *
14907     * <p>
14908     * The animation starts only if at least one of the scrollbars is enabled,
14909     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14910     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14911     * this method returns true, and false otherwise. If the animation is
14912     * started, this method calls {@link #invalidate()}; in that case the caller
14913     * should not call {@link #invalidate()}.
14914     * </p>
14915     *
14916     * <p>
14917     * This method should be invoked every time a subclass directly updates the
14918     * scroll parameters.
14919     * </p>
14920     *
14921     * @param startDelay the delay, in milliseconds, after which the animation
14922     *        should start; when the delay is 0, the animation starts
14923     *        immediately
14924     * @return true if the animation is played, false otherwise
14925     *
14926     * @see #scrollBy(int, int)
14927     * @see #scrollTo(int, int)
14928     * @see #isHorizontalScrollBarEnabled()
14929     * @see #isVerticalScrollBarEnabled()
14930     * @see #setHorizontalScrollBarEnabled(boolean)
14931     * @see #setVerticalScrollBarEnabled(boolean)
14932     */
14933    protected boolean awakenScrollBars(int startDelay) {
14934        return awakenScrollBars(startDelay, true);
14935    }
14936
14937    /**
14938     * <p>
14939     * Trigger the scrollbars to draw. When invoked this method starts an
14940     * animation to fade the scrollbars out after a fixed delay. If a subclass
14941     * provides animated scrolling, the start delay should equal the duration of
14942     * the scrolling animation.
14943     * </p>
14944     *
14945     * <p>
14946     * The animation starts only if at least one of the scrollbars is enabled,
14947     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14948     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14949     * this method returns true, and false otherwise. If the animation is
14950     * started, this method calls {@link #invalidate()} if the invalidate parameter
14951     * is set to true; in that case the caller
14952     * should not call {@link #invalidate()}.
14953     * </p>
14954     *
14955     * <p>
14956     * This method should be invoked every time a subclass directly updates the
14957     * scroll parameters.
14958     * </p>
14959     *
14960     * @param startDelay the delay, in milliseconds, after which the animation
14961     *        should start; when the delay is 0, the animation starts
14962     *        immediately
14963     *
14964     * @param invalidate Whether this method should call invalidate
14965     *
14966     * @return true if the animation is played, false otherwise
14967     *
14968     * @see #scrollBy(int, int)
14969     * @see #scrollTo(int, int)
14970     * @see #isHorizontalScrollBarEnabled()
14971     * @see #isVerticalScrollBarEnabled()
14972     * @see #setHorizontalScrollBarEnabled(boolean)
14973     * @see #setVerticalScrollBarEnabled(boolean)
14974     */
14975    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14976        final ScrollabilityCache scrollCache = mScrollCache;
14977
14978        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14979            return false;
14980        }
14981
14982        if (scrollCache.scrollBar == null) {
14983            scrollCache.scrollBar = new ScrollBarDrawable();
14984            scrollCache.scrollBar.setState(getDrawableState());
14985            scrollCache.scrollBar.setCallback(this);
14986        }
14987
14988        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14989
14990            if (invalidate) {
14991                // Invalidate to show the scrollbars
14992                postInvalidateOnAnimation();
14993            }
14994
14995            if (scrollCache.state == ScrollabilityCache.OFF) {
14996                // FIXME: this is copied from WindowManagerService.
14997                // We should get this value from the system when it
14998                // is possible to do so.
14999                final int KEY_REPEAT_FIRST_DELAY = 750;
15000                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15001            }
15002
15003            // Tell mScrollCache when we should start fading. This may
15004            // extend the fade start time if one was already scheduled
15005            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15006            scrollCache.fadeStartTime = fadeStartTime;
15007            scrollCache.state = ScrollabilityCache.ON;
15008
15009            // Schedule our fader to run, unscheduling any old ones first
15010            if (mAttachInfo != null) {
15011                mAttachInfo.mHandler.removeCallbacks(scrollCache);
15012                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15013            }
15014
15015            return true;
15016        }
15017
15018        return false;
15019    }
15020
15021    /**
15022     * Do not invalidate views which are not visible and which are not running an animation. They
15023     * will not get drawn and they should not set dirty flags as if they will be drawn
15024     */
15025    private boolean skipInvalidate() {
15026        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15027                (!(mParent instanceof ViewGroup) ||
15028                        !((ViewGroup) mParent).isViewTransitioning(this));
15029    }
15030
15031    /**
15032     * Mark the area defined by dirty as needing to be drawn. If the view is
15033     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15034     * point in the future.
15035     * <p>
15036     * This must be called from a UI thread. To call from a non-UI thread, call
15037     * {@link #postInvalidate()}.
15038     * <p>
15039     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15040     * {@code dirty}.
15041     *
15042     * @param dirty the rectangle representing the bounds of the dirty region
15043     */
15044    public void invalidate(Rect dirty) {
15045        final int scrollX = mScrollX;
15046        final int scrollY = mScrollY;
15047        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15048                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15049    }
15050
15051    /**
15052     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15053     * coordinates of the dirty rect are relative to the view. If the view is
15054     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15055     * point in the future.
15056     * <p>
15057     * This must be called from a UI thread. To call from a non-UI thread, call
15058     * {@link #postInvalidate()}.
15059     *
15060     * @param l the left position of the dirty region
15061     * @param t the top position of the dirty region
15062     * @param r the right position of the dirty region
15063     * @param b the bottom position of the dirty region
15064     */
15065    public void invalidate(int l, int t, int r, int b) {
15066        final int scrollX = mScrollX;
15067        final int scrollY = mScrollY;
15068        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15069    }
15070
15071    /**
15072     * Invalidate the whole view. If the view is visible,
15073     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15074     * the future.
15075     * <p>
15076     * This must be called from a UI thread. To call from a non-UI thread, call
15077     * {@link #postInvalidate()}.
15078     */
15079    public void invalidate() {
15080        invalidate(true);
15081    }
15082
15083    /**
15084     * This is where the invalidate() work actually happens. A full invalidate()
15085     * causes the drawing cache to be invalidated, but this function can be
15086     * called with invalidateCache set to false to skip that invalidation step
15087     * for cases that do not need it (for example, a component that remains at
15088     * the same dimensions with the same content).
15089     *
15090     * @param invalidateCache Whether the drawing cache for this view should be
15091     *            invalidated as well. This is usually true for a full
15092     *            invalidate, but may be set to false if the View's contents or
15093     *            dimensions have not changed.
15094     * @hide
15095     */
15096    public void invalidate(boolean invalidateCache) {
15097        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15098    }
15099
15100    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15101            boolean fullInvalidate) {
15102        if (mGhostView != null) {
15103            mGhostView.invalidate(true);
15104            return;
15105        }
15106
15107        if (skipInvalidate()) {
15108            return;
15109        }
15110
15111        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15112                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15113                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15114                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15115            if (fullInvalidate) {
15116                mLastIsOpaque = isOpaque();
15117                mPrivateFlags &= ~PFLAG_DRAWN;
15118            }
15119
15120            mPrivateFlags |= PFLAG_DIRTY;
15121
15122            if (invalidateCache) {
15123                mPrivateFlags |= PFLAG_INVALIDATED;
15124                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15125            }
15126
15127            // Propagate the damage rectangle to the parent view.
15128            final AttachInfo ai = mAttachInfo;
15129            final ViewParent p = mParent;
15130            if (p != null && ai != null && l < r && t < b) {
15131                final Rect damage = ai.mTmpInvalRect;
15132                damage.set(l, t, r, b);
15133                p.invalidateChild(this, damage);
15134            }
15135
15136            // Damage the entire projection receiver, if necessary.
15137            if (mBackground != null && mBackground.isProjected()) {
15138                final View receiver = getProjectionReceiver();
15139                if (receiver != null) {
15140                    receiver.damageInParent();
15141                }
15142            }
15143        }
15144    }
15145
15146    /**
15147     * @return this view's projection receiver, or {@code null} if none exists
15148     */
15149    private View getProjectionReceiver() {
15150        ViewParent p = getParent();
15151        while (p != null && p instanceof View) {
15152            final View v = (View) p;
15153            if (v.isProjectionReceiver()) {
15154                return v;
15155            }
15156            p = p.getParent();
15157        }
15158
15159        return null;
15160    }
15161
15162    /**
15163     * @return whether the view is a projection receiver
15164     */
15165    private boolean isProjectionReceiver() {
15166        return mBackground != null;
15167    }
15168
15169    /**
15170     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15171     * set any flags or handle all of the cases handled by the default invalidation methods.
15172     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15173     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15174     * walk up the hierarchy, transforming the dirty rect as necessary.
15175     *
15176     * The method also handles normal invalidation logic if display list properties are not
15177     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15178     * backup approach, to handle these cases used in the various property-setting methods.
15179     *
15180     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15181     * are not being used in this view
15182     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15183     * list properties are not being used in this view
15184     */
15185    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15186        if (!isHardwareAccelerated()
15187                || !mRenderNode.isValid()
15188                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15189            if (invalidateParent) {
15190                invalidateParentCaches();
15191            }
15192            if (forceRedraw) {
15193                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15194            }
15195            invalidate(false);
15196        } else {
15197            damageInParent();
15198        }
15199    }
15200
15201    /**
15202     * Tells the parent view to damage this view's bounds.
15203     *
15204     * @hide
15205     */
15206    protected void damageInParent() {
15207        if (mParent != null && mAttachInfo != null) {
15208            mParent.onDescendantInvalidated(this, this);
15209        }
15210    }
15211
15212    /**
15213     * Utility method to transform a given Rect by the current matrix of this view.
15214     */
15215    void transformRect(final Rect rect) {
15216        if (!getMatrix().isIdentity()) {
15217            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15218            boundingRect.set(rect);
15219            getMatrix().mapRect(boundingRect);
15220            rect.set((int) Math.floor(boundingRect.left),
15221                    (int) Math.floor(boundingRect.top),
15222                    (int) Math.ceil(boundingRect.right),
15223                    (int) Math.ceil(boundingRect.bottom));
15224        }
15225    }
15226
15227    /**
15228     * Used to indicate that the parent of this view should clear its caches. This functionality
15229     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15230     * which is necessary when various parent-managed properties of the view change, such as
15231     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15232     * clears the parent caches and does not causes an invalidate event.
15233     *
15234     * @hide
15235     */
15236    protected void invalidateParentCaches() {
15237        if (mParent instanceof View) {
15238            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15239        }
15240    }
15241
15242    /**
15243     * Used to indicate that the parent of this view should be invalidated. This functionality
15244     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15245     * which is necessary when various parent-managed properties of the view change, such as
15246     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15247     * an invalidation event to the parent.
15248     *
15249     * @hide
15250     */
15251    protected void invalidateParentIfNeeded() {
15252        if (isHardwareAccelerated() && mParent instanceof View) {
15253            ((View) mParent).invalidate(true);
15254        }
15255    }
15256
15257    /**
15258     * @hide
15259     */
15260    protected void invalidateParentIfNeededAndWasQuickRejected() {
15261        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15262            // View was rejected last time it was drawn by its parent; this may have changed
15263            invalidateParentIfNeeded();
15264        }
15265    }
15266
15267    /**
15268     * Indicates whether this View is opaque. An opaque View guarantees that it will
15269     * draw all the pixels overlapping its bounds using a fully opaque color.
15270     *
15271     * Subclasses of View should override this method whenever possible to indicate
15272     * whether an instance is opaque. Opaque Views are treated in a special way by
15273     * the View hierarchy, possibly allowing it to perform optimizations during
15274     * invalidate/draw passes.
15275     *
15276     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15277     */
15278    @ViewDebug.ExportedProperty(category = "drawing")
15279    public boolean isOpaque() {
15280        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15281                getFinalAlpha() >= 1.0f;
15282    }
15283
15284    /**
15285     * @hide
15286     */
15287    protected void computeOpaqueFlags() {
15288        // Opaque if:
15289        //   - Has a background
15290        //   - Background is opaque
15291        //   - Doesn't have scrollbars or scrollbars overlay
15292
15293        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15294            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15295        } else {
15296            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15297        }
15298
15299        final int flags = mViewFlags;
15300        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15301                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15302                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15303            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15304        } else {
15305            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15306        }
15307    }
15308
15309    /**
15310     * @hide
15311     */
15312    protected boolean hasOpaqueScrollbars() {
15313        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15314    }
15315
15316    /**
15317     * @return A handler associated with the thread running the View. This
15318     * handler can be used to pump events in the UI events queue.
15319     */
15320    public Handler getHandler() {
15321        final AttachInfo attachInfo = mAttachInfo;
15322        if (attachInfo != null) {
15323            return attachInfo.mHandler;
15324        }
15325        return null;
15326    }
15327
15328    /**
15329     * Returns the queue of runnable for this view.
15330     *
15331     * @return the queue of runnables for this view
15332     */
15333    private HandlerActionQueue getRunQueue() {
15334        if (mRunQueue == null) {
15335            mRunQueue = new HandlerActionQueue();
15336        }
15337        return mRunQueue;
15338    }
15339
15340    /**
15341     * Gets the view root associated with the View.
15342     * @return The view root, or null if none.
15343     * @hide
15344     */
15345    public ViewRootImpl getViewRootImpl() {
15346        if (mAttachInfo != null) {
15347            return mAttachInfo.mViewRootImpl;
15348        }
15349        return null;
15350    }
15351
15352    /**
15353     * @hide
15354     */
15355    public ThreadedRenderer getThreadedRenderer() {
15356        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15357    }
15358
15359    /**
15360     * <p>Causes the Runnable to be added to the message queue.
15361     * The runnable will be run on the user interface thread.</p>
15362     *
15363     * @param action The Runnable that will be executed.
15364     *
15365     * @return Returns true if the Runnable was successfully placed in to the
15366     *         message queue.  Returns false on failure, usually because the
15367     *         looper processing the message queue is exiting.
15368     *
15369     * @see #postDelayed
15370     * @see #removeCallbacks
15371     */
15372    public boolean post(Runnable action) {
15373        final AttachInfo attachInfo = mAttachInfo;
15374        if (attachInfo != null) {
15375            return attachInfo.mHandler.post(action);
15376        }
15377
15378        // Postpone the runnable until we know on which thread it needs to run.
15379        // Assume that the runnable will be successfully placed after attach.
15380        getRunQueue().post(action);
15381        return true;
15382    }
15383
15384    /**
15385     * <p>Causes the Runnable to be added to the message queue, to be run
15386     * after the specified amount of time elapses.
15387     * The runnable will be run on the user interface thread.</p>
15388     *
15389     * @param action The Runnable that will be executed.
15390     * @param delayMillis The delay (in milliseconds) until the Runnable
15391     *        will be executed.
15392     *
15393     * @return true if the Runnable was successfully placed in to the
15394     *         message queue.  Returns false on failure, usually because the
15395     *         looper processing the message queue is exiting.  Note that a
15396     *         result of true does not mean the Runnable will be processed --
15397     *         if the looper is quit before the delivery time of the message
15398     *         occurs then the message will be dropped.
15399     *
15400     * @see #post
15401     * @see #removeCallbacks
15402     */
15403    public boolean postDelayed(Runnable action, long delayMillis) {
15404        final AttachInfo attachInfo = mAttachInfo;
15405        if (attachInfo != null) {
15406            return attachInfo.mHandler.postDelayed(action, delayMillis);
15407        }
15408
15409        // Postpone the runnable until we know on which thread it needs to run.
15410        // Assume that the runnable will be successfully placed after attach.
15411        getRunQueue().postDelayed(action, delayMillis);
15412        return true;
15413    }
15414
15415    /**
15416     * <p>Causes the Runnable to execute on the next animation time step.
15417     * The runnable will be run on the user interface thread.</p>
15418     *
15419     * @param action The Runnable that will be executed.
15420     *
15421     * @see #postOnAnimationDelayed
15422     * @see #removeCallbacks
15423     */
15424    public void postOnAnimation(Runnable action) {
15425        final AttachInfo attachInfo = mAttachInfo;
15426        if (attachInfo != null) {
15427            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15428                    Choreographer.CALLBACK_ANIMATION, action, null);
15429        } else {
15430            // Postpone the runnable until we know
15431            // on which thread it needs to run.
15432            getRunQueue().post(action);
15433        }
15434    }
15435
15436    /**
15437     * <p>Causes the Runnable to execute on the next animation time step,
15438     * after the specified amount of time elapses.
15439     * The runnable will be run on the user interface thread.</p>
15440     *
15441     * @param action The Runnable that will be executed.
15442     * @param delayMillis The delay (in milliseconds) until the Runnable
15443     *        will be executed.
15444     *
15445     * @see #postOnAnimation
15446     * @see #removeCallbacks
15447     */
15448    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15449        final AttachInfo attachInfo = mAttachInfo;
15450        if (attachInfo != null) {
15451            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15452                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15453        } else {
15454            // Postpone the runnable until we know
15455            // on which thread it needs to run.
15456            getRunQueue().postDelayed(action, delayMillis);
15457        }
15458    }
15459
15460    /**
15461     * <p>Removes the specified Runnable from the message queue.</p>
15462     *
15463     * @param action The Runnable to remove from the message handling queue
15464     *
15465     * @return true if this view could ask the Handler to remove the Runnable,
15466     *         false otherwise. When the returned value is true, the Runnable
15467     *         may or may not have been actually removed from the message queue
15468     *         (for instance, if the Runnable was not in the queue already.)
15469     *
15470     * @see #post
15471     * @see #postDelayed
15472     * @see #postOnAnimation
15473     * @see #postOnAnimationDelayed
15474     */
15475    public boolean removeCallbacks(Runnable action) {
15476        if (action != null) {
15477            final AttachInfo attachInfo = mAttachInfo;
15478            if (attachInfo != null) {
15479                attachInfo.mHandler.removeCallbacks(action);
15480                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15481                        Choreographer.CALLBACK_ANIMATION, action, null);
15482            }
15483            getRunQueue().removeCallbacks(action);
15484        }
15485        return true;
15486    }
15487
15488    /**
15489     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15490     * Use this to invalidate the View from a non-UI thread.</p>
15491     *
15492     * <p>This method can be invoked from outside of the UI thread
15493     * only when this View is attached to a window.</p>
15494     *
15495     * @see #invalidate()
15496     * @see #postInvalidateDelayed(long)
15497     */
15498    public void postInvalidate() {
15499        postInvalidateDelayed(0);
15500    }
15501
15502    /**
15503     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15504     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15505     *
15506     * <p>This method can be invoked from outside of the UI thread
15507     * only when this View is attached to a window.</p>
15508     *
15509     * @param left The left coordinate of the rectangle to invalidate.
15510     * @param top The top coordinate of the rectangle to invalidate.
15511     * @param right The right coordinate of the rectangle to invalidate.
15512     * @param bottom The bottom coordinate of the rectangle to invalidate.
15513     *
15514     * @see #invalidate(int, int, int, int)
15515     * @see #invalidate(Rect)
15516     * @see #postInvalidateDelayed(long, int, int, int, int)
15517     */
15518    public void postInvalidate(int left, int top, int right, int bottom) {
15519        postInvalidateDelayed(0, left, top, right, bottom);
15520    }
15521
15522    /**
15523     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15524     * loop. Waits for the specified amount of time.</p>
15525     *
15526     * <p>This method can be invoked from outside of the UI thread
15527     * only when this View is attached to a window.</p>
15528     *
15529     * @param delayMilliseconds the duration in milliseconds to delay the
15530     *         invalidation by
15531     *
15532     * @see #invalidate()
15533     * @see #postInvalidate()
15534     */
15535    public void postInvalidateDelayed(long delayMilliseconds) {
15536        // We try only with the AttachInfo because there's no point in invalidating
15537        // if we are not attached to our window
15538        final AttachInfo attachInfo = mAttachInfo;
15539        if (attachInfo != null) {
15540            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15541        }
15542    }
15543
15544    /**
15545     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15546     * through the event loop. Waits for the specified amount of time.</p>
15547     *
15548     * <p>This method can be invoked from outside of the UI thread
15549     * only when this View is attached to a window.</p>
15550     *
15551     * @param delayMilliseconds the duration in milliseconds to delay the
15552     *         invalidation by
15553     * @param left The left coordinate of the rectangle to invalidate.
15554     * @param top The top coordinate of the rectangle to invalidate.
15555     * @param right The right coordinate of the rectangle to invalidate.
15556     * @param bottom The bottom coordinate of the rectangle to invalidate.
15557     *
15558     * @see #invalidate(int, int, int, int)
15559     * @see #invalidate(Rect)
15560     * @see #postInvalidate(int, int, int, int)
15561     */
15562    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15563            int right, int bottom) {
15564
15565        // We try only with the AttachInfo because there's no point in invalidating
15566        // if we are not attached to our window
15567        final AttachInfo attachInfo = mAttachInfo;
15568        if (attachInfo != null) {
15569            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15570            info.target = this;
15571            info.left = left;
15572            info.top = top;
15573            info.right = right;
15574            info.bottom = bottom;
15575
15576            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15577        }
15578    }
15579
15580    /**
15581     * <p>Cause an invalidate to happen on the next animation time step, typically the
15582     * next display frame.</p>
15583     *
15584     * <p>This method can be invoked from outside of the UI thread
15585     * only when this View is attached to a window.</p>
15586     *
15587     * @see #invalidate()
15588     */
15589    public void postInvalidateOnAnimation() {
15590        // We try only with the AttachInfo because there's no point in invalidating
15591        // if we are not attached to our window
15592        final AttachInfo attachInfo = mAttachInfo;
15593        if (attachInfo != null) {
15594            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15595        }
15596    }
15597
15598    /**
15599     * <p>Cause an invalidate of the specified area to happen on the next animation
15600     * time step, typically the next display frame.</p>
15601     *
15602     * <p>This method can be invoked from outside of the UI thread
15603     * only when this View is attached to a window.</p>
15604     *
15605     * @param left The left coordinate of the rectangle to invalidate.
15606     * @param top The top coordinate of the rectangle to invalidate.
15607     * @param right The right coordinate of the rectangle to invalidate.
15608     * @param bottom The bottom coordinate of the rectangle to invalidate.
15609     *
15610     * @see #invalidate(int, int, int, int)
15611     * @see #invalidate(Rect)
15612     */
15613    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15614        // We try only with the AttachInfo because there's no point in invalidating
15615        // if we are not attached to our window
15616        final AttachInfo attachInfo = mAttachInfo;
15617        if (attachInfo != null) {
15618            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15619            info.target = this;
15620            info.left = left;
15621            info.top = top;
15622            info.right = right;
15623            info.bottom = bottom;
15624
15625            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15626        }
15627    }
15628
15629    /**
15630     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15631     * This event is sent at most once every
15632     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15633     */
15634    private void postSendViewScrolledAccessibilityEventCallback() {
15635        if (mSendViewScrolledAccessibilityEvent == null) {
15636            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15637        }
15638        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15639            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15640            postDelayed(mSendViewScrolledAccessibilityEvent,
15641                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15642        }
15643    }
15644
15645    /**
15646     * Called by a parent to request that a child update its values for mScrollX
15647     * and mScrollY if necessary. This will typically be done if the child is
15648     * animating a scroll using a {@link android.widget.Scroller Scroller}
15649     * object.
15650     */
15651    public void computeScroll() {
15652    }
15653
15654    /**
15655     * <p>Indicate whether the horizontal edges are faded when the view is
15656     * scrolled horizontally.</p>
15657     *
15658     * @return true if the horizontal edges should are faded on scroll, false
15659     *         otherwise
15660     *
15661     * @see #setHorizontalFadingEdgeEnabled(boolean)
15662     *
15663     * @attr ref android.R.styleable#View_requiresFadingEdge
15664     */
15665    public boolean isHorizontalFadingEdgeEnabled() {
15666        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15667    }
15668
15669    /**
15670     * <p>Define whether the horizontal edges should be faded when this view
15671     * is scrolled horizontally.</p>
15672     *
15673     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15674     *                                    be faded when the view is scrolled
15675     *                                    horizontally
15676     *
15677     * @see #isHorizontalFadingEdgeEnabled()
15678     *
15679     * @attr ref android.R.styleable#View_requiresFadingEdge
15680     */
15681    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15682        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15683            if (horizontalFadingEdgeEnabled) {
15684                initScrollCache();
15685            }
15686
15687            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15688        }
15689    }
15690
15691    /**
15692     * <p>Indicate whether the vertical edges are faded when the view is
15693     * scrolled horizontally.</p>
15694     *
15695     * @return true if the vertical edges should are faded on scroll, false
15696     *         otherwise
15697     *
15698     * @see #setVerticalFadingEdgeEnabled(boolean)
15699     *
15700     * @attr ref android.R.styleable#View_requiresFadingEdge
15701     */
15702    public boolean isVerticalFadingEdgeEnabled() {
15703        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15704    }
15705
15706    /**
15707     * <p>Define whether the vertical edges should be faded when this view
15708     * is scrolled vertically.</p>
15709     *
15710     * @param verticalFadingEdgeEnabled true if the vertical edges should
15711     *                                  be faded when the view is scrolled
15712     *                                  vertically
15713     *
15714     * @see #isVerticalFadingEdgeEnabled()
15715     *
15716     * @attr ref android.R.styleable#View_requiresFadingEdge
15717     */
15718    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15719        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15720            if (verticalFadingEdgeEnabled) {
15721                initScrollCache();
15722            }
15723
15724            mViewFlags ^= FADING_EDGE_VERTICAL;
15725        }
15726    }
15727
15728    /**
15729     * Returns the strength, or intensity, of the top faded edge. The strength is
15730     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15731     * returns 0.0 or 1.0 but no value in between.
15732     *
15733     * Subclasses should override this method to provide a smoother fade transition
15734     * when scrolling occurs.
15735     *
15736     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15737     */
15738    protected float getTopFadingEdgeStrength() {
15739        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15740    }
15741
15742    /**
15743     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15744     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15745     * returns 0.0 or 1.0 but no value in between.
15746     *
15747     * Subclasses should override this method to provide a smoother fade transition
15748     * when scrolling occurs.
15749     *
15750     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15751     */
15752    protected float getBottomFadingEdgeStrength() {
15753        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15754                computeVerticalScrollRange() ? 1.0f : 0.0f;
15755    }
15756
15757    /**
15758     * Returns the strength, or intensity, of the left faded edge. The strength is
15759     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15760     * returns 0.0 or 1.0 but no value in between.
15761     *
15762     * Subclasses should override this method to provide a smoother fade transition
15763     * when scrolling occurs.
15764     *
15765     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15766     */
15767    protected float getLeftFadingEdgeStrength() {
15768        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15769    }
15770
15771    /**
15772     * Returns the strength, or intensity, of the right faded edge. The strength is
15773     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15774     * returns 0.0 or 1.0 but no value in between.
15775     *
15776     * Subclasses should override this method to provide a smoother fade transition
15777     * when scrolling occurs.
15778     *
15779     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15780     */
15781    protected float getRightFadingEdgeStrength() {
15782        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15783                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15784    }
15785
15786    /**
15787     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15788     * scrollbar is not drawn by default.</p>
15789     *
15790     * @return true if the horizontal scrollbar should be painted, false
15791     *         otherwise
15792     *
15793     * @see #setHorizontalScrollBarEnabled(boolean)
15794     */
15795    public boolean isHorizontalScrollBarEnabled() {
15796        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15797    }
15798
15799    /**
15800     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15801     * scrollbar is not drawn by default.</p>
15802     *
15803     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15804     *                                   be painted
15805     *
15806     * @see #isHorizontalScrollBarEnabled()
15807     */
15808    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15809        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15810            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15811            computeOpaqueFlags();
15812            resolvePadding();
15813        }
15814    }
15815
15816    /**
15817     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15818     * scrollbar is not drawn by default.</p>
15819     *
15820     * @return true if the vertical scrollbar should be painted, false
15821     *         otherwise
15822     *
15823     * @see #setVerticalScrollBarEnabled(boolean)
15824     */
15825    public boolean isVerticalScrollBarEnabled() {
15826        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15827    }
15828
15829    /**
15830     * <p>Define whether the vertical scrollbar should be drawn or not. The
15831     * scrollbar is not drawn by default.</p>
15832     *
15833     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15834     *                                 be painted
15835     *
15836     * @see #isVerticalScrollBarEnabled()
15837     */
15838    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15839        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15840            mViewFlags ^= SCROLLBARS_VERTICAL;
15841            computeOpaqueFlags();
15842            resolvePadding();
15843        }
15844    }
15845
15846    /**
15847     * @hide
15848     */
15849    protected void recomputePadding() {
15850        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15851    }
15852
15853    /**
15854     * Define whether scrollbars will fade when the view is not scrolling.
15855     *
15856     * @param fadeScrollbars whether to enable fading
15857     *
15858     * @attr ref android.R.styleable#View_fadeScrollbars
15859     */
15860    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15861        initScrollCache();
15862        final ScrollabilityCache scrollabilityCache = mScrollCache;
15863        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15864        if (fadeScrollbars) {
15865            scrollabilityCache.state = ScrollabilityCache.OFF;
15866        } else {
15867            scrollabilityCache.state = ScrollabilityCache.ON;
15868        }
15869    }
15870
15871    /**
15872     *
15873     * Returns true if scrollbars will fade when this view is not scrolling
15874     *
15875     * @return true if scrollbar fading is enabled
15876     *
15877     * @attr ref android.R.styleable#View_fadeScrollbars
15878     */
15879    public boolean isScrollbarFadingEnabled() {
15880        return mScrollCache != null && mScrollCache.fadeScrollBars;
15881    }
15882
15883    /**
15884     *
15885     * Returns the delay before scrollbars fade.
15886     *
15887     * @return the delay before scrollbars fade
15888     *
15889     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15890     */
15891    public int getScrollBarDefaultDelayBeforeFade() {
15892        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15893                mScrollCache.scrollBarDefaultDelayBeforeFade;
15894    }
15895
15896    /**
15897     * Define the delay before scrollbars fade.
15898     *
15899     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15900     *
15901     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15902     */
15903    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15904        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15905    }
15906
15907    /**
15908     *
15909     * Returns the scrollbar fade duration.
15910     *
15911     * @return the scrollbar fade duration, in milliseconds
15912     *
15913     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15914     */
15915    public int getScrollBarFadeDuration() {
15916        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15917                mScrollCache.scrollBarFadeDuration;
15918    }
15919
15920    /**
15921     * Define the scrollbar fade duration.
15922     *
15923     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15924     *
15925     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15926     */
15927    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15928        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15929    }
15930
15931    /**
15932     *
15933     * Returns the scrollbar size.
15934     *
15935     * @return the scrollbar size
15936     *
15937     * @attr ref android.R.styleable#View_scrollbarSize
15938     */
15939    public int getScrollBarSize() {
15940        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15941                mScrollCache.scrollBarSize;
15942    }
15943
15944    /**
15945     * Define the scrollbar size.
15946     *
15947     * @param scrollBarSize - the scrollbar size
15948     *
15949     * @attr ref android.R.styleable#View_scrollbarSize
15950     */
15951    public void setScrollBarSize(int scrollBarSize) {
15952        getScrollCache().scrollBarSize = scrollBarSize;
15953    }
15954
15955    /**
15956     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15957     * inset. When inset, they add to the padding of the view. And the scrollbars
15958     * can be drawn inside the padding area or on the edge of the view. For example,
15959     * if a view has a background drawable and you want to draw the scrollbars
15960     * inside the padding specified by the drawable, you can use
15961     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15962     * appear at the edge of the view, ignoring the padding, then you can use
15963     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15964     * @param style the style of the scrollbars. Should be one of
15965     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15966     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15967     * @see #SCROLLBARS_INSIDE_OVERLAY
15968     * @see #SCROLLBARS_INSIDE_INSET
15969     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15970     * @see #SCROLLBARS_OUTSIDE_INSET
15971     *
15972     * @attr ref android.R.styleable#View_scrollbarStyle
15973     */
15974    public void setScrollBarStyle(@ScrollBarStyle int style) {
15975        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15976            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15977            computeOpaqueFlags();
15978            resolvePadding();
15979        }
15980    }
15981
15982    /**
15983     * <p>Returns the current scrollbar style.</p>
15984     * @return the current scrollbar style
15985     * @see #SCROLLBARS_INSIDE_OVERLAY
15986     * @see #SCROLLBARS_INSIDE_INSET
15987     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15988     * @see #SCROLLBARS_OUTSIDE_INSET
15989     *
15990     * @attr ref android.R.styleable#View_scrollbarStyle
15991     */
15992    @ViewDebug.ExportedProperty(mapping = {
15993            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15994            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15995            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15996            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15997    })
15998    @ScrollBarStyle
15999    public int getScrollBarStyle() {
16000        return mViewFlags & SCROLLBARS_STYLE_MASK;
16001    }
16002
16003    /**
16004     * <p>Compute the horizontal range that the horizontal scrollbar
16005     * represents.</p>
16006     *
16007     * <p>The range is expressed in arbitrary units that must be the same as the
16008     * units used by {@link #computeHorizontalScrollExtent()} and
16009     * {@link #computeHorizontalScrollOffset()}.</p>
16010     *
16011     * <p>The default range is the drawing width of this view.</p>
16012     *
16013     * @return the total horizontal range represented by the horizontal
16014     *         scrollbar
16015     *
16016     * @see #computeHorizontalScrollExtent()
16017     * @see #computeHorizontalScrollOffset()
16018     * @see android.widget.ScrollBarDrawable
16019     */
16020    protected int computeHorizontalScrollRange() {
16021        return getWidth();
16022    }
16023
16024    /**
16025     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16026     * within the horizontal range. This value is used to compute the position
16027     * of the thumb within the scrollbar's track.</p>
16028     *
16029     * <p>The range is expressed in arbitrary units that must be the same as the
16030     * units used by {@link #computeHorizontalScrollRange()} and
16031     * {@link #computeHorizontalScrollExtent()}.</p>
16032     *
16033     * <p>The default offset is the scroll offset of this view.</p>
16034     *
16035     * @return the horizontal offset of the scrollbar's thumb
16036     *
16037     * @see #computeHorizontalScrollRange()
16038     * @see #computeHorizontalScrollExtent()
16039     * @see android.widget.ScrollBarDrawable
16040     */
16041    protected int computeHorizontalScrollOffset() {
16042        return mScrollX;
16043    }
16044
16045    /**
16046     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16047     * within the horizontal range. This value is used to compute the length
16048     * of the thumb within the scrollbar's track.</p>
16049     *
16050     * <p>The range is expressed in arbitrary units that must be the same as the
16051     * units used by {@link #computeHorizontalScrollRange()} and
16052     * {@link #computeHorizontalScrollOffset()}.</p>
16053     *
16054     * <p>The default extent is the drawing width of this view.</p>
16055     *
16056     * @return the horizontal extent of the scrollbar's thumb
16057     *
16058     * @see #computeHorizontalScrollRange()
16059     * @see #computeHorizontalScrollOffset()
16060     * @see android.widget.ScrollBarDrawable
16061     */
16062    protected int computeHorizontalScrollExtent() {
16063        return getWidth();
16064    }
16065
16066    /**
16067     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16068     *
16069     * <p>The range is expressed in arbitrary units that must be the same as the
16070     * units used by {@link #computeVerticalScrollExtent()} and
16071     * {@link #computeVerticalScrollOffset()}.</p>
16072     *
16073     * @return the total vertical range represented by the vertical scrollbar
16074     *
16075     * <p>The default range is the drawing height of this view.</p>
16076     *
16077     * @see #computeVerticalScrollExtent()
16078     * @see #computeVerticalScrollOffset()
16079     * @see android.widget.ScrollBarDrawable
16080     */
16081    protected int computeVerticalScrollRange() {
16082        return getHeight();
16083    }
16084
16085    /**
16086     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16087     * within the horizontal range. This value is used to compute the position
16088     * of the thumb within the scrollbar's track.</p>
16089     *
16090     * <p>The range is expressed in arbitrary units that must be the same as the
16091     * units used by {@link #computeVerticalScrollRange()} and
16092     * {@link #computeVerticalScrollExtent()}.</p>
16093     *
16094     * <p>The default offset is the scroll offset of this view.</p>
16095     *
16096     * @return the vertical offset of the scrollbar's thumb
16097     *
16098     * @see #computeVerticalScrollRange()
16099     * @see #computeVerticalScrollExtent()
16100     * @see android.widget.ScrollBarDrawable
16101     */
16102    protected int computeVerticalScrollOffset() {
16103        return mScrollY;
16104    }
16105
16106    /**
16107     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16108     * within the vertical range. This value is used to compute the length
16109     * of the thumb within the scrollbar's track.</p>
16110     *
16111     * <p>The range is expressed in arbitrary units that must be the same as the
16112     * units used by {@link #computeVerticalScrollRange()} and
16113     * {@link #computeVerticalScrollOffset()}.</p>
16114     *
16115     * <p>The default extent is the drawing height of this view.</p>
16116     *
16117     * @return the vertical extent of the scrollbar's thumb
16118     *
16119     * @see #computeVerticalScrollRange()
16120     * @see #computeVerticalScrollOffset()
16121     * @see android.widget.ScrollBarDrawable
16122     */
16123    protected int computeVerticalScrollExtent() {
16124        return getHeight();
16125    }
16126
16127    /**
16128     * Check if this view can be scrolled horizontally in a certain direction.
16129     *
16130     * @param direction Negative to check scrolling left, positive to check scrolling right.
16131     * @return true if this view can be scrolled in the specified direction, false otherwise.
16132     */
16133    public boolean canScrollHorizontally(int direction) {
16134        final int offset = computeHorizontalScrollOffset();
16135        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16136        if (range == 0) return false;
16137        if (direction < 0) {
16138            return offset > 0;
16139        } else {
16140            return offset < range - 1;
16141        }
16142    }
16143
16144    /**
16145     * Check if this view can be scrolled vertically in a certain direction.
16146     *
16147     * @param direction Negative to check scrolling up, positive to check scrolling down.
16148     * @return true if this view can be scrolled in the specified direction, false otherwise.
16149     */
16150    public boolean canScrollVertically(int direction) {
16151        final int offset = computeVerticalScrollOffset();
16152        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16153        if (range == 0) return false;
16154        if (direction < 0) {
16155            return offset > 0;
16156        } else {
16157            return offset < range - 1;
16158        }
16159    }
16160
16161    void getScrollIndicatorBounds(@NonNull Rect out) {
16162        out.left = mScrollX;
16163        out.right = mScrollX + mRight - mLeft;
16164        out.top = mScrollY;
16165        out.bottom = mScrollY + mBottom - mTop;
16166    }
16167
16168    private void onDrawScrollIndicators(Canvas c) {
16169        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16170            // No scroll indicators enabled.
16171            return;
16172        }
16173
16174        final Drawable dr = mScrollIndicatorDrawable;
16175        if (dr == null) {
16176            // Scroll indicators aren't supported here.
16177            return;
16178        }
16179
16180        final int h = dr.getIntrinsicHeight();
16181        final int w = dr.getIntrinsicWidth();
16182        final Rect rect = mAttachInfo.mTmpInvalRect;
16183        getScrollIndicatorBounds(rect);
16184
16185        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16186            final boolean canScrollUp = canScrollVertically(-1);
16187            if (canScrollUp) {
16188                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16189                dr.draw(c);
16190            }
16191        }
16192
16193        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16194            final boolean canScrollDown = canScrollVertically(1);
16195            if (canScrollDown) {
16196                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16197                dr.draw(c);
16198            }
16199        }
16200
16201        final int leftRtl;
16202        final int rightRtl;
16203        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16204            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16205            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16206        } else {
16207            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16208            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16209        }
16210
16211        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16212        if ((mPrivateFlags3 & leftMask) != 0) {
16213            final boolean canScrollLeft = canScrollHorizontally(-1);
16214            if (canScrollLeft) {
16215                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16216                dr.draw(c);
16217            }
16218        }
16219
16220        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16221        if ((mPrivateFlags3 & rightMask) != 0) {
16222            final boolean canScrollRight = canScrollHorizontally(1);
16223            if (canScrollRight) {
16224                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16225                dr.draw(c);
16226            }
16227        }
16228    }
16229
16230    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16231            @Nullable Rect touchBounds) {
16232        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16233        if (bounds == null) {
16234            return;
16235        }
16236        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16237        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16238                && !isVerticalScrollBarHidden();
16239        final int size = getHorizontalScrollbarHeight();
16240        final int verticalScrollBarGap = drawVerticalScrollBar ?
16241                getVerticalScrollbarWidth() : 0;
16242        final int width = mRight - mLeft;
16243        final int height = mBottom - mTop;
16244        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16245        bounds.left = mScrollX + (mPaddingLeft & inside);
16246        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16247        bounds.bottom = bounds.top + size;
16248
16249        if (touchBounds == null) {
16250            return;
16251        }
16252        if (touchBounds != bounds) {
16253            touchBounds.set(bounds);
16254        }
16255        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16256        if (touchBounds.height() < minTouchTarget) {
16257            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16258            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16259            touchBounds.top = touchBounds.bottom - minTouchTarget;
16260        }
16261        if (touchBounds.width() < minTouchTarget) {
16262            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16263            touchBounds.left -= adjust;
16264            touchBounds.right = touchBounds.left + minTouchTarget;
16265        }
16266    }
16267
16268    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16269        if (mRoundScrollbarRenderer == null) {
16270            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16271        } else {
16272            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16273        }
16274    }
16275
16276    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16277        final int width = mRight - mLeft;
16278        final int height = mBottom - mTop;
16279        // Do not take padding into account as we always want the scrollbars
16280        // to hug the screen for round wearable devices.
16281        bounds.left = mScrollX;
16282        bounds.top = mScrollY;
16283        bounds.right = bounds.left + width;
16284        bounds.bottom = mScrollY + height;
16285    }
16286
16287    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16288            @Nullable Rect touchBounds) {
16289        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16290        if (bounds == null) {
16291            return;
16292        }
16293        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16294        final int size = getVerticalScrollbarWidth();
16295        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16296        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16297            verticalScrollbarPosition = isLayoutRtl() ?
16298                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16299        }
16300        final int width = mRight - mLeft;
16301        final int height = mBottom - mTop;
16302        switch (verticalScrollbarPosition) {
16303            default:
16304            case SCROLLBAR_POSITION_RIGHT:
16305                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16306                break;
16307            case SCROLLBAR_POSITION_LEFT:
16308                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16309                break;
16310        }
16311        bounds.top = mScrollY + (mPaddingTop & inside);
16312        bounds.right = bounds.left + size;
16313        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16314
16315        if (touchBounds == null) {
16316            return;
16317        }
16318        if (touchBounds != bounds) {
16319            touchBounds.set(bounds);
16320        }
16321        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16322        if (touchBounds.width() < minTouchTarget) {
16323            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16324            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16325                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16326                touchBounds.left = touchBounds.right - minTouchTarget;
16327            } else {
16328                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16329                touchBounds.right = touchBounds.left + minTouchTarget;
16330            }
16331        }
16332        if (touchBounds.height() < minTouchTarget) {
16333            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16334            touchBounds.top -= adjust;
16335            touchBounds.bottom = touchBounds.top + minTouchTarget;
16336        }
16337    }
16338
16339    /**
16340     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16341     * scrollbars are painted only if they have been awakened first.</p>
16342     *
16343     * @param canvas the canvas on which to draw the scrollbars
16344     *
16345     * @see #awakenScrollBars(int)
16346     */
16347    protected final void onDrawScrollBars(Canvas canvas) {
16348        // scrollbars are drawn only when the animation is running
16349        final ScrollabilityCache cache = mScrollCache;
16350
16351        if (cache != null) {
16352
16353            int state = cache.state;
16354
16355            if (state == ScrollabilityCache.OFF) {
16356                return;
16357            }
16358
16359            boolean invalidate = false;
16360
16361            if (state == ScrollabilityCache.FADING) {
16362                // We're fading -- get our fade interpolation
16363                if (cache.interpolatorValues == null) {
16364                    cache.interpolatorValues = new float[1];
16365                }
16366
16367                float[] values = cache.interpolatorValues;
16368
16369                // Stops the animation if we're done
16370                if (cache.scrollBarInterpolator.timeToValues(values) ==
16371                        Interpolator.Result.FREEZE_END) {
16372                    cache.state = ScrollabilityCache.OFF;
16373                } else {
16374                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16375                }
16376
16377                // This will make the scroll bars inval themselves after
16378                // drawing. We only want this when we're fading so that
16379                // we prevent excessive redraws
16380                invalidate = true;
16381            } else {
16382                // We're just on -- but we may have been fading before so
16383                // reset alpha
16384                cache.scrollBar.mutate().setAlpha(255);
16385            }
16386
16387            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16388            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16389                    && !isVerticalScrollBarHidden();
16390
16391            // Fork out the scroll bar drawing for round wearable devices.
16392            if (mRoundScrollbarRenderer != null) {
16393                if (drawVerticalScrollBar) {
16394                    final Rect bounds = cache.mScrollBarBounds;
16395                    getVerticalScrollBarBounds(bounds, null);
16396                    mRoundScrollbarRenderer.drawRoundScrollbars(
16397                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16398                    if (invalidate) {
16399                        invalidate();
16400                    }
16401                }
16402                // Do not draw horizontal scroll bars for round wearable devices.
16403            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16404                final ScrollBarDrawable scrollBar = cache.scrollBar;
16405
16406                if (drawHorizontalScrollBar) {
16407                    scrollBar.setParameters(computeHorizontalScrollRange(),
16408                            computeHorizontalScrollOffset(),
16409                            computeHorizontalScrollExtent(), false);
16410                    final Rect bounds = cache.mScrollBarBounds;
16411                    getHorizontalScrollBarBounds(bounds, null);
16412                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16413                            bounds.right, bounds.bottom);
16414                    if (invalidate) {
16415                        invalidate(bounds);
16416                    }
16417                }
16418
16419                if (drawVerticalScrollBar) {
16420                    scrollBar.setParameters(computeVerticalScrollRange(),
16421                            computeVerticalScrollOffset(),
16422                            computeVerticalScrollExtent(), true);
16423                    final Rect bounds = cache.mScrollBarBounds;
16424                    getVerticalScrollBarBounds(bounds, null);
16425                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16426                            bounds.right, bounds.bottom);
16427                    if (invalidate) {
16428                        invalidate(bounds);
16429                    }
16430                }
16431            }
16432        }
16433    }
16434
16435    /**
16436     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16437     * FastScroller is visible.
16438     * @return whether to temporarily hide the vertical scrollbar
16439     * @hide
16440     */
16441    protected boolean isVerticalScrollBarHidden() {
16442        return false;
16443    }
16444
16445    /**
16446     * <p>Draw the horizontal scrollbar if
16447     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16448     *
16449     * @param canvas the canvas on which to draw the scrollbar
16450     * @param scrollBar the scrollbar's drawable
16451     *
16452     * @see #isHorizontalScrollBarEnabled()
16453     * @see #computeHorizontalScrollRange()
16454     * @see #computeHorizontalScrollExtent()
16455     * @see #computeHorizontalScrollOffset()
16456     * @see android.widget.ScrollBarDrawable
16457     * @hide
16458     */
16459    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16460            int l, int t, int r, int b) {
16461        scrollBar.setBounds(l, t, r, b);
16462        scrollBar.draw(canvas);
16463    }
16464
16465    /**
16466     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16467     * returns true.</p>
16468     *
16469     * @param canvas the canvas on which to draw the scrollbar
16470     * @param scrollBar the scrollbar's drawable
16471     *
16472     * @see #isVerticalScrollBarEnabled()
16473     * @see #computeVerticalScrollRange()
16474     * @see #computeVerticalScrollExtent()
16475     * @see #computeVerticalScrollOffset()
16476     * @see android.widget.ScrollBarDrawable
16477     * @hide
16478     */
16479    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16480            int l, int t, int r, int b) {
16481        scrollBar.setBounds(l, t, r, b);
16482        scrollBar.draw(canvas);
16483    }
16484
16485    /**
16486     * Implement this to do your drawing.
16487     *
16488     * @param canvas the canvas on which the background will be drawn
16489     */
16490    protected void onDraw(Canvas canvas) {
16491    }
16492
16493    /*
16494     * Caller is responsible for calling requestLayout if necessary.
16495     * (This allows addViewInLayout to not request a new layout.)
16496     */
16497    void assignParent(ViewParent parent) {
16498        if (mParent == null) {
16499            mParent = parent;
16500        } else if (parent == null) {
16501            mParent = null;
16502        } else {
16503            throw new RuntimeException("view " + this + " being added, but"
16504                    + " it already has a parent");
16505        }
16506    }
16507
16508    /**
16509     * This is called when the view is attached to a window.  At this point it
16510     * has a Surface and will start drawing.  Note that this function is
16511     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16512     * however it may be called any time before the first onDraw -- including
16513     * before or after {@link #onMeasure(int, int)}.
16514     *
16515     * @see #onDetachedFromWindow()
16516     */
16517    @CallSuper
16518    protected void onAttachedToWindow() {
16519        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16520            mParent.requestTransparentRegion(this);
16521        }
16522
16523        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16524
16525        jumpDrawablesToCurrentState();
16526
16527        resetSubtreeAccessibilityStateChanged();
16528
16529        // rebuild, since Outline not maintained while View is detached
16530        rebuildOutline();
16531
16532        if (isFocused()) {
16533            InputMethodManager imm = InputMethodManager.peekInstance();
16534            if (imm != null) {
16535                imm.focusIn(this);
16536            }
16537        }
16538    }
16539
16540    /**
16541     * Resolve all RTL related properties.
16542     *
16543     * @return true if resolution of RTL properties has been done
16544     *
16545     * @hide
16546     */
16547    public boolean resolveRtlPropertiesIfNeeded() {
16548        if (!needRtlPropertiesResolution()) return false;
16549
16550        // Order is important here: LayoutDirection MUST be resolved first
16551        if (!isLayoutDirectionResolved()) {
16552            resolveLayoutDirection();
16553            resolveLayoutParams();
16554        }
16555        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16556        if (!isTextDirectionResolved()) {
16557            resolveTextDirection();
16558        }
16559        if (!isTextAlignmentResolved()) {
16560            resolveTextAlignment();
16561        }
16562        // Should resolve Drawables before Padding because we need the layout direction of the
16563        // Drawable to correctly resolve Padding.
16564        if (!areDrawablesResolved()) {
16565            resolveDrawables();
16566        }
16567        if (!isPaddingResolved()) {
16568            resolvePadding();
16569        }
16570        onRtlPropertiesChanged(getLayoutDirection());
16571        return true;
16572    }
16573
16574    /**
16575     * Reset resolution of all RTL related properties.
16576     *
16577     * @hide
16578     */
16579    public void resetRtlProperties() {
16580        resetResolvedLayoutDirection();
16581        resetResolvedTextDirection();
16582        resetResolvedTextAlignment();
16583        resetResolvedPadding();
16584        resetResolvedDrawables();
16585    }
16586
16587    /**
16588     * @see #onScreenStateChanged(int)
16589     */
16590    void dispatchScreenStateChanged(int screenState) {
16591        onScreenStateChanged(screenState);
16592    }
16593
16594    /**
16595     * This method is called whenever the state of the screen this view is
16596     * attached to changes. A state change will usually occurs when the screen
16597     * turns on or off (whether it happens automatically or the user does it
16598     * manually.)
16599     *
16600     * @param screenState The new state of the screen. Can be either
16601     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16602     */
16603    public void onScreenStateChanged(int screenState) {
16604    }
16605
16606    /**
16607     * @see #onMovedToDisplay(int, Configuration)
16608     */
16609    void dispatchMovedToDisplay(Display display, Configuration config) {
16610        mAttachInfo.mDisplay = display;
16611        mAttachInfo.mDisplayState = display.getState();
16612        onMovedToDisplay(display.getDisplayId(), config);
16613    }
16614
16615    /**
16616     * Called by the system when the hosting activity is moved from one display to another without
16617     * recreation. This means that the activity is declared to handle all changes to configuration
16618     * that happened when it was switched to another display, so it wasn't destroyed and created
16619     * again.
16620     *
16621     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16622     * applied configuration actually changed. It is up to app developer to choose whether to handle
16623     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16624     * call.
16625     *
16626     * <p>Use this callback to track changes to the displays if some functionality relies on an
16627     * association with some display properties.
16628     *
16629     * @param displayId The id of the display to which the view was moved.
16630     * @param config Configuration of the resources on new display after move.
16631     *
16632     * @see #onConfigurationChanged(Configuration)
16633     * @hide
16634     */
16635    public void onMovedToDisplay(int displayId, Configuration config) {
16636    }
16637
16638    /**
16639     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16640     */
16641    private boolean hasRtlSupport() {
16642        return mContext.getApplicationInfo().hasRtlSupport();
16643    }
16644
16645    /**
16646     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16647     * RTL not supported)
16648     */
16649    private boolean isRtlCompatibilityMode() {
16650        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16651        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16652    }
16653
16654    /**
16655     * @return true if RTL properties need resolution.
16656     *
16657     */
16658    private boolean needRtlPropertiesResolution() {
16659        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16660    }
16661
16662    /**
16663     * Called when any RTL property (layout direction or text direction or text alignment) has
16664     * been changed.
16665     *
16666     * Subclasses need to override this method to take care of cached information that depends on the
16667     * resolved layout direction, or to inform child views that inherit their layout direction.
16668     *
16669     * The default implementation does nothing.
16670     *
16671     * @param layoutDirection the direction of the layout
16672     *
16673     * @see #LAYOUT_DIRECTION_LTR
16674     * @see #LAYOUT_DIRECTION_RTL
16675     */
16676    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16677    }
16678
16679    /**
16680     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16681     * that the parent directionality can and will be resolved before its children.
16682     *
16683     * @return true if resolution has been done, false otherwise.
16684     *
16685     * @hide
16686     */
16687    public boolean resolveLayoutDirection() {
16688        // Clear any previous layout direction resolution
16689        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16690
16691        if (hasRtlSupport()) {
16692            // Set resolved depending on layout direction
16693            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16694                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16695                case LAYOUT_DIRECTION_INHERIT:
16696                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16697                    // later to get the correct resolved value
16698                    if (!canResolveLayoutDirection()) return false;
16699
16700                    // Parent has not yet resolved, LTR is still the default
16701                    try {
16702                        if (!mParent.isLayoutDirectionResolved()) return false;
16703
16704                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16705                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16706                        }
16707                    } catch (AbstractMethodError e) {
16708                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16709                                " does not fully implement ViewParent", e);
16710                    }
16711                    break;
16712                case LAYOUT_DIRECTION_RTL:
16713                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16714                    break;
16715                case LAYOUT_DIRECTION_LOCALE:
16716                    if((LAYOUT_DIRECTION_RTL ==
16717                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16718                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16719                    }
16720                    break;
16721                default:
16722                    // Nothing to do, LTR by default
16723            }
16724        }
16725
16726        // Set to resolved
16727        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16728        return true;
16729    }
16730
16731    /**
16732     * Check if layout direction resolution can be done.
16733     *
16734     * @return true if layout direction resolution can be done otherwise return false.
16735     */
16736    public boolean canResolveLayoutDirection() {
16737        switch (getRawLayoutDirection()) {
16738            case LAYOUT_DIRECTION_INHERIT:
16739                if (mParent != null) {
16740                    try {
16741                        return mParent.canResolveLayoutDirection();
16742                    } catch (AbstractMethodError e) {
16743                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16744                                " does not fully implement ViewParent", e);
16745                    }
16746                }
16747                return false;
16748
16749            default:
16750                return true;
16751        }
16752    }
16753
16754    /**
16755     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16756     * {@link #onMeasure(int, int)}.
16757     *
16758     * @hide
16759     */
16760    public void resetResolvedLayoutDirection() {
16761        // Reset the current resolved bits
16762        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16763    }
16764
16765    /**
16766     * @return true if the layout direction is inherited.
16767     *
16768     * @hide
16769     */
16770    public boolean isLayoutDirectionInherited() {
16771        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16772    }
16773
16774    /**
16775     * @return true if layout direction has been resolved.
16776     */
16777    public boolean isLayoutDirectionResolved() {
16778        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16779    }
16780
16781    /**
16782     * Return if padding has been resolved
16783     *
16784     * @hide
16785     */
16786    boolean isPaddingResolved() {
16787        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16788    }
16789
16790    /**
16791     * Resolves padding depending on layout direction, if applicable, and
16792     * recomputes internal padding values to adjust for scroll bars.
16793     *
16794     * @hide
16795     */
16796    public void resolvePadding() {
16797        final int resolvedLayoutDirection = getLayoutDirection();
16798
16799        if (!isRtlCompatibilityMode()) {
16800            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16801            // If start / end padding are defined, they will be resolved (hence overriding) to
16802            // left / right or right / left depending on the resolved layout direction.
16803            // If start / end padding are not defined, use the left / right ones.
16804            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16805                Rect padding = sThreadLocal.get();
16806                if (padding == null) {
16807                    padding = new Rect();
16808                    sThreadLocal.set(padding);
16809                }
16810                mBackground.getPadding(padding);
16811                if (!mLeftPaddingDefined) {
16812                    mUserPaddingLeftInitial = padding.left;
16813                }
16814                if (!mRightPaddingDefined) {
16815                    mUserPaddingRightInitial = padding.right;
16816                }
16817            }
16818            switch (resolvedLayoutDirection) {
16819                case LAYOUT_DIRECTION_RTL:
16820                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16821                        mUserPaddingRight = mUserPaddingStart;
16822                    } else {
16823                        mUserPaddingRight = mUserPaddingRightInitial;
16824                    }
16825                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16826                        mUserPaddingLeft = mUserPaddingEnd;
16827                    } else {
16828                        mUserPaddingLeft = mUserPaddingLeftInitial;
16829                    }
16830                    break;
16831                case LAYOUT_DIRECTION_LTR:
16832                default:
16833                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16834                        mUserPaddingLeft = mUserPaddingStart;
16835                    } else {
16836                        mUserPaddingLeft = mUserPaddingLeftInitial;
16837                    }
16838                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16839                        mUserPaddingRight = mUserPaddingEnd;
16840                    } else {
16841                        mUserPaddingRight = mUserPaddingRightInitial;
16842                    }
16843            }
16844
16845            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16846        }
16847
16848        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16849        onRtlPropertiesChanged(resolvedLayoutDirection);
16850
16851        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16852    }
16853
16854    /**
16855     * Reset the resolved layout direction.
16856     *
16857     * @hide
16858     */
16859    public void resetResolvedPadding() {
16860        resetResolvedPaddingInternal();
16861    }
16862
16863    /**
16864     * Used when we only want to reset *this* view's padding and not trigger overrides
16865     * in ViewGroup that reset children too.
16866     */
16867    void resetResolvedPaddingInternal() {
16868        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16869    }
16870
16871    /**
16872     * This is called when the view is detached from a window.  At this point it
16873     * no longer has a surface for drawing.
16874     *
16875     * @see #onAttachedToWindow()
16876     */
16877    @CallSuper
16878    protected void onDetachedFromWindow() {
16879    }
16880
16881    /**
16882     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16883     * after onDetachedFromWindow().
16884     *
16885     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16886     * The super method should be called at the end of the overridden method to ensure
16887     * subclasses are destroyed first
16888     *
16889     * @hide
16890     */
16891    @CallSuper
16892    protected void onDetachedFromWindowInternal() {
16893        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16894        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16895        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16896
16897        removeUnsetPressCallback();
16898        removeLongPressCallback();
16899        removePerformClickCallback();
16900        removeSendViewScrolledAccessibilityEventCallback();
16901        stopNestedScroll();
16902
16903        // Anything that started animating right before detach should already
16904        // be in its final state when re-attached.
16905        jumpDrawablesToCurrentState();
16906
16907        destroyDrawingCache();
16908
16909        cleanupDraw();
16910        mCurrentAnimation = null;
16911
16912        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16913            hideTooltip();
16914        }
16915    }
16916
16917    private void cleanupDraw() {
16918        resetDisplayList();
16919        if (mAttachInfo != null) {
16920            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16921        }
16922    }
16923
16924    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16925    }
16926
16927    /**
16928     * @return The number of times this view has been attached to a window
16929     */
16930    protected int getWindowAttachCount() {
16931        return mWindowAttachCount;
16932    }
16933
16934    /**
16935     * Retrieve a unique token identifying the window this view is attached to.
16936     * @return Return the window's token for use in
16937     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16938     */
16939    public IBinder getWindowToken() {
16940        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16941    }
16942
16943    /**
16944     * Retrieve the {@link WindowId} for the window this view is
16945     * currently attached to.
16946     */
16947    public WindowId getWindowId() {
16948        if (mAttachInfo == null) {
16949            return null;
16950        }
16951        if (mAttachInfo.mWindowId == null) {
16952            try {
16953                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16954                        mAttachInfo.mWindowToken);
16955                mAttachInfo.mWindowId = new WindowId(
16956                        mAttachInfo.mIWindowId);
16957            } catch (RemoteException e) {
16958            }
16959        }
16960        return mAttachInfo.mWindowId;
16961    }
16962
16963    /**
16964     * Retrieve a unique token identifying the top-level "real" window of
16965     * the window that this view is attached to.  That is, this is like
16966     * {@link #getWindowToken}, except if the window this view in is a panel
16967     * window (attached to another containing window), then the token of
16968     * the containing window is returned instead.
16969     *
16970     * @return Returns the associated window token, either
16971     * {@link #getWindowToken()} or the containing window's token.
16972     */
16973    public IBinder getApplicationWindowToken() {
16974        AttachInfo ai = mAttachInfo;
16975        if (ai != null) {
16976            IBinder appWindowToken = ai.mPanelParentWindowToken;
16977            if (appWindowToken == null) {
16978                appWindowToken = ai.mWindowToken;
16979            }
16980            return appWindowToken;
16981        }
16982        return null;
16983    }
16984
16985    /**
16986     * Gets the logical display to which the view's window has been attached.
16987     *
16988     * @return The logical display, or null if the view is not currently attached to a window.
16989     */
16990    public Display getDisplay() {
16991        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16992    }
16993
16994    /**
16995     * Retrieve private session object this view hierarchy is using to
16996     * communicate with the window manager.
16997     * @return the session object to communicate with the window manager
16998     */
16999    /*package*/ IWindowSession getWindowSession() {
17000        return mAttachInfo != null ? mAttachInfo.mSession : null;
17001    }
17002
17003    /**
17004     * Return the visibility value of the least visible component passed.
17005     */
17006    int combineVisibility(int vis1, int vis2) {
17007        // This works because VISIBLE < INVISIBLE < GONE.
17008        return Math.max(vis1, vis2);
17009    }
17010
17011    /**
17012     * @param info the {@link android.view.View.AttachInfo} to associated with
17013     *        this view
17014     */
17015    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17016        mAttachInfo = info;
17017        if (mOverlay != null) {
17018            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17019        }
17020        mWindowAttachCount++;
17021        // We will need to evaluate the drawable state at least once.
17022        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17023        if (mFloatingTreeObserver != null) {
17024            info.mTreeObserver.merge(mFloatingTreeObserver);
17025            mFloatingTreeObserver = null;
17026        }
17027
17028        registerPendingFrameMetricsObservers();
17029
17030        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17031            mAttachInfo.mScrollContainers.add(this);
17032            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17033        }
17034        // Transfer all pending runnables.
17035        if (mRunQueue != null) {
17036            mRunQueue.executeActions(info.mHandler);
17037            mRunQueue = null;
17038        }
17039        performCollectViewAttributes(mAttachInfo, visibility);
17040        onAttachedToWindow();
17041
17042        ListenerInfo li = mListenerInfo;
17043        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17044                li != null ? li.mOnAttachStateChangeListeners : null;
17045        if (listeners != null && listeners.size() > 0) {
17046            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17047            // perform the dispatching. The iterator is a safe guard against listeners that
17048            // could mutate the list by calling the various add/remove methods. This prevents
17049            // the array from being modified while we iterate it.
17050            for (OnAttachStateChangeListener listener : listeners) {
17051                listener.onViewAttachedToWindow(this);
17052            }
17053        }
17054
17055        int vis = info.mWindowVisibility;
17056        if (vis != GONE) {
17057            onWindowVisibilityChanged(vis);
17058            if (isShown()) {
17059                // Calling onVisibilityAggregated directly here since the subtree will also
17060                // receive dispatchAttachedToWindow and this same call
17061                onVisibilityAggregated(vis == VISIBLE);
17062            }
17063        }
17064
17065        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17066        // As all views in the subtree will already receive dispatchAttachedToWindow
17067        // traversing the subtree again here is not desired.
17068        onVisibilityChanged(this, visibility);
17069
17070        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17071            // If nobody has evaluated the drawable state yet, then do it now.
17072            refreshDrawableState();
17073        }
17074        needGlobalAttributesUpdate(false);
17075
17076        notifyEnterOrExitForAutoFillIfNeeded(true);
17077    }
17078
17079    void dispatchDetachedFromWindow() {
17080        AttachInfo info = mAttachInfo;
17081        if (info != null) {
17082            int vis = info.mWindowVisibility;
17083            if (vis != GONE) {
17084                onWindowVisibilityChanged(GONE);
17085                if (isShown()) {
17086                    // Invoking onVisibilityAggregated directly here since the subtree
17087                    // will also receive detached from window
17088                    onVisibilityAggregated(false);
17089                }
17090            }
17091        }
17092
17093        onDetachedFromWindow();
17094        onDetachedFromWindowInternal();
17095
17096        InputMethodManager imm = InputMethodManager.peekInstance();
17097        if (imm != null) {
17098            imm.onViewDetachedFromWindow(this);
17099        }
17100
17101        ListenerInfo li = mListenerInfo;
17102        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17103                li != null ? li.mOnAttachStateChangeListeners : null;
17104        if (listeners != null && listeners.size() > 0) {
17105            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17106            // perform the dispatching. The iterator is a safe guard against listeners that
17107            // could mutate the list by calling the various add/remove methods. This prevents
17108            // the array from being modified while we iterate it.
17109            for (OnAttachStateChangeListener listener : listeners) {
17110                listener.onViewDetachedFromWindow(this);
17111            }
17112        }
17113
17114        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17115            mAttachInfo.mScrollContainers.remove(this);
17116            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17117        }
17118
17119        mAttachInfo = null;
17120        if (mOverlay != null) {
17121            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17122        }
17123
17124        notifyEnterOrExitForAutoFillIfNeeded(false);
17125    }
17126
17127    /**
17128     * Cancel any deferred high-level input events that were previously posted to the event queue.
17129     *
17130     * <p>Many views post high-level events such as click handlers to the event queue
17131     * to run deferred in order to preserve a desired user experience - clearing visible
17132     * pressed states before executing, etc. This method will abort any events of this nature
17133     * that are currently in flight.</p>
17134     *
17135     * <p>Custom views that generate their own high-level deferred input events should override
17136     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17137     *
17138     * <p>This will also cancel pending input events for any child views.</p>
17139     *
17140     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17141     * This will not impact newer events posted after this call that may occur as a result of
17142     * lower-level input events still waiting in the queue. If you are trying to prevent
17143     * double-submitted  events for the duration of some sort of asynchronous transaction
17144     * you should also take other steps to protect against unexpected double inputs e.g. calling
17145     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17146     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17147     */
17148    public final void cancelPendingInputEvents() {
17149        dispatchCancelPendingInputEvents();
17150    }
17151
17152    /**
17153     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17154     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17155     */
17156    void dispatchCancelPendingInputEvents() {
17157        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17158        onCancelPendingInputEvents();
17159        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17160            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17161                    " did not call through to super.onCancelPendingInputEvents()");
17162        }
17163    }
17164
17165    /**
17166     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17167     * a parent view.
17168     *
17169     * <p>This method is responsible for removing any pending high-level input events that were
17170     * posted to the event queue to run later. Custom view classes that post their own deferred
17171     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17172     * {@link android.os.Handler} should override this method, call
17173     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17174     * </p>
17175     */
17176    public void onCancelPendingInputEvents() {
17177        removePerformClickCallback();
17178        cancelLongPress();
17179        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17180    }
17181
17182    /**
17183     * Store this view hierarchy's frozen state into the given container.
17184     *
17185     * @param container The SparseArray in which to save the view's state.
17186     *
17187     * @see #restoreHierarchyState(android.util.SparseArray)
17188     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17189     * @see #onSaveInstanceState()
17190     */
17191    public void saveHierarchyState(SparseArray<Parcelable> container) {
17192        dispatchSaveInstanceState(container);
17193    }
17194
17195    /**
17196     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17197     * this view and its children. May be overridden to modify how freezing happens to a
17198     * view's children; for example, some views may want to not store state for their children.
17199     *
17200     * @param container The SparseArray in which to save the view's state.
17201     *
17202     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17203     * @see #saveHierarchyState(android.util.SparseArray)
17204     * @see #onSaveInstanceState()
17205     */
17206    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17207        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17208            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17209            Parcelable state = onSaveInstanceState();
17210            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17211                throw new IllegalStateException(
17212                        "Derived class did not call super.onSaveInstanceState()");
17213            }
17214            if (state != null) {
17215                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17216                // + ": " + state);
17217                container.put(mID, state);
17218            }
17219        }
17220    }
17221
17222    /**
17223     * Hook allowing a view to generate a representation of its internal state
17224     * that can later be used to create a new instance with that same state.
17225     * This state should only contain information that is not persistent or can
17226     * not be reconstructed later. For example, you will never store your
17227     * current position on screen because that will be computed again when a
17228     * new instance of the view is placed in its view hierarchy.
17229     * <p>
17230     * Some examples of things you may store here: the current cursor position
17231     * in a text view (but usually not the text itself since that is stored in a
17232     * content provider or other persistent storage), the currently selected
17233     * item in a list view.
17234     *
17235     * @return Returns a Parcelable object containing the view's current dynamic
17236     *         state, or null if there is nothing interesting to save. The
17237     *         default implementation returns null.
17238     * @see #onRestoreInstanceState(android.os.Parcelable)
17239     * @see #saveHierarchyState(android.util.SparseArray)
17240     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17241     * @see #setSaveEnabled(boolean)
17242     */
17243    @CallSuper
17244    protected Parcelable onSaveInstanceState() {
17245        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17246        if (mStartActivityRequestWho != null || isAutofilled()
17247                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17248            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17249
17250            if (mStartActivityRequestWho != null) {
17251                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17252            }
17253
17254            if (isAutofilled()) {
17255                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17256            }
17257
17258            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17259                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17260            }
17261
17262            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17263            state.mIsAutofilled = isAutofilled();
17264            state.mAccessibilityViewId = mAccessibilityViewId;
17265            return state;
17266        }
17267        return BaseSavedState.EMPTY_STATE;
17268    }
17269
17270    /**
17271     * Restore this view hierarchy's frozen state from the given container.
17272     *
17273     * @param container The SparseArray which holds previously frozen states.
17274     *
17275     * @see #saveHierarchyState(android.util.SparseArray)
17276     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17277     * @see #onRestoreInstanceState(android.os.Parcelable)
17278     */
17279    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17280        dispatchRestoreInstanceState(container);
17281    }
17282
17283    /**
17284     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17285     * state for this view and its children. May be overridden to modify how restoring
17286     * happens to a view's children; for example, some views may want to not store state
17287     * for their children.
17288     *
17289     * @param container The SparseArray which holds previously saved state.
17290     *
17291     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17292     * @see #restoreHierarchyState(android.util.SparseArray)
17293     * @see #onRestoreInstanceState(android.os.Parcelable)
17294     */
17295    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17296        if (mID != NO_ID) {
17297            Parcelable state = container.get(mID);
17298            if (state != null) {
17299                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17300                // + ": " + state);
17301                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17302                onRestoreInstanceState(state);
17303                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17304                    throw new IllegalStateException(
17305                            "Derived class did not call super.onRestoreInstanceState()");
17306                }
17307            }
17308        }
17309    }
17310
17311    /**
17312     * Hook allowing a view to re-apply a representation of its internal state that had previously
17313     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17314     * null state.
17315     *
17316     * @param state The frozen state that had previously been returned by
17317     *        {@link #onSaveInstanceState}.
17318     *
17319     * @see #onSaveInstanceState()
17320     * @see #restoreHierarchyState(android.util.SparseArray)
17321     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17322     */
17323    @CallSuper
17324    protected void onRestoreInstanceState(Parcelable state) {
17325        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17326        if (state != null && !(state instanceof AbsSavedState)) {
17327            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17328                    + "received " + state.getClass().toString() + " instead. This usually happens "
17329                    + "when two views of different type have the same id in the same hierarchy. "
17330                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17331                    + "other views do not use the same id.");
17332        }
17333        if (state != null && state instanceof BaseSavedState) {
17334            BaseSavedState baseState = (BaseSavedState) state;
17335
17336            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17337                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17338            }
17339            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17340                setAutofilled(baseState.mIsAutofilled);
17341            }
17342            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17343                mAccessibilityViewId = baseState.mAccessibilityViewId;
17344            }
17345        }
17346    }
17347
17348    /**
17349     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17350     *
17351     * @return the drawing start time in milliseconds
17352     */
17353    public long getDrawingTime() {
17354        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17355    }
17356
17357    /**
17358     * <p>Enables or disables the duplication of the parent's state into this view. When
17359     * duplication is enabled, this view gets its drawable state from its parent rather
17360     * than from its own internal properties.</p>
17361     *
17362     * <p>Note: in the current implementation, setting this property to true after the
17363     * view was added to a ViewGroup might have no effect at all. This property should
17364     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17365     *
17366     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17367     * property is enabled, an exception will be thrown.</p>
17368     *
17369     * <p>Note: if the child view uses and updates additional states which are unknown to the
17370     * parent, these states should not be affected by this method.</p>
17371     *
17372     * @param enabled True to enable duplication of the parent's drawable state, false
17373     *                to disable it.
17374     *
17375     * @see #getDrawableState()
17376     * @see #isDuplicateParentStateEnabled()
17377     */
17378    public void setDuplicateParentStateEnabled(boolean enabled) {
17379        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17380    }
17381
17382    /**
17383     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17384     *
17385     * @return True if this view's drawable state is duplicated from the parent,
17386     *         false otherwise
17387     *
17388     * @see #getDrawableState()
17389     * @see #setDuplicateParentStateEnabled(boolean)
17390     */
17391    public boolean isDuplicateParentStateEnabled() {
17392        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17393    }
17394
17395    /**
17396     * <p>Specifies the type of layer backing this view. The layer can be
17397     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17398     * {@link #LAYER_TYPE_HARDWARE}.</p>
17399     *
17400     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17401     * instance that controls how the layer is composed on screen. The following
17402     * properties of the paint are taken into account when composing the layer:</p>
17403     * <ul>
17404     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17405     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17406     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17407     * </ul>
17408     *
17409     * <p>If this view has an alpha value set to < 1.0 by calling
17410     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17411     * by this view's alpha value.</p>
17412     *
17413     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17414     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17415     * for more information on when and how to use layers.</p>
17416     *
17417     * @param layerType The type of layer to use with this view, must be one of
17418     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17419     *        {@link #LAYER_TYPE_HARDWARE}
17420     * @param paint The paint used to compose the layer. This argument is optional
17421     *        and can be null. It is ignored when the layer type is
17422     *        {@link #LAYER_TYPE_NONE}
17423     *
17424     * @see #getLayerType()
17425     * @see #LAYER_TYPE_NONE
17426     * @see #LAYER_TYPE_SOFTWARE
17427     * @see #LAYER_TYPE_HARDWARE
17428     * @see #setAlpha(float)
17429     *
17430     * @attr ref android.R.styleable#View_layerType
17431     */
17432    public void setLayerType(int layerType, @Nullable Paint paint) {
17433        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17434            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17435                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17436        }
17437
17438        boolean typeChanged = mRenderNode.setLayerType(layerType);
17439
17440        if (!typeChanged) {
17441            setLayerPaint(paint);
17442            return;
17443        }
17444
17445        if (layerType != LAYER_TYPE_SOFTWARE) {
17446            // Destroy any previous software drawing cache if present
17447            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17448            // drawing cache created in View#draw when drawing to a SW canvas.
17449            destroyDrawingCache();
17450        }
17451
17452        mLayerType = layerType;
17453        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17454        mRenderNode.setLayerPaint(mLayerPaint);
17455
17456        // draw() behaves differently if we are on a layer, so we need to
17457        // invalidate() here
17458        invalidateParentCaches();
17459        invalidate(true);
17460    }
17461
17462    /**
17463     * Updates the {@link Paint} object used with the current layer (used only if the current
17464     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17465     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17466     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17467     * ensure that the view gets redrawn immediately.
17468     *
17469     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17470     * instance that controls how the layer is composed on screen. The following
17471     * properties of the paint are taken into account when composing the layer:</p>
17472     * <ul>
17473     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17474     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17475     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17476     * </ul>
17477     *
17478     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17479     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17480     *
17481     * @param paint The paint used to compose the layer. This argument is optional
17482     *        and can be null. It is ignored when the layer type is
17483     *        {@link #LAYER_TYPE_NONE}
17484     *
17485     * @see #setLayerType(int, android.graphics.Paint)
17486     */
17487    public void setLayerPaint(@Nullable Paint paint) {
17488        int layerType = getLayerType();
17489        if (layerType != LAYER_TYPE_NONE) {
17490            mLayerPaint = paint;
17491            if (layerType == LAYER_TYPE_HARDWARE) {
17492                if (mRenderNode.setLayerPaint(paint)) {
17493                    invalidateViewProperty(false, false);
17494                }
17495            } else {
17496                invalidate();
17497            }
17498        }
17499    }
17500
17501    /**
17502     * Indicates what type of layer is currently associated with this view. By default
17503     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17504     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17505     * for more information on the different types of layers.
17506     *
17507     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17508     *         {@link #LAYER_TYPE_HARDWARE}
17509     *
17510     * @see #setLayerType(int, android.graphics.Paint)
17511     * @see #buildLayer()
17512     * @see #LAYER_TYPE_NONE
17513     * @see #LAYER_TYPE_SOFTWARE
17514     * @see #LAYER_TYPE_HARDWARE
17515     */
17516    public int getLayerType() {
17517        return mLayerType;
17518    }
17519
17520    /**
17521     * Forces this view's layer to be created and this view to be rendered
17522     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17523     * invoking this method will have no effect.
17524     *
17525     * This method can for instance be used to render a view into its layer before
17526     * starting an animation. If this view is complex, rendering into the layer
17527     * before starting the animation will avoid skipping frames.
17528     *
17529     * @throws IllegalStateException If this view is not attached to a window
17530     *
17531     * @see #setLayerType(int, android.graphics.Paint)
17532     */
17533    public void buildLayer() {
17534        if (mLayerType == LAYER_TYPE_NONE) return;
17535
17536        final AttachInfo attachInfo = mAttachInfo;
17537        if (attachInfo == null) {
17538            throw new IllegalStateException("This view must be attached to a window first");
17539        }
17540
17541        if (getWidth() == 0 || getHeight() == 0) {
17542            return;
17543        }
17544
17545        switch (mLayerType) {
17546            case LAYER_TYPE_HARDWARE:
17547                updateDisplayListIfDirty();
17548                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17549                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17550                }
17551                break;
17552            case LAYER_TYPE_SOFTWARE:
17553                buildDrawingCache(true);
17554                break;
17555        }
17556    }
17557
17558    /**
17559     * Destroys all hardware rendering resources. This method is invoked
17560     * when the system needs to reclaim resources. Upon execution of this
17561     * method, you should free any OpenGL resources created by the view.
17562     *
17563     * Note: you <strong>must</strong> call
17564     * <code>super.destroyHardwareResources()</code> when overriding
17565     * this method.
17566     *
17567     * @hide
17568     */
17569    @CallSuper
17570    protected void destroyHardwareResources() {
17571        if (mOverlay != null) {
17572            mOverlay.getOverlayView().destroyHardwareResources();
17573        }
17574        if (mGhostView != null) {
17575            mGhostView.destroyHardwareResources();
17576        }
17577    }
17578
17579    /**
17580     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17581     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17582     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17583     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17584     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17585     * null.</p>
17586     *
17587     * <p>Enabling the drawing cache is similar to
17588     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17589     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17590     * drawing cache has no effect on rendering because the system uses a different mechanism
17591     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17592     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17593     * for information on how to enable software and hardware layers.</p>
17594     *
17595     * <p>This API can be used to manually generate
17596     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17597     * {@link #getDrawingCache()}.</p>
17598     *
17599     * @param enabled true to enable the drawing cache, false otherwise
17600     *
17601     * @see #isDrawingCacheEnabled()
17602     * @see #getDrawingCache()
17603     * @see #buildDrawingCache()
17604     * @see #setLayerType(int, android.graphics.Paint)
17605     */
17606    public void setDrawingCacheEnabled(boolean enabled) {
17607        mCachingFailed = false;
17608        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17609    }
17610
17611    /**
17612     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17613     *
17614     * @return true if the drawing cache is enabled
17615     *
17616     * @see #setDrawingCacheEnabled(boolean)
17617     * @see #getDrawingCache()
17618     */
17619    @ViewDebug.ExportedProperty(category = "drawing")
17620    public boolean isDrawingCacheEnabled() {
17621        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17622    }
17623
17624    /**
17625     * Debugging utility which recursively outputs the dirty state of a view and its
17626     * descendants.
17627     *
17628     * @hide
17629     */
17630    @SuppressWarnings({"UnusedDeclaration"})
17631    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17632        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17633                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17634                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17635                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17636        if (clear) {
17637            mPrivateFlags &= clearMask;
17638        }
17639        if (this instanceof ViewGroup) {
17640            ViewGroup parent = (ViewGroup) this;
17641            final int count = parent.getChildCount();
17642            for (int i = 0; i < count; i++) {
17643                final View child = parent.getChildAt(i);
17644                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17645            }
17646        }
17647    }
17648
17649    /**
17650     * This method is used by ViewGroup to cause its children to restore or recreate their
17651     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17652     * to recreate its own display list, which would happen if it went through the normal
17653     * draw/dispatchDraw mechanisms.
17654     *
17655     * @hide
17656     */
17657    protected void dispatchGetDisplayList() {}
17658
17659    /**
17660     * A view that is not attached or hardware accelerated cannot create a display list.
17661     * This method checks these conditions and returns the appropriate result.
17662     *
17663     * @return true if view has the ability to create a display list, false otherwise.
17664     *
17665     * @hide
17666     */
17667    public boolean canHaveDisplayList() {
17668        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17669    }
17670
17671    /**
17672     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17673     * @hide
17674     */
17675    @NonNull
17676    public RenderNode updateDisplayListIfDirty() {
17677        final RenderNode renderNode = mRenderNode;
17678        if (!canHaveDisplayList()) {
17679            // can't populate RenderNode, don't try
17680            return renderNode;
17681        }
17682
17683        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17684                || !renderNode.isValid()
17685                || (mRecreateDisplayList)) {
17686            // Don't need to recreate the display list, just need to tell our
17687            // children to restore/recreate theirs
17688            if (renderNode.isValid()
17689                    && !mRecreateDisplayList) {
17690                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17691                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17692                dispatchGetDisplayList();
17693
17694                return renderNode; // no work needed
17695            }
17696
17697            // If we got here, we're recreating it. Mark it as such to ensure that
17698            // we copy in child display lists into ours in drawChild()
17699            mRecreateDisplayList = true;
17700
17701            int width = mRight - mLeft;
17702            int height = mBottom - mTop;
17703            int layerType = getLayerType();
17704
17705            final DisplayListCanvas canvas = renderNode.start(width, height);
17706            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17707
17708            try {
17709                if (layerType == LAYER_TYPE_SOFTWARE) {
17710                    buildDrawingCache(true);
17711                    Bitmap cache = getDrawingCache(true);
17712                    if (cache != null) {
17713                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17714                    }
17715                } else {
17716                    computeScroll();
17717
17718                    canvas.translate(-mScrollX, -mScrollY);
17719                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17720                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17721
17722                    // Fast path for layouts with no backgrounds
17723                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17724                        dispatchDraw(canvas);
17725                        drawAutofilledHighlight(canvas);
17726                        if (mOverlay != null && !mOverlay.isEmpty()) {
17727                            mOverlay.getOverlayView().draw(canvas);
17728                        }
17729                        if (debugDraw()) {
17730                            debugDrawFocus(canvas);
17731                        }
17732                    } else {
17733                        draw(canvas);
17734                    }
17735                }
17736            } finally {
17737                renderNode.end(canvas);
17738                setDisplayListProperties(renderNode);
17739            }
17740        } else {
17741            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17742            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17743        }
17744        return renderNode;
17745    }
17746
17747    private void resetDisplayList() {
17748        mRenderNode.discardDisplayList();
17749        if (mBackgroundRenderNode != null) {
17750            mBackgroundRenderNode.discardDisplayList();
17751        }
17752    }
17753
17754    /**
17755     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17756     *
17757     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17758     *
17759     * @see #getDrawingCache(boolean)
17760     */
17761    public Bitmap getDrawingCache() {
17762        return getDrawingCache(false);
17763    }
17764
17765    /**
17766     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17767     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17768     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17769     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17770     * request the drawing cache by calling this method and draw it on screen if the
17771     * returned bitmap is not null.</p>
17772     *
17773     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17774     * this method will create a bitmap of the same size as this view. Because this bitmap
17775     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17776     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17777     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17778     * size than the view. This implies that your application must be able to handle this
17779     * size.</p>
17780     *
17781     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17782     *        the current density of the screen when the application is in compatibility
17783     *        mode.
17784     *
17785     * @return A bitmap representing this view or null if cache is disabled.
17786     *
17787     * @see #setDrawingCacheEnabled(boolean)
17788     * @see #isDrawingCacheEnabled()
17789     * @see #buildDrawingCache(boolean)
17790     * @see #destroyDrawingCache()
17791     */
17792    public Bitmap getDrawingCache(boolean autoScale) {
17793        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17794            return null;
17795        }
17796        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17797            buildDrawingCache(autoScale);
17798        }
17799        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17800    }
17801
17802    /**
17803     * <p>Frees the resources used by the drawing cache. If you call
17804     * {@link #buildDrawingCache()} manually without calling
17805     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17806     * should cleanup the cache with this method afterwards.</p>
17807     *
17808     * @see #setDrawingCacheEnabled(boolean)
17809     * @see #buildDrawingCache()
17810     * @see #getDrawingCache()
17811     */
17812    public void destroyDrawingCache() {
17813        if (mDrawingCache != null) {
17814            mDrawingCache.recycle();
17815            mDrawingCache = null;
17816        }
17817        if (mUnscaledDrawingCache != null) {
17818            mUnscaledDrawingCache.recycle();
17819            mUnscaledDrawingCache = null;
17820        }
17821    }
17822
17823    /**
17824     * Setting a solid background color for the drawing cache's bitmaps will improve
17825     * performance and memory usage. Note, though that this should only be used if this
17826     * view will always be drawn on top of a solid color.
17827     *
17828     * @param color The background color to use for the drawing cache's bitmap
17829     *
17830     * @see #setDrawingCacheEnabled(boolean)
17831     * @see #buildDrawingCache()
17832     * @see #getDrawingCache()
17833     */
17834    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17835        if (color != mDrawingCacheBackgroundColor) {
17836            mDrawingCacheBackgroundColor = color;
17837            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17838        }
17839    }
17840
17841    /**
17842     * @see #setDrawingCacheBackgroundColor(int)
17843     *
17844     * @return The background color to used for the drawing cache's bitmap
17845     */
17846    @ColorInt
17847    public int getDrawingCacheBackgroundColor() {
17848        return mDrawingCacheBackgroundColor;
17849    }
17850
17851    /**
17852     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17853     *
17854     * @see #buildDrawingCache(boolean)
17855     */
17856    public void buildDrawingCache() {
17857        buildDrawingCache(false);
17858    }
17859
17860    /**
17861     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17862     *
17863     * <p>If you call {@link #buildDrawingCache()} manually without calling
17864     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17865     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17866     *
17867     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17868     * this method will create a bitmap of the same size as this view. Because this bitmap
17869     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17870     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17871     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17872     * size than the view. This implies that your application must be able to handle this
17873     * size.</p>
17874     *
17875     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17876     * you do not need the drawing cache bitmap, calling this method will increase memory
17877     * usage and cause the view to be rendered in software once, thus negatively impacting
17878     * performance.</p>
17879     *
17880     * @see #getDrawingCache()
17881     * @see #destroyDrawingCache()
17882     */
17883    public void buildDrawingCache(boolean autoScale) {
17884        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17885                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17886            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17887                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17888                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17889            }
17890            try {
17891                buildDrawingCacheImpl(autoScale);
17892            } finally {
17893                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17894            }
17895        }
17896    }
17897
17898    /**
17899     * private, internal implementation of buildDrawingCache, used to enable tracing
17900     */
17901    private void buildDrawingCacheImpl(boolean autoScale) {
17902        mCachingFailed = false;
17903
17904        int width = mRight - mLeft;
17905        int height = mBottom - mTop;
17906
17907        final AttachInfo attachInfo = mAttachInfo;
17908        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17909
17910        if (autoScale && scalingRequired) {
17911            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17912            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17913        }
17914
17915        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17916        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17917        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17918
17919        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17920        final long drawingCacheSize =
17921                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17922        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17923            if (width > 0 && height > 0) {
17924                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17925                        + " too large to fit into a software layer (or drawing cache), needs "
17926                        + projectedBitmapSize + " bytes, only "
17927                        + drawingCacheSize + " available");
17928            }
17929            destroyDrawingCache();
17930            mCachingFailed = true;
17931            return;
17932        }
17933
17934        boolean clear = true;
17935        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17936
17937        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17938            Bitmap.Config quality;
17939            if (!opaque) {
17940                // Never pick ARGB_4444 because it looks awful
17941                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17942                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17943                    case DRAWING_CACHE_QUALITY_AUTO:
17944                    case DRAWING_CACHE_QUALITY_LOW:
17945                    case DRAWING_CACHE_QUALITY_HIGH:
17946                    default:
17947                        quality = Bitmap.Config.ARGB_8888;
17948                        break;
17949                }
17950            } else {
17951                // Optimization for translucent windows
17952                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17953                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17954            }
17955
17956            // Try to cleanup memory
17957            if (bitmap != null) bitmap.recycle();
17958
17959            try {
17960                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17961                        width, height, quality);
17962                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17963                if (autoScale) {
17964                    mDrawingCache = bitmap;
17965                } else {
17966                    mUnscaledDrawingCache = bitmap;
17967                }
17968                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17969            } catch (OutOfMemoryError e) {
17970                // If there is not enough memory to create the bitmap cache, just
17971                // ignore the issue as bitmap caches are not required to draw the
17972                // view hierarchy
17973                if (autoScale) {
17974                    mDrawingCache = null;
17975                } else {
17976                    mUnscaledDrawingCache = null;
17977                }
17978                mCachingFailed = true;
17979                return;
17980            }
17981
17982            clear = drawingCacheBackgroundColor != 0;
17983        }
17984
17985        Canvas canvas;
17986        if (attachInfo != null) {
17987            canvas = attachInfo.mCanvas;
17988            if (canvas == null) {
17989                canvas = new Canvas();
17990            }
17991            canvas.setBitmap(bitmap);
17992            // Temporarily clobber the cached Canvas in case one of our children
17993            // is also using a drawing cache. Without this, the children would
17994            // steal the canvas by attaching their own bitmap to it and bad, bad
17995            // thing would happen (invisible views, corrupted drawings, etc.)
17996            attachInfo.mCanvas = null;
17997        } else {
17998            // This case should hopefully never or seldom happen
17999            canvas = new Canvas(bitmap);
18000        }
18001
18002        if (clear) {
18003            bitmap.eraseColor(drawingCacheBackgroundColor);
18004        }
18005
18006        computeScroll();
18007        final int restoreCount = canvas.save();
18008
18009        if (autoScale && scalingRequired) {
18010            final float scale = attachInfo.mApplicationScale;
18011            canvas.scale(scale, scale);
18012        }
18013
18014        canvas.translate(-mScrollX, -mScrollY);
18015
18016        mPrivateFlags |= PFLAG_DRAWN;
18017        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18018                mLayerType != LAYER_TYPE_NONE) {
18019            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18020        }
18021
18022        // Fast path for layouts with no backgrounds
18023        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18024            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18025            dispatchDraw(canvas);
18026            drawAutofilledHighlight(canvas);
18027            if (mOverlay != null && !mOverlay.isEmpty()) {
18028                mOverlay.getOverlayView().draw(canvas);
18029            }
18030        } else {
18031            draw(canvas);
18032        }
18033
18034        canvas.restoreToCount(restoreCount);
18035        canvas.setBitmap(null);
18036
18037        if (attachInfo != null) {
18038            // Restore the cached Canvas for our siblings
18039            attachInfo.mCanvas = canvas;
18040        }
18041    }
18042
18043    /**
18044     * Create a snapshot of the view into a bitmap.  We should probably make
18045     * some form of this public, but should think about the API.
18046     *
18047     * @hide
18048     */
18049    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18050        int width = mRight - mLeft;
18051        int height = mBottom - mTop;
18052
18053        final AttachInfo attachInfo = mAttachInfo;
18054        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18055        width = (int) ((width * scale) + 0.5f);
18056        height = (int) ((height * scale) + 0.5f);
18057
18058        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18059                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18060        if (bitmap == null) {
18061            throw new OutOfMemoryError();
18062        }
18063
18064        Resources resources = getResources();
18065        if (resources != null) {
18066            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18067        }
18068
18069        Canvas canvas;
18070        if (attachInfo != null) {
18071            canvas = attachInfo.mCanvas;
18072            if (canvas == null) {
18073                canvas = new Canvas();
18074            }
18075            canvas.setBitmap(bitmap);
18076            // Temporarily clobber the cached Canvas in case one of our children
18077            // is also using a drawing cache. Without this, the children would
18078            // steal the canvas by attaching their own bitmap to it and bad, bad
18079            // things would happen (invisible views, corrupted drawings, etc.)
18080            attachInfo.mCanvas = null;
18081        } else {
18082            // This case should hopefully never or seldom happen
18083            canvas = new Canvas(bitmap);
18084        }
18085        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18086        canvas.setHwBitmapsInSwModeEnabled(true);
18087        if ((backgroundColor & 0xff000000) != 0) {
18088            bitmap.eraseColor(backgroundColor);
18089        }
18090
18091        computeScroll();
18092        final int restoreCount = canvas.save();
18093        canvas.scale(scale, scale);
18094        canvas.translate(-mScrollX, -mScrollY);
18095
18096        // Temporarily remove the dirty mask
18097        int flags = mPrivateFlags;
18098        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18099
18100        // Fast path for layouts with no backgrounds
18101        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18102            dispatchDraw(canvas);
18103            drawAutofilledHighlight(canvas);
18104            if (mOverlay != null && !mOverlay.isEmpty()) {
18105                mOverlay.getOverlayView().draw(canvas);
18106            }
18107        } else {
18108            draw(canvas);
18109        }
18110
18111        mPrivateFlags = flags;
18112
18113        canvas.restoreToCount(restoreCount);
18114        canvas.setBitmap(null);
18115        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18116
18117        if (attachInfo != null) {
18118            // Restore the cached Canvas for our siblings
18119            attachInfo.mCanvas = canvas;
18120        }
18121
18122        return bitmap;
18123    }
18124
18125    /**
18126     * Indicates whether this View is currently in edit mode. A View is usually
18127     * in edit mode when displayed within a developer tool. For instance, if
18128     * this View is being drawn by a visual user interface builder, this method
18129     * should return true.
18130     *
18131     * Subclasses should check the return value of this method to provide
18132     * different behaviors if their normal behavior might interfere with the
18133     * host environment. For instance: the class spawns a thread in its
18134     * constructor, the drawing code relies on device-specific features, etc.
18135     *
18136     * This method is usually checked in the drawing code of custom widgets.
18137     *
18138     * @return True if this View is in edit mode, false otherwise.
18139     */
18140    public boolean isInEditMode() {
18141        return false;
18142    }
18143
18144    /**
18145     * If the View draws content inside its padding and enables fading edges,
18146     * it needs to support padding offsets. Padding offsets are added to the
18147     * fading edges to extend the length of the fade so that it covers pixels
18148     * drawn inside the padding.
18149     *
18150     * Subclasses of this class should override this method if they need
18151     * to draw content inside the padding.
18152     *
18153     * @return True if padding offset must be applied, false otherwise.
18154     *
18155     * @see #getLeftPaddingOffset()
18156     * @see #getRightPaddingOffset()
18157     * @see #getTopPaddingOffset()
18158     * @see #getBottomPaddingOffset()
18159     *
18160     * @since CURRENT
18161     */
18162    protected boolean isPaddingOffsetRequired() {
18163        return false;
18164    }
18165
18166    /**
18167     * Amount by which to extend the left fading region. Called only when
18168     * {@link #isPaddingOffsetRequired()} returns true.
18169     *
18170     * @return The left padding offset in pixels.
18171     *
18172     * @see #isPaddingOffsetRequired()
18173     *
18174     * @since CURRENT
18175     */
18176    protected int getLeftPaddingOffset() {
18177        return 0;
18178    }
18179
18180    /**
18181     * Amount by which to extend the right fading region. Called only when
18182     * {@link #isPaddingOffsetRequired()} returns true.
18183     *
18184     * @return The right padding offset in pixels.
18185     *
18186     * @see #isPaddingOffsetRequired()
18187     *
18188     * @since CURRENT
18189     */
18190    protected int getRightPaddingOffset() {
18191        return 0;
18192    }
18193
18194    /**
18195     * Amount by which to extend the top fading region. Called only when
18196     * {@link #isPaddingOffsetRequired()} returns true.
18197     *
18198     * @return The top padding offset in pixels.
18199     *
18200     * @see #isPaddingOffsetRequired()
18201     *
18202     * @since CURRENT
18203     */
18204    protected int getTopPaddingOffset() {
18205        return 0;
18206    }
18207
18208    /**
18209     * Amount by which to extend the bottom fading region. Called only when
18210     * {@link #isPaddingOffsetRequired()} returns true.
18211     *
18212     * @return The bottom padding offset in pixels.
18213     *
18214     * @see #isPaddingOffsetRequired()
18215     *
18216     * @since CURRENT
18217     */
18218    protected int getBottomPaddingOffset() {
18219        return 0;
18220    }
18221
18222    /**
18223     * @hide
18224     * @param offsetRequired
18225     */
18226    protected int getFadeTop(boolean offsetRequired) {
18227        int top = mPaddingTop;
18228        if (offsetRequired) top += getTopPaddingOffset();
18229        return top;
18230    }
18231
18232    /**
18233     * @hide
18234     * @param offsetRequired
18235     */
18236    protected int getFadeHeight(boolean offsetRequired) {
18237        int padding = mPaddingTop;
18238        if (offsetRequired) padding += getTopPaddingOffset();
18239        return mBottom - mTop - mPaddingBottom - padding;
18240    }
18241
18242    /**
18243     * <p>Indicates whether this view is attached to a hardware accelerated
18244     * window or not.</p>
18245     *
18246     * <p>Even if this method returns true, it does not mean that every call
18247     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18248     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18249     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18250     * window is hardware accelerated,
18251     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18252     * return false, and this method will return true.</p>
18253     *
18254     * @return True if the view is attached to a window and the window is
18255     *         hardware accelerated; false in any other case.
18256     */
18257    @ViewDebug.ExportedProperty(category = "drawing")
18258    public boolean isHardwareAccelerated() {
18259        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18260    }
18261
18262    /**
18263     * Sets a rectangular area on this view to which the view will be clipped
18264     * when it is drawn. Setting the value to null will remove the clip bounds
18265     * and the view will draw normally, using its full bounds.
18266     *
18267     * @param clipBounds The rectangular area, in the local coordinates of
18268     * this view, to which future drawing operations will be clipped.
18269     */
18270    public void setClipBounds(Rect clipBounds) {
18271        if (clipBounds == mClipBounds
18272                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18273            return;
18274        }
18275        if (clipBounds != null) {
18276            if (mClipBounds == null) {
18277                mClipBounds = new Rect(clipBounds);
18278            } else {
18279                mClipBounds.set(clipBounds);
18280            }
18281        } else {
18282            mClipBounds = null;
18283        }
18284        mRenderNode.setClipBounds(mClipBounds);
18285        invalidateViewProperty(false, false);
18286    }
18287
18288    /**
18289     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18290     *
18291     * @return A copy of the current clip bounds if clip bounds are set,
18292     * otherwise null.
18293     */
18294    public Rect getClipBounds() {
18295        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18296    }
18297
18298
18299    /**
18300     * Populates an output rectangle with the clip bounds of the view,
18301     * returning {@code true} if successful or {@code false} if the view's
18302     * clip bounds are {@code null}.
18303     *
18304     * @param outRect rectangle in which to place the clip bounds of the view
18305     * @return {@code true} if successful or {@code false} if the view's
18306     *         clip bounds are {@code null}
18307     */
18308    public boolean getClipBounds(Rect outRect) {
18309        if (mClipBounds != null) {
18310            outRect.set(mClipBounds);
18311            return true;
18312        }
18313        return false;
18314    }
18315
18316    /**
18317     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18318     * case of an active Animation being run on the view.
18319     */
18320    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18321            Animation a, boolean scalingRequired) {
18322        Transformation invalidationTransform;
18323        final int flags = parent.mGroupFlags;
18324        final boolean initialized = a.isInitialized();
18325        if (!initialized) {
18326            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18327            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18328            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18329            onAnimationStart();
18330        }
18331
18332        final Transformation t = parent.getChildTransformation();
18333        boolean more = a.getTransformation(drawingTime, t, 1f);
18334        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18335            if (parent.mInvalidationTransformation == null) {
18336                parent.mInvalidationTransformation = new Transformation();
18337            }
18338            invalidationTransform = parent.mInvalidationTransformation;
18339            a.getTransformation(drawingTime, invalidationTransform, 1f);
18340        } else {
18341            invalidationTransform = t;
18342        }
18343
18344        if (more) {
18345            if (!a.willChangeBounds()) {
18346                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18347                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18348                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18349                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18350                    // The child need to draw an animation, potentially offscreen, so
18351                    // make sure we do not cancel invalidate requests
18352                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18353                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18354                }
18355            } else {
18356                if (parent.mInvalidateRegion == null) {
18357                    parent.mInvalidateRegion = new RectF();
18358                }
18359                final RectF region = parent.mInvalidateRegion;
18360                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18361                        invalidationTransform);
18362
18363                // The child need to draw an animation, potentially offscreen, so
18364                // make sure we do not cancel invalidate requests
18365                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18366
18367                final int left = mLeft + (int) region.left;
18368                final int top = mTop + (int) region.top;
18369                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18370                        top + (int) (region.height() + .5f));
18371            }
18372        }
18373        return more;
18374    }
18375
18376    /**
18377     * This method is called by getDisplayList() when a display list is recorded for a View.
18378     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18379     */
18380    void setDisplayListProperties(RenderNode renderNode) {
18381        if (renderNode != null) {
18382            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18383            renderNode.setClipToBounds(mParent instanceof ViewGroup
18384                    && ((ViewGroup) mParent).getClipChildren());
18385
18386            float alpha = 1;
18387            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18388                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18389                ViewGroup parentVG = (ViewGroup) mParent;
18390                final Transformation t = parentVG.getChildTransformation();
18391                if (parentVG.getChildStaticTransformation(this, t)) {
18392                    final int transformType = t.getTransformationType();
18393                    if (transformType != Transformation.TYPE_IDENTITY) {
18394                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18395                            alpha = t.getAlpha();
18396                        }
18397                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18398                            renderNode.setStaticMatrix(t.getMatrix());
18399                        }
18400                    }
18401                }
18402            }
18403            if (mTransformationInfo != null) {
18404                alpha *= getFinalAlpha();
18405                if (alpha < 1) {
18406                    final int multipliedAlpha = (int) (255 * alpha);
18407                    if (onSetAlpha(multipliedAlpha)) {
18408                        alpha = 1;
18409                    }
18410                }
18411                renderNode.setAlpha(alpha);
18412            } else if (alpha < 1) {
18413                renderNode.setAlpha(alpha);
18414            }
18415        }
18416    }
18417
18418    /**
18419     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18420     *
18421     * This is where the View specializes rendering behavior based on layer type,
18422     * and hardware acceleration.
18423     */
18424    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18425        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18426        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18427         *
18428         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18429         * HW accelerated, it can't handle drawing RenderNodes.
18430         */
18431        boolean drawingWithRenderNode = mAttachInfo != null
18432                && mAttachInfo.mHardwareAccelerated
18433                && hardwareAcceleratedCanvas;
18434
18435        boolean more = false;
18436        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18437        final int parentFlags = parent.mGroupFlags;
18438
18439        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18440            parent.getChildTransformation().clear();
18441            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18442        }
18443
18444        Transformation transformToApply = null;
18445        boolean concatMatrix = false;
18446        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18447        final Animation a = getAnimation();
18448        if (a != null) {
18449            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18450            concatMatrix = a.willChangeTransformationMatrix();
18451            if (concatMatrix) {
18452                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18453            }
18454            transformToApply = parent.getChildTransformation();
18455        } else {
18456            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18457                // No longer animating: clear out old animation matrix
18458                mRenderNode.setAnimationMatrix(null);
18459                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18460            }
18461            if (!drawingWithRenderNode
18462                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18463                final Transformation t = parent.getChildTransformation();
18464                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18465                if (hasTransform) {
18466                    final int transformType = t.getTransformationType();
18467                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18468                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18469                }
18470            }
18471        }
18472
18473        concatMatrix |= !childHasIdentityMatrix;
18474
18475        // Sets the flag as early as possible to allow draw() implementations
18476        // to call invalidate() successfully when doing animations
18477        mPrivateFlags |= PFLAG_DRAWN;
18478
18479        if (!concatMatrix &&
18480                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18481                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18482                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18483                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18484            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18485            return more;
18486        }
18487        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18488
18489        if (hardwareAcceleratedCanvas) {
18490            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18491            // retain the flag's value temporarily in the mRecreateDisplayList flag
18492            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18493            mPrivateFlags &= ~PFLAG_INVALIDATED;
18494        }
18495
18496        RenderNode renderNode = null;
18497        Bitmap cache = null;
18498        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18499        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18500             if (layerType != LAYER_TYPE_NONE) {
18501                 // If not drawing with RenderNode, treat HW layers as SW
18502                 layerType = LAYER_TYPE_SOFTWARE;
18503                 buildDrawingCache(true);
18504            }
18505            cache = getDrawingCache(true);
18506        }
18507
18508        if (drawingWithRenderNode) {
18509            // Delay getting the display list until animation-driven alpha values are
18510            // set up and possibly passed on to the view
18511            renderNode = updateDisplayListIfDirty();
18512            if (!renderNode.isValid()) {
18513                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18514                // to getDisplayList(), the display list will be marked invalid and we should not
18515                // try to use it again.
18516                renderNode = null;
18517                drawingWithRenderNode = false;
18518            }
18519        }
18520
18521        int sx = 0;
18522        int sy = 0;
18523        if (!drawingWithRenderNode) {
18524            computeScroll();
18525            sx = mScrollX;
18526            sy = mScrollY;
18527        }
18528
18529        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18530        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18531
18532        int restoreTo = -1;
18533        if (!drawingWithRenderNode || transformToApply != null) {
18534            restoreTo = canvas.save();
18535        }
18536        if (offsetForScroll) {
18537            canvas.translate(mLeft - sx, mTop - sy);
18538        } else {
18539            if (!drawingWithRenderNode) {
18540                canvas.translate(mLeft, mTop);
18541            }
18542            if (scalingRequired) {
18543                if (drawingWithRenderNode) {
18544                    // TODO: Might not need this if we put everything inside the DL
18545                    restoreTo = canvas.save();
18546                }
18547                // mAttachInfo cannot be null, otherwise scalingRequired == false
18548                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18549                canvas.scale(scale, scale);
18550            }
18551        }
18552
18553        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18554        if (transformToApply != null
18555                || alpha < 1
18556                || !hasIdentityMatrix()
18557                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18558            if (transformToApply != null || !childHasIdentityMatrix) {
18559                int transX = 0;
18560                int transY = 0;
18561
18562                if (offsetForScroll) {
18563                    transX = -sx;
18564                    transY = -sy;
18565                }
18566
18567                if (transformToApply != null) {
18568                    if (concatMatrix) {
18569                        if (drawingWithRenderNode) {
18570                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18571                        } else {
18572                            // Undo the scroll translation, apply the transformation matrix,
18573                            // then redo the scroll translate to get the correct result.
18574                            canvas.translate(-transX, -transY);
18575                            canvas.concat(transformToApply.getMatrix());
18576                            canvas.translate(transX, transY);
18577                        }
18578                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18579                    }
18580
18581                    float transformAlpha = transformToApply.getAlpha();
18582                    if (transformAlpha < 1) {
18583                        alpha *= transformAlpha;
18584                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18585                    }
18586                }
18587
18588                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18589                    canvas.translate(-transX, -transY);
18590                    canvas.concat(getMatrix());
18591                    canvas.translate(transX, transY);
18592                }
18593            }
18594
18595            // Deal with alpha if it is or used to be <1
18596            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18597                if (alpha < 1) {
18598                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18599                } else {
18600                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18601                }
18602                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18603                if (!drawingWithDrawingCache) {
18604                    final int multipliedAlpha = (int) (255 * alpha);
18605                    if (!onSetAlpha(multipliedAlpha)) {
18606                        if (drawingWithRenderNode) {
18607                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18608                        } else if (layerType == LAYER_TYPE_NONE) {
18609                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18610                                    multipliedAlpha);
18611                        }
18612                    } else {
18613                        // Alpha is handled by the child directly, clobber the layer's alpha
18614                        mPrivateFlags |= PFLAG_ALPHA_SET;
18615                    }
18616                }
18617            }
18618        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18619            onSetAlpha(255);
18620            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18621        }
18622
18623        if (!drawingWithRenderNode) {
18624            // apply clips directly, since RenderNode won't do it for this draw
18625            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18626                if (offsetForScroll) {
18627                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18628                } else {
18629                    if (!scalingRequired || cache == null) {
18630                        canvas.clipRect(0, 0, getWidth(), getHeight());
18631                    } else {
18632                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18633                    }
18634                }
18635            }
18636
18637            if (mClipBounds != null) {
18638                // clip bounds ignore scroll
18639                canvas.clipRect(mClipBounds);
18640            }
18641        }
18642
18643        if (!drawingWithDrawingCache) {
18644            if (drawingWithRenderNode) {
18645                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18646                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18647            } else {
18648                // Fast path for layouts with no backgrounds
18649                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18650                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18651                    dispatchDraw(canvas);
18652                } else {
18653                    draw(canvas);
18654                }
18655            }
18656        } else if (cache != null) {
18657            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18658            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18659                // no layer paint, use temporary paint to draw bitmap
18660                Paint cachePaint = parent.mCachePaint;
18661                if (cachePaint == null) {
18662                    cachePaint = new Paint();
18663                    cachePaint.setDither(false);
18664                    parent.mCachePaint = cachePaint;
18665                }
18666                cachePaint.setAlpha((int) (alpha * 255));
18667                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18668            } else {
18669                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18670                int layerPaintAlpha = mLayerPaint.getAlpha();
18671                if (alpha < 1) {
18672                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18673                }
18674                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18675                if (alpha < 1) {
18676                    mLayerPaint.setAlpha(layerPaintAlpha);
18677                }
18678            }
18679        }
18680
18681        if (restoreTo >= 0) {
18682            canvas.restoreToCount(restoreTo);
18683        }
18684
18685        if (a != null && !more) {
18686            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18687                onSetAlpha(255);
18688            }
18689            parent.finishAnimatingView(this, a);
18690        }
18691
18692        if (more && hardwareAcceleratedCanvas) {
18693            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18694                // alpha animations should cause the child to recreate its display list
18695                invalidate(true);
18696            }
18697        }
18698
18699        mRecreateDisplayList = false;
18700
18701        return more;
18702    }
18703
18704    static Paint getDebugPaint() {
18705        if (sDebugPaint == null) {
18706            sDebugPaint = new Paint();
18707            sDebugPaint.setAntiAlias(false);
18708        }
18709        return sDebugPaint;
18710    }
18711
18712    final int dipsToPixels(int dips) {
18713        float scale = getContext().getResources().getDisplayMetrics().density;
18714        return (int) (dips * scale + 0.5f);
18715    }
18716
18717    final private void debugDrawFocus(Canvas canvas) {
18718        if (isFocused()) {
18719            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18720            final int l = mScrollX;
18721            final int r = l + mRight - mLeft;
18722            final int t = mScrollY;
18723            final int b = t + mBottom - mTop;
18724
18725            final Paint paint = getDebugPaint();
18726            paint.setColor(DEBUG_CORNERS_COLOR);
18727
18728            // Draw squares in corners.
18729            paint.setStyle(Paint.Style.FILL);
18730            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18731            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18732            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18733            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18734
18735            // Draw big X across the view.
18736            paint.setStyle(Paint.Style.STROKE);
18737            canvas.drawLine(l, t, r, b, paint);
18738            canvas.drawLine(l, b, r, t, paint);
18739        }
18740    }
18741
18742    /**
18743     * Manually render this view (and all of its children) to the given Canvas.
18744     * The view must have already done a full layout before this function is
18745     * called.  When implementing a view, implement
18746     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18747     * If you do need to override this method, call the superclass version.
18748     *
18749     * @param canvas The Canvas to which the View is rendered.
18750     */
18751    @CallSuper
18752    public void draw(Canvas canvas) {
18753        final int privateFlags = mPrivateFlags;
18754        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18755                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18756        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18757
18758        /*
18759         * Draw traversal performs several drawing steps which must be executed
18760         * in the appropriate order:
18761         *
18762         *      1. Draw the background
18763         *      2. If necessary, save the canvas' layers to prepare for fading
18764         *      3. Draw view's content
18765         *      4. Draw children
18766         *      5. If necessary, draw the fading edges and restore layers
18767         *      6. Draw decorations (scrollbars for instance)
18768         */
18769
18770        // Step 1, draw the background, if needed
18771        int saveCount;
18772
18773        if (!dirtyOpaque) {
18774            drawBackground(canvas);
18775        }
18776
18777        // skip step 2 & 5 if possible (common case)
18778        final int viewFlags = mViewFlags;
18779        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18780        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18781        if (!verticalEdges && !horizontalEdges) {
18782            // Step 3, draw the content
18783            if (!dirtyOpaque) onDraw(canvas);
18784
18785            // Step 4, draw the children
18786            dispatchDraw(canvas);
18787
18788            drawAutofilledHighlight(canvas);
18789
18790            // Overlay is part of the content and draws beneath Foreground
18791            if (mOverlay != null && !mOverlay.isEmpty()) {
18792                mOverlay.getOverlayView().dispatchDraw(canvas);
18793            }
18794
18795            // Step 6, draw decorations (foreground, scrollbars)
18796            onDrawForeground(canvas);
18797
18798            // Step 7, draw the default focus highlight
18799            drawDefaultFocusHighlight(canvas);
18800
18801            if (debugDraw()) {
18802                debugDrawFocus(canvas);
18803            }
18804
18805            // we're done...
18806            return;
18807        }
18808
18809        /*
18810         * Here we do the full fledged routine...
18811         * (this is an uncommon case where speed matters less,
18812         * this is why we repeat some of the tests that have been
18813         * done above)
18814         */
18815
18816        boolean drawTop = false;
18817        boolean drawBottom = false;
18818        boolean drawLeft = false;
18819        boolean drawRight = false;
18820
18821        float topFadeStrength = 0.0f;
18822        float bottomFadeStrength = 0.0f;
18823        float leftFadeStrength = 0.0f;
18824        float rightFadeStrength = 0.0f;
18825
18826        // Step 2, save the canvas' layers
18827        int paddingLeft = mPaddingLeft;
18828
18829        final boolean offsetRequired = isPaddingOffsetRequired();
18830        if (offsetRequired) {
18831            paddingLeft += getLeftPaddingOffset();
18832        }
18833
18834        int left = mScrollX + paddingLeft;
18835        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18836        int top = mScrollY + getFadeTop(offsetRequired);
18837        int bottom = top + getFadeHeight(offsetRequired);
18838
18839        if (offsetRequired) {
18840            right += getRightPaddingOffset();
18841            bottom += getBottomPaddingOffset();
18842        }
18843
18844        final ScrollabilityCache scrollabilityCache = mScrollCache;
18845        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18846        int length = (int) fadeHeight;
18847
18848        // clip the fade length if top and bottom fades overlap
18849        // overlapping fades produce odd-looking artifacts
18850        if (verticalEdges && (top + length > bottom - length)) {
18851            length = (bottom - top) / 2;
18852        }
18853
18854        // also clip horizontal fades if necessary
18855        if (horizontalEdges && (left + length > right - length)) {
18856            length = (right - left) / 2;
18857        }
18858
18859        if (verticalEdges) {
18860            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18861            drawTop = topFadeStrength * fadeHeight > 1.0f;
18862            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18863            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18864        }
18865
18866        if (horizontalEdges) {
18867            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18868            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18869            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18870            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18871        }
18872
18873        saveCount = canvas.getSaveCount();
18874
18875        int solidColor = getSolidColor();
18876        if (solidColor == 0) {
18877            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18878
18879            if (drawTop) {
18880                canvas.saveLayer(left, top, right, top + length, null, flags);
18881            }
18882
18883            if (drawBottom) {
18884                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18885            }
18886
18887            if (drawLeft) {
18888                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18889            }
18890
18891            if (drawRight) {
18892                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18893            }
18894        } else {
18895            scrollabilityCache.setFadeColor(solidColor);
18896        }
18897
18898        // Step 3, draw the content
18899        if (!dirtyOpaque) onDraw(canvas);
18900
18901        // Step 4, draw the children
18902        dispatchDraw(canvas);
18903
18904        // Step 5, draw the fade effect and restore layers
18905        final Paint p = scrollabilityCache.paint;
18906        final Matrix matrix = scrollabilityCache.matrix;
18907        final Shader fade = scrollabilityCache.shader;
18908
18909        if (drawTop) {
18910            matrix.setScale(1, fadeHeight * topFadeStrength);
18911            matrix.postTranslate(left, top);
18912            fade.setLocalMatrix(matrix);
18913            p.setShader(fade);
18914            canvas.drawRect(left, top, right, top + length, p);
18915        }
18916
18917        if (drawBottom) {
18918            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18919            matrix.postRotate(180);
18920            matrix.postTranslate(left, bottom);
18921            fade.setLocalMatrix(matrix);
18922            p.setShader(fade);
18923            canvas.drawRect(left, bottom - length, right, bottom, p);
18924        }
18925
18926        if (drawLeft) {
18927            matrix.setScale(1, fadeHeight * leftFadeStrength);
18928            matrix.postRotate(-90);
18929            matrix.postTranslate(left, top);
18930            fade.setLocalMatrix(matrix);
18931            p.setShader(fade);
18932            canvas.drawRect(left, top, left + length, bottom, p);
18933        }
18934
18935        if (drawRight) {
18936            matrix.setScale(1, fadeHeight * rightFadeStrength);
18937            matrix.postRotate(90);
18938            matrix.postTranslate(right, top);
18939            fade.setLocalMatrix(matrix);
18940            p.setShader(fade);
18941            canvas.drawRect(right - length, top, right, bottom, p);
18942        }
18943
18944        canvas.restoreToCount(saveCount);
18945
18946        drawAutofilledHighlight(canvas);
18947
18948        // Overlay is part of the content and draws beneath Foreground
18949        if (mOverlay != null && !mOverlay.isEmpty()) {
18950            mOverlay.getOverlayView().dispatchDraw(canvas);
18951        }
18952
18953        // Step 6, draw decorations (foreground, scrollbars)
18954        onDrawForeground(canvas);
18955
18956        if (debugDraw()) {
18957            debugDrawFocus(canvas);
18958        }
18959    }
18960
18961    /**
18962     * Draws the background onto the specified canvas.
18963     *
18964     * @param canvas Canvas on which to draw the background
18965     */
18966    private void drawBackground(Canvas canvas) {
18967        final Drawable background = mBackground;
18968        if (background == null) {
18969            return;
18970        }
18971
18972        setBackgroundBounds();
18973
18974        // Attempt to use a display list if requested.
18975        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18976                && mAttachInfo.mThreadedRenderer != null) {
18977            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18978
18979            final RenderNode renderNode = mBackgroundRenderNode;
18980            if (renderNode != null && renderNode.isValid()) {
18981                setBackgroundRenderNodeProperties(renderNode);
18982                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18983                return;
18984            }
18985        }
18986
18987        final int scrollX = mScrollX;
18988        final int scrollY = mScrollY;
18989        if ((scrollX | scrollY) == 0) {
18990            background.draw(canvas);
18991        } else {
18992            canvas.translate(scrollX, scrollY);
18993            background.draw(canvas);
18994            canvas.translate(-scrollX, -scrollY);
18995        }
18996    }
18997
18998    /**
18999     * Sets the correct background bounds and rebuilds the outline, if needed.
19000     * <p/>
19001     * This is called by LayoutLib.
19002     */
19003    void setBackgroundBounds() {
19004        if (mBackgroundSizeChanged && mBackground != null) {
19005            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19006            mBackgroundSizeChanged = false;
19007            rebuildOutline();
19008        }
19009    }
19010
19011    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19012        renderNode.setTranslationX(mScrollX);
19013        renderNode.setTranslationY(mScrollY);
19014    }
19015
19016    /**
19017     * Creates a new display list or updates the existing display list for the
19018     * specified Drawable.
19019     *
19020     * @param drawable Drawable for which to create a display list
19021     * @param renderNode Existing RenderNode, or {@code null}
19022     * @return A valid display list for the specified drawable
19023     */
19024    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19025        if (renderNode == null) {
19026            renderNode = RenderNode.create(drawable.getClass().getName(), this);
19027        }
19028
19029        final Rect bounds = drawable.getBounds();
19030        final int width = bounds.width();
19031        final int height = bounds.height();
19032        final DisplayListCanvas canvas = renderNode.start(width, height);
19033
19034        // Reverse left/top translation done by drawable canvas, which will
19035        // instead be applied by rendernode's LTRB bounds below. This way, the
19036        // drawable's bounds match with its rendernode bounds and its content
19037        // will lie within those bounds in the rendernode tree.
19038        canvas.translate(-bounds.left, -bounds.top);
19039
19040        try {
19041            drawable.draw(canvas);
19042        } finally {
19043            renderNode.end(canvas);
19044        }
19045
19046        // Set up drawable properties that are view-independent.
19047        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19048        renderNode.setProjectBackwards(drawable.isProjected());
19049        renderNode.setProjectionReceiver(true);
19050        renderNode.setClipToBounds(false);
19051        return renderNode;
19052    }
19053
19054    /**
19055     * Returns the overlay for this view, creating it if it does not yet exist.
19056     * Adding drawables to the overlay will cause them to be displayed whenever
19057     * the view itself is redrawn. Objects in the overlay should be actively
19058     * managed: remove them when they should not be displayed anymore. The
19059     * overlay will always have the same size as its host view.
19060     *
19061     * <p>Note: Overlays do not currently work correctly with {@link
19062     * SurfaceView} or {@link TextureView}; contents in overlays for these
19063     * types of views may not display correctly.</p>
19064     *
19065     * @return The ViewOverlay object for this view.
19066     * @see ViewOverlay
19067     */
19068    public ViewOverlay getOverlay() {
19069        if (mOverlay == null) {
19070            mOverlay = new ViewOverlay(mContext, this);
19071        }
19072        return mOverlay;
19073    }
19074
19075    /**
19076     * Override this if your view is known to always be drawn on top of a solid color background,
19077     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19078     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19079     * should be set to 0xFF.
19080     *
19081     * @see #setVerticalFadingEdgeEnabled(boolean)
19082     * @see #setHorizontalFadingEdgeEnabled(boolean)
19083     *
19084     * @return The known solid color background for this view, or 0 if the color may vary
19085     */
19086    @ViewDebug.ExportedProperty(category = "drawing")
19087    @ColorInt
19088    public int getSolidColor() {
19089        return 0;
19090    }
19091
19092    /**
19093     * Build a human readable string representation of the specified view flags.
19094     *
19095     * @param flags the view flags to convert to a string
19096     * @return a String representing the supplied flags
19097     */
19098    private static String printFlags(int flags) {
19099        String output = "";
19100        int numFlags = 0;
19101        if ((flags & FOCUSABLE) == FOCUSABLE) {
19102            output += "TAKES_FOCUS";
19103            numFlags++;
19104        }
19105
19106        switch (flags & VISIBILITY_MASK) {
19107        case INVISIBLE:
19108            if (numFlags > 0) {
19109                output += " ";
19110            }
19111            output += "INVISIBLE";
19112            // USELESS HERE numFlags++;
19113            break;
19114        case GONE:
19115            if (numFlags > 0) {
19116                output += " ";
19117            }
19118            output += "GONE";
19119            // USELESS HERE numFlags++;
19120            break;
19121        default:
19122            break;
19123        }
19124        return output;
19125    }
19126
19127    /**
19128     * Build a human readable string representation of the specified private
19129     * view flags.
19130     *
19131     * @param privateFlags the private view flags to convert to a string
19132     * @return a String representing the supplied flags
19133     */
19134    private static String printPrivateFlags(int privateFlags) {
19135        String output = "";
19136        int numFlags = 0;
19137
19138        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19139            output += "WANTS_FOCUS";
19140            numFlags++;
19141        }
19142
19143        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19144            if (numFlags > 0) {
19145                output += " ";
19146            }
19147            output += "FOCUSED";
19148            numFlags++;
19149        }
19150
19151        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19152            if (numFlags > 0) {
19153                output += " ";
19154            }
19155            output += "SELECTED";
19156            numFlags++;
19157        }
19158
19159        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19160            if (numFlags > 0) {
19161                output += " ";
19162            }
19163            output += "IS_ROOT_NAMESPACE";
19164            numFlags++;
19165        }
19166
19167        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19168            if (numFlags > 0) {
19169                output += " ";
19170            }
19171            output += "HAS_BOUNDS";
19172            numFlags++;
19173        }
19174
19175        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19176            if (numFlags > 0) {
19177                output += " ";
19178            }
19179            output += "DRAWN";
19180            // USELESS HERE numFlags++;
19181        }
19182        return output;
19183    }
19184
19185    /**
19186     * <p>Indicates whether or not this view's layout will be requested during
19187     * the next hierarchy layout pass.</p>
19188     *
19189     * @return true if the layout will be forced during next layout pass
19190     */
19191    public boolean isLayoutRequested() {
19192        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19193    }
19194
19195    /**
19196     * Return true if o is a ViewGroup that is laying out using optical bounds.
19197     * @hide
19198     */
19199    public static boolean isLayoutModeOptical(Object o) {
19200        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19201    }
19202
19203    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19204        Insets parentInsets = mParent instanceof View ?
19205                ((View) mParent).getOpticalInsets() : Insets.NONE;
19206        Insets childInsets = getOpticalInsets();
19207        return setFrame(
19208                left   + parentInsets.left - childInsets.left,
19209                top    + parentInsets.top  - childInsets.top,
19210                right  + parentInsets.left + childInsets.right,
19211                bottom + parentInsets.top  + childInsets.bottom);
19212    }
19213
19214    /**
19215     * Assign a size and position to a view and all of its
19216     * descendants
19217     *
19218     * <p>This is the second phase of the layout mechanism.
19219     * (The first is measuring). In this phase, each parent calls
19220     * layout on all of its children to position them.
19221     * This is typically done using the child measurements
19222     * that were stored in the measure pass().</p>
19223     *
19224     * <p>Derived classes should not override this method.
19225     * Derived classes with children should override
19226     * onLayout. In that method, they should
19227     * call layout on each of their children.</p>
19228     *
19229     * @param l Left position, relative to parent
19230     * @param t Top position, relative to parent
19231     * @param r Right position, relative to parent
19232     * @param b Bottom position, relative to parent
19233     */
19234    @SuppressWarnings({"unchecked"})
19235    public void layout(int l, int t, int r, int b) {
19236        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19237            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19238            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19239        }
19240
19241        int oldL = mLeft;
19242        int oldT = mTop;
19243        int oldB = mBottom;
19244        int oldR = mRight;
19245
19246        boolean changed = isLayoutModeOptical(mParent) ?
19247                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19248
19249        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19250            onLayout(changed, l, t, r, b);
19251
19252            if (shouldDrawRoundScrollbar()) {
19253                if(mRoundScrollbarRenderer == null) {
19254                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19255                }
19256            } else {
19257                mRoundScrollbarRenderer = null;
19258            }
19259
19260            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19261
19262            ListenerInfo li = mListenerInfo;
19263            if (li != null && li.mOnLayoutChangeListeners != null) {
19264                ArrayList<OnLayoutChangeListener> listenersCopy =
19265                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19266                int numListeners = listenersCopy.size();
19267                for (int i = 0; i < numListeners; ++i) {
19268                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19269                }
19270            }
19271        }
19272
19273        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19274        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19275    }
19276
19277    /**
19278     * Called from layout when this view should
19279     * assign a size and position to each of its children.
19280     *
19281     * Derived classes with children should override
19282     * this method and call layout on each of
19283     * their children.
19284     * @param changed This is a new size or position for this view
19285     * @param left Left position, relative to parent
19286     * @param top Top position, relative to parent
19287     * @param right Right position, relative to parent
19288     * @param bottom Bottom position, relative to parent
19289     */
19290    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19291    }
19292
19293    /**
19294     * Assign a size and position to this view.
19295     *
19296     * This is called from layout.
19297     *
19298     * @param left Left position, relative to parent
19299     * @param top Top position, relative to parent
19300     * @param right Right position, relative to parent
19301     * @param bottom Bottom position, relative to parent
19302     * @return true if the new size and position are different than the
19303     *         previous ones
19304     * {@hide}
19305     */
19306    protected boolean setFrame(int left, int top, int right, int bottom) {
19307        boolean changed = false;
19308
19309        if (DBG) {
19310            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19311                    + right + "," + bottom + ")");
19312        }
19313
19314        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19315            changed = true;
19316
19317            // Remember our drawn bit
19318            int drawn = mPrivateFlags & PFLAG_DRAWN;
19319
19320            int oldWidth = mRight - mLeft;
19321            int oldHeight = mBottom - mTop;
19322            int newWidth = right - left;
19323            int newHeight = bottom - top;
19324            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19325
19326            // Invalidate our old position
19327            invalidate(sizeChanged);
19328
19329            mLeft = left;
19330            mTop = top;
19331            mRight = right;
19332            mBottom = bottom;
19333            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19334
19335            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19336
19337
19338            if (sizeChanged) {
19339                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19340            }
19341
19342            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19343                // If we are visible, force the DRAWN bit to on so that
19344                // this invalidate will go through (at least to our parent).
19345                // This is because someone may have invalidated this view
19346                // before this call to setFrame came in, thereby clearing
19347                // the DRAWN bit.
19348                mPrivateFlags |= PFLAG_DRAWN;
19349                invalidate(sizeChanged);
19350                // parent display list may need to be recreated based on a change in the bounds
19351                // of any child
19352                invalidateParentCaches();
19353            }
19354
19355            // Reset drawn bit to original value (invalidate turns it off)
19356            mPrivateFlags |= drawn;
19357
19358            mBackgroundSizeChanged = true;
19359            mDefaultFocusHighlightSizeChanged = true;
19360            if (mForegroundInfo != null) {
19361                mForegroundInfo.mBoundsChanged = true;
19362            }
19363
19364            notifySubtreeAccessibilityStateChangedIfNeeded();
19365        }
19366        return changed;
19367    }
19368
19369    /**
19370     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19371     * @hide
19372     */
19373    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19374        setFrame(left, top, right, bottom);
19375    }
19376
19377    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19378        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19379        if (mOverlay != null) {
19380            mOverlay.getOverlayView().setRight(newWidth);
19381            mOverlay.getOverlayView().setBottom(newHeight);
19382        }
19383        rebuildOutline();
19384    }
19385
19386    /**
19387     * Finalize inflating a view from XML.  This is called as the last phase
19388     * of inflation, after all child views have been added.
19389     *
19390     * <p>Even if the subclass overrides onFinishInflate, they should always be
19391     * sure to call the super method, so that we get called.
19392     */
19393    @CallSuper
19394    protected void onFinishInflate() {
19395    }
19396
19397    /**
19398     * Returns the resources associated with this view.
19399     *
19400     * @return Resources object.
19401     */
19402    public Resources getResources() {
19403        return mResources;
19404    }
19405
19406    /**
19407     * Invalidates the specified Drawable.
19408     *
19409     * @param drawable the drawable to invalidate
19410     */
19411    @Override
19412    public void invalidateDrawable(@NonNull Drawable drawable) {
19413        if (verifyDrawable(drawable)) {
19414            final Rect dirty = drawable.getDirtyBounds();
19415            final int scrollX = mScrollX;
19416            final int scrollY = mScrollY;
19417
19418            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19419                    dirty.right + scrollX, dirty.bottom + scrollY);
19420            rebuildOutline();
19421        }
19422    }
19423
19424    /**
19425     * Schedules an action on a drawable to occur at a specified time.
19426     *
19427     * @param who the recipient of the action
19428     * @param what the action to run on the drawable
19429     * @param when the time at which the action must occur. Uses the
19430     *        {@link SystemClock#uptimeMillis} timebase.
19431     */
19432    @Override
19433    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19434        if (verifyDrawable(who) && what != null) {
19435            final long delay = when - SystemClock.uptimeMillis();
19436            if (mAttachInfo != null) {
19437                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19438                        Choreographer.CALLBACK_ANIMATION, what, who,
19439                        Choreographer.subtractFrameDelay(delay));
19440            } else {
19441                // Postpone the runnable until we know
19442                // on which thread it needs to run.
19443                getRunQueue().postDelayed(what, delay);
19444            }
19445        }
19446    }
19447
19448    /**
19449     * Cancels a scheduled action on a drawable.
19450     *
19451     * @param who the recipient of the action
19452     * @param what the action to cancel
19453     */
19454    @Override
19455    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19456        if (verifyDrawable(who) && what != null) {
19457            if (mAttachInfo != null) {
19458                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19459                        Choreographer.CALLBACK_ANIMATION, what, who);
19460            }
19461            getRunQueue().removeCallbacks(what);
19462        }
19463    }
19464
19465    /**
19466     * Unschedule any events associated with the given Drawable.  This can be
19467     * used when selecting a new Drawable into a view, so that the previous
19468     * one is completely unscheduled.
19469     *
19470     * @param who The Drawable to unschedule.
19471     *
19472     * @see #drawableStateChanged
19473     */
19474    public void unscheduleDrawable(Drawable who) {
19475        if (mAttachInfo != null && who != null) {
19476            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19477                    Choreographer.CALLBACK_ANIMATION, null, who);
19478        }
19479    }
19480
19481    /**
19482     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19483     * that the View directionality can and will be resolved before its Drawables.
19484     *
19485     * Will call {@link View#onResolveDrawables} when resolution is done.
19486     *
19487     * @hide
19488     */
19489    protected void resolveDrawables() {
19490        // Drawables resolution may need to happen before resolving the layout direction (which is
19491        // done only during the measure() call).
19492        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19493        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19494        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19495        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19496        // direction to be resolved as its resolved value will be the same as its raw value.
19497        if (!isLayoutDirectionResolved() &&
19498                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19499            return;
19500        }
19501
19502        final int layoutDirection = isLayoutDirectionResolved() ?
19503                getLayoutDirection() : getRawLayoutDirection();
19504
19505        if (mBackground != null) {
19506            mBackground.setLayoutDirection(layoutDirection);
19507        }
19508        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19509            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19510        }
19511        if (mDefaultFocusHighlight != null) {
19512            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19513        }
19514        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19515        onResolveDrawables(layoutDirection);
19516    }
19517
19518    boolean areDrawablesResolved() {
19519        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19520    }
19521
19522    /**
19523     * Called when layout direction has been resolved.
19524     *
19525     * The default implementation does nothing.
19526     *
19527     * @param layoutDirection The resolved layout direction.
19528     *
19529     * @see #LAYOUT_DIRECTION_LTR
19530     * @see #LAYOUT_DIRECTION_RTL
19531     *
19532     * @hide
19533     */
19534    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19535    }
19536
19537    /**
19538     * @hide
19539     */
19540    protected void resetResolvedDrawables() {
19541        resetResolvedDrawablesInternal();
19542    }
19543
19544    void resetResolvedDrawablesInternal() {
19545        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19546    }
19547
19548    /**
19549     * If your view subclass is displaying its own Drawable objects, it should
19550     * override this function and return true for any Drawable it is
19551     * displaying.  This allows animations for those drawables to be
19552     * scheduled.
19553     *
19554     * <p>Be sure to call through to the super class when overriding this
19555     * function.
19556     *
19557     * @param who The Drawable to verify.  Return true if it is one you are
19558     *            displaying, else return the result of calling through to the
19559     *            super class.
19560     *
19561     * @return boolean If true than the Drawable is being displayed in the
19562     *         view; else false and it is not allowed to animate.
19563     *
19564     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19565     * @see #drawableStateChanged()
19566     */
19567    @CallSuper
19568    protected boolean verifyDrawable(@NonNull Drawable who) {
19569        // Avoid verifying the scroll bar drawable so that we don't end up in
19570        // an invalidation loop. This effectively prevents the scroll bar
19571        // drawable from triggering invalidations and scheduling runnables.
19572        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19573                || (mDefaultFocusHighlight == who);
19574    }
19575
19576    /**
19577     * This function is called whenever the state of the view changes in such
19578     * a way that it impacts the state of drawables being shown.
19579     * <p>
19580     * If the View has a StateListAnimator, it will also be called to run necessary state
19581     * change animations.
19582     * <p>
19583     * Be sure to call through to the superclass when overriding this function.
19584     *
19585     * @see Drawable#setState(int[])
19586     */
19587    @CallSuper
19588    protected void drawableStateChanged() {
19589        final int[] state = getDrawableState();
19590        boolean changed = false;
19591
19592        final Drawable bg = mBackground;
19593        if (bg != null && bg.isStateful()) {
19594            changed |= bg.setState(state);
19595        }
19596
19597        final Drawable hl = mDefaultFocusHighlight;
19598        if (hl != null && hl.isStateful()) {
19599            changed |= hl.setState(state);
19600        }
19601
19602        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19603        if (fg != null && fg.isStateful()) {
19604            changed |= fg.setState(state);
19605        }
19606
19607        if (mScrollCache != null) {
19608            final Drawable scrollBar = mScrollCache.scrollBar;
19609            if (scrollBar != null && scrollBar.isStateful()) {
19610                changed |= scrollBar.setState(state)
19611                        && mScrollCache.state != ScrollabilityCache.OFF;
19612            }
19613        }
19614
19615        if (mStateListAnimator != null) {
19616            mStateListAnimator.setState(state);
19617        }
19618
19619        if (changed) {
19620            invalidate();
19621        }
19622    }
19623
19624    /**
19625     * This function is called whenever the view hotspot changes and needs to
19626     * be propagated to drawables or child views managed by the view.
19627     * <p>
19628     * Dispatching to child views is handled by
19629     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19630     * <p>
19631     * Be sure to call through to the superclass when overriding this function.
19632     *
19633     * @param x hotspot x coordinate
19634     * @param y hotspot y coordinate
19635     */
19636    @CallSuper
19637    public void drawableHotspotChanged(float x, float y) {
19638        if (mBackground != null) {
19639            mBackground.setHotspot(x, y);
19640        }
19641        if (mDefaultFocusHighlight != null) {
19642            mDefaultFocusHighlight.setHotspot(x, y);
19643        }
19644        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19645            mForegroundInfo.mDrawable.setHotspot(x, y);
19646        }
19647
19648        dispatchDrawableHotspotChanged(x, y);
19649    }
19650
19651    /**
19652     * Dispatches drawableHotspotChanged to all of this View's children.
19653     *
19654     * @param x hotspot x coordinate
19655     * @param y hotspot y coordinate
19656     * @see #drawableHotspotChanged(float, float)
19657     */
19658    public void dispatchDrawableHotspotChanged(float x, float y) {
19659    }
19660
19661    /**
19662     * Call this to force a view to update its drawable state. This will cause
19663     * drawableStateChanged to be called on this view. Views that are interested
19664     * in the new state should call getDrawableState.
19665     *
19666     * @see #drawableStateChanged
19667     * @see #getDrawableState
19668     */
19669    public void refreshDrawableState() {
19670        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19671        drawableStateChanged();
19672
19673        ViewParent parent = mParent;
19674        if (parent != null) {
19675            parent.childDrawableStateChanged(this);
19676        }
19677    }
19678
19679    /**
19680     * Create a default focus highlight if it doesn't exist.
19681     * @return a default focus highlight.
19682     */
19683    private Drawable getDefaultFocusHighlightDrawable() {
19684        if (mDefaultFocusHighlightCache == null) {
19685            if (mContext != null) {
19686                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
19687                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
19688                mDefaultFocusHighlightCache = ta.getDrawable(0);
19689                ta.recycle();
19690            }
19691        }
19692        return mDefaultFocusHighlightCache;
19693    }
19694
19695    /**
19696     * Set the current default focus highlight.
19697     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
19698     */
19699    private void setDefaultFocusHighlight(Drawable highlight) {
19700        mDefaultFocusHighlight = highlight;
19701        mDefaultFocusHighlightSizeChanged = true;
19702        if (highlight != null) {
19703            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19704                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19705            }
19706            highlight.setLayoutDirection(getLayoutDirection());
19707            if (highlight.isStateful()) {
19708                highlight.setState(getDrawableState());
19709            }
19710            if (isAttachedToWindow()) {
19711                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19712            }
19713            // Set callback last, since the view may still be initializing.
19714            highlight.setCallback(this);
19715        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
19716                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19717            mPrivateFlags |= PFLAG_SKIP_DRAW;
19718        }
19719        requestLayout();
19720        invalidate();
19721    }
19722
19723    /**
19724     * Check whether we need to draw a default focus highlight when this view gets focused,
19725     * which requires:
19726     * <ul>
19727     *     <li>In the background, {@link android.R.attr#state_focused} is not defined.</li>
19728     *     <li>This view is not in touch mode.</li>
19729     *     <li>This view doesn't opt out for a default focus highlight, via
19730     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
19731     *     <li>This view is attached to window.</li>
19732     * </ul>
19733     * @return {@code true} if a default focus highlight is needed.
19734     */
19735    private boolean isDefaultFocusHighlightNeeded(Drawable background) {
19736        final boolean hasFocusStateSpecified = background == null || !background.isStateful()
19737                || !background.hasFocusStateSpecified();
19738        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
19739                && isAttachedToWindow() && sUseDefaultFocusHighlight;
19740    }
19741
19742    /**
19743     * When this view is focused, switches on/off the default focused highlight.
19744     * <p>
19745     * This always happens when this view is focused, and only at this moment the default focus
19746     * highlight can be visible.
19747     */
19748    private void switchDefaultFocusHighlight() {
19749        if (isFocused()) {
19750            final boolean needed = isDefaultFocusHighlightNeeded(mBackground);
19751            final boolean active = mDefaultFocusHighlight != null;
19752            if (needed && !active) {
19753                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
19754            } else if (!needed && active) {
19755                // The highlight is no longer needed, so tear it down.
19756                setDefaultFocusHighlight(null);
19757            }
19758        }
19759    }
19760
19761    /**
19762     * Draw the default focus highlight onto the canvas.
19763     * @param canvas the canvas where we're drawing the highlight.
19764     */
19765    private void drawDefaultFocusHighlight(Canvas canvas) {
19766        if (mDefaultFocusHighlight != null) {
19767            if (mDefaultFocusHighlightSizeChanged) {
19768                mDefaultFocusHighlightSizeChanged = false;
19769                final int l = mScrollX;
19770                final int r = l + mRight - mLeft;
19771                final int t = mScrollY;
19772                final int b = t + mBottom - mTop;
19773                mDefaultFocusHighlight.setBounds(l, t, r, b);
19774            }
19775            mDefaultFocusHighlight.draw(canvas);
19776        }
19777    }
19778
19779    /**
19780     * Return an array of resource IDs of the drawable states representing the
19781     * current state of the view.
19782     *
19783     * @return The current drawable state
19784     *
19785     * @see Drawable#setState(int[])
19786     * @see #drawableStateChanged()
19787     * @see #onCreateDrawableState(int)
19788     */
19789    public final int[] getDrawableState() {
19790        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19791            return mDrawableState;
19792        } else {
19793            mDrawableState = onCreateDrawableState(0);
19794            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19795            return mDrawableState;
19796        }
19797    }
19798
19799    /**
19800     * Generate the new {@link android.graphics.drawable.Drawable} state for
19801     * this view. This is called by the view
19802     * system when the cached Drawable state is determined to be invalid.  To
19803     * retrieve the current state, you should use {@link #getDrawableState}.
19804     *
19805     * @param extraSpace if non-zero, this is the number of extra entries you
19806     * would like in the returned array in which you can place your own
19807     * states.
19808     *
19809     * @return Returns an array holding the current {@link Drawable} state of
19810     * the view.
19811     *
19812     * @see #mergeDrawableStates(int[], int[])
19813     */
19814    protected int[] onCreateDrawableState(int extraSpace) {
19815        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19816                mParent instanceof View) {
19817            return ((View) mParent).onCreateDrawableState(extraSpace);
19818        }
19819
19820        int[] drawableState;
19821
19822        int privateFlags = mPrivateFlags;
19823
19824        int viewStateIndex = 0;
19825        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19826        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19827        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19828        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19829        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19830        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19831        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19832                ThreadedRenderer.isAvailable()) {
19833            // This is set if HW acceleration is requested, even if the current
19834            // process doesn't allow it.  This is just to allow app preview
19835            // windows to better match their app.
19836            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19837        }
19838        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19839
19840        final int privateFlags2 = mPrivateFlags2;
19841        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19842            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19843        }
19844        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19845            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19846        }
19847
19848        drawableState = StateSet.get(viewStateIndex);
19849
19850        //noinspection ConstantIfStatement
19851        if (false) {
19852            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19853            Log.i("View", toString()
19854                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19855                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19856                    + " fo=" + hasFocus()
19857                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19858                    + " wf=" + hasWindowFocus()
19859                    + ": " + Arrays.toString(drawableState));
19860        }
19861
19862        if (extraSpace == 0) {
19863            return drawableState;
19864        }
19865
19866        final int[] fullState;
19867        if (drawableState != null) {
19868            fullState = new int[drawableState.length + extraSpace];
19869            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19870        } else {
19871            fullState = new int[extraSpace];
19872        }
19873
19874        return fullState;
19875    }
19876
19877    /**
19878     * Merge your own state values in <var>additionalState</var> into the base
19879     * state values <var>baseState</var> that were returned by
19880     * {@link #onCreateDrawableState(int)}.
19881     *
19882     * @param baseState The base state values returned by
19883     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19884     * own additional state values.
19885     *
19886     * @param additionalState The additional state values you would like
19887     * added to <var>baseState</var>; this array is not modified.
19888     *
19889     * @return As a convenience, the <var>baseState</var> array you originally
19890     * passed into the function is returned.
19891     *
19892     * @see #onCreateDrawableState(int)
19893     */
19894    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19895        final int N = baseState.length;
19896        int i = N - 1;
19897        while (i >= 0 && baseState[i] == 0) {
19898            i--;
19899        }
19900        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19901        return baseState;
19902    }
19903
19904    /**
19905     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19906     * on all Drawable objects associated with this view.
19907     * <p>
19908     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19909     * attached to this view.
19910     */
19911    @CallSuper
19912    public void jumpDrawablesToCurrentState() {
19913        if (mBackground != null) {
19914            mBackground.jumpToCurrentState();
19915        }
19916        if (mStateListAnimator != null) {
19917            mStateListAnimator.jumpToCurrentState();
19918        }
19919        if (mDefaultFocusHighlight != null) {
19920            mDefaultFocusHighlight.jumpToCurrentState();
19921        }
19922        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19923            mForegroundInfo.mDrawable.jumpToCurrentState();
19924        }
19925    }
19926
19927    /**
19928     * Sets the background color for this view.
19929     * @param color the color of the background
19930     */
19931    @RemotableViewMethod
19932    public void setBackgroundColor(@ColorInt int color) {
19933        if (mBackground instanceof ColorDrawable) {
19934            ((ColorDrawable) mBackground.mutate()).setColor(color);
19935            computeOpaqueFlags();
19936            mBackgroundResource = 0;
19937        } else {
19938            setBackground(new ColorDrawable(color));
19939        }
19940    }
19941
19942    /**
19943     * Set the background to a given resource. The resource should refer to
19944     * a Drawable object or 0 to remove the background.
19945     * @param resid The identifier of the resource.
19946     *
19947     * @attr ref android.R.styleable#View_background
19948     */
19949    @RemotableViewMethod
19950    public void setBackgroundResource(@DrawableRes int resid) {
19951        if (resid != 0 && resid == mBackgroundResource) {
19952            return;
19953        }
19954
19955        Drawable d = null;
19956        if (resid != 0) {
19957            d = mContext.getDrawable(resid);
19958        }
19959        setBackground(d);
19960
19961        mBackgroundResource = resid;
19962    }
19963
19964    /**
19965     * Set the background to a given Drawable, or remove the background. If the
19966     * background has padding, this View's padding is set to the background's
19967     * padding. However, when a background is removed, this View's padding isn't
19968     * touched. If setting the padding is desired, please use
19969     * {@link #setPadding(int, int, int, int)}.
19970     *
19971     * @param background The Drawable to use as the background, or null to remove the
19972     *        background
19973     */
19974    public void setBackground(Drawable background) {
19975        //noinspection deprecation
19976        setBackgroundDrawable(background);
19977    }
19978
19979    /**
19980     * @deprecated use {@link #setBackground(Drawable)} instead
19981     */
19982    @Deprecated
19983    public void setBackgroundDrawable(Drawable background) {
19984        computeOpaqueFlags();
19985
19986        if (background == mBackground) {
19987            return;
19988        }
19989
19990        boolean requestLayout = false;
19991
19992        mBackgroundResource = 0;
19993
19994        /*
19995         * Regardless of whether we're setting a new background or not, we want
19996         * to clear the previous drawable. setVisible first while we still have the callback set.
19997         */
19998        if (mBackground != null) {
19999            if (isAttachedToWindow()) {
20000                mBackground.setVisible(false, false);
20001            }
20002            mBackground.setCallback(null);
20003            unscheduleDrawable(mBackground);
20004        }
20005
20006        if (background != null) {
20007            Rect padding = sThreadLocal.get();
20008            if (padding == null) {
20009                padding = new Rect();
20010                sThreadLocal.set(padding);
20011            }
20012            resetResolvedDrawablesInternal();
20013            background.setLayoutDirection(getLayoutDirection());
20014            if (background.getPadding(padding)) {
20015                resetResolvedPaddingInternal();
20016                switch (background.getLayoutDirection()) {
20017                    case LAYOUT_DIRECTION_RTL:
20018                        mUserPaddingLeftInitial = padding.right;
20019                        mUserPaddingRightInitial = padding.left;
20020                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20021                        break;
20022                    case LAYOUT_DIRECTION_LTR:
20023                    default:
20024                        mUserPaddingLeftInitial = padding.left;
20025                        mUserPaddingRightInitial = padding.right;
20026                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20027                }
20028                mLeftPaddingDefined = false;
20029                mRightPaddingDefined = false;
20030            }
20031
20032            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20033            // if it has a different minimum size, we should layout again
20034            if (mBackground == null
20035                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
20036                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20037                requestLayout = true;
20038            }
20039
20040            // Set mBackground before we set this as the callback and start making other
20041            // background drawable state change calls. In particular, the setVisible call below
20042            // can result in drawables attempting to start animations or otherwise invalidate,
20043            // which requires the view set as the callback (us) to recognize the drawable as
20044            // belonging to it as per verifyDrawable.
20045            mBackground = background;
20046            if (background.isStateful()) {
20047                background.setState(getDrawableState());
20048            }
20049            if (isAttachedToWindow()) {
20050                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20051            }
20052
20053            applyBackgroundTint();
20054
20055            // Set callback last, since the view may still be initializing.
20056            background.setCallback(this);
20057
20058            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20059                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20060                requestLayout = true;
20061            }
20062        } else {
20063            /* Remove the background */
20064            mBackground = null;
20065            if ((mViewFlags & WILL_NOT_DRAW) != 0
20066                    && (mDefaultFocusHighlight == null)
20067                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20068                mPrivateFlags |= PFLAG_SKIP_DRAW;
20069            }
20070
20071            /*
20072             * When the background is set, we try to apply its padding to this
20073             * View. When the background is removed, we don't touch this View's
20074             * padding. This is noted in the Javadocs. Hence, we don't need to
20075             * requestLayout(), the invalidate() below is sufficient.
20076             */
20077
20078            // The old background's minimum size could have affected this
20079            // View's layout, so let's requestLayout
20080            requestLayout = true;
20081        }
20082
20083        computeOpaqueFlags();
20084
20085        if (requestLayout) {
20086            requestLayout();
20087        }
20088
20089        mBackgroundSizeChanged = true;
20090        invalidate(true);
20091        invalidateOutline();
20092    }
20093
20094    /**
20095     * Gets the background drawable
20096     *
20097     * @return The drawable used as the background for this view, if any.
20098     *
20099     * @see #setBackground(Drawable)
20100     *
20101     * @attr ref android.R.styleable#View_background
20102     */
20103    public Drawable getBackground() {
20104        return mBackground;
20105    }
20106
20107    /**
20108     * Applies a tint to the background drawable. Does not modify the current tint
20109     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20110     * <p>
20111     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20112     * mutate the drawable and apply the specified tint and tint mode using
20113     * {@link Drawable#setTintList(ColorStateList)}.
20114     *
20115     * @param tint the tint to apply, may be {@code null} to clear tint
20116     *
20117     * @attr ref android.R.styleable#View_backgroundTint
20118     * @see #getBackgroundTintList()
20119     * @see Drawable#setTintList(ColorStateList)
20120     */
20121    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20122        if (mBackgroundTint == null) {
20123            mBackgroundTint = new TintInfo();
20124        }
20125        mBackgroundTint.mTintList = tint;
20126        mBackgroundTint.mHasTintList = true;
20127
20128        applyBackgroundTint();
20129    }
20130
20131    /**
20132     * Return the tint applied to the background drawable, if specified.
20133     *
20134     * @return the tint applied to the background drawable
20135     * @attr ref android.R.styleable#View_backgroundTint
20136     * @see #setBackgroundTintList(ColorStateList)
20137     */
20138    @Nullable
20139    public ColorStateList getBackgroundTintList() {
20140        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20141    }
20142
20143    /**
20144     * Specifies the blending mode used to apply the tint specified by
20145     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20146     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20147     *
20148     * @param tintMode the blending mode used to apply the tint, may be
20149     *                 {@code null} to clear tint
20150     * @attr ref android.R.styleable#View_backgroundTintMode
20151     * @see #getBackgroundTintMode()
20152     * @see Drawable#setTintMode(PorterDuff.Mode)
20153     */
20154    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20155        if (mBackgroundTint == null) {
20156            mBackgroundTint = new TintInfo();
20157        }
20158        mBackgroundTint.mTintMode = tintMode;
20159        mBackgroundTint.mHasTintMode = true;
20160
20161        applyBackgroundTint();
20162    }
20163
20164    /**
20165     * Return the blending mode used to apply the tint to the background
20166     * drawable, if specified.
20167     *
20168     * @return the blending mode used to apply the tint to the background
20169     *         drawable
20170     * @attr ref android.R.styleable#View_backgroundTintMode
20171     * @see #setBackgroundTintMode(PorterDuff.Mode)
20172     */
20173    @Nullable
20174    public PorterDuff.Mode getBackgroundTintMode() {
20175        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20176    }
20177
20178    private void applyBackgroundTint() {
20179        if (mBackground != null && mBackgroundTint != null) {
20180            final TintInfo tintInfo = mBackgroundTint;
20181            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20182                mBackground = mBackground.mutate();
20183
20184                if (tintInfo.mHasTintList) {
20185                    mBackground.setTintList(tintInfo.mTintList);
20186                }
20187
20188                if (tintInfo.mHasTintMode) {
20189                    mBackground.setTintMode(tintInfo.mTintMode);
20190                }
20191
20192                // The drawable (or one of its children) may not have been
20193                // stateful before applying the tint, so let's try again.
20194                if (mBackground.isStateful()) {
20195                    mBackground.setState(getDrawableState());
20196                }
20197            }
20198        }
20199    }
20200
20201    /**
20202     * Returns the drawable used as the foreground of this View. The
20203     * foreground drawable, if non-null, is always drawn on top of the view's content.
20204     *
20205     * @return a Drawable or null if no foreground was set
20206     *
20207     * @see #onDrawForeground(Canvas)
20208     */
20209    public Drawable getForeground() {
20210        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20211    }
20212
20213    /**
20214     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20215     *
20216     * @param foreground the Drawable to be drawn on top of the children
20217     *
20218     * @attr ref android.R.styleable#View_foreground
20219     */
20220    public void setForeground(Drawable foreground) {
20221        if (mForegroundInfo == null) {
20222            if (foreground == null) {
20223                // Nothing to do.
20224                return;
20225            }
20226            mForegroundInfo = new ForegroundInfo();
20227        }
20228
20229        if (foreground == mForegroundInfo.mDrawable) {
20230            // Nothing to do
20231            return;
20232        }
20233
20234        if (mForegroundInfo.mDrawable != null) {
20235            if (isAttachedToWindow()) {
20236                mForegroundInfo.mDrawable.setVisible(false, false);
20237            }
20238            mForegroundInfo.mDrawable.setCallback(null);
20239            unscheduleDrawable(mForegroundInfo.mDrawable);
20240        }
20241
20242        mForegroundInfo.mDrawable = foreground;
20243        mForegroundInfo.mBoundsChanged = true;
20244        if (foreground != null) {
20245            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20246                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20247            }
20248            foreground.setLayoutDirection(getLayoutDirection());
20249            if (foreground.isStateful()) {
20250                foreground.setState(getDrawableState());
20251            }
20252            applyForegroundTint();
20253            if (isAttachedToWindow()) {
20254                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20255            }
20256            // Set callback last, since the view may still be initializing.
20257            foreground.setCallback(this);
20258        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20259                && (mDefaultFocusHighlight == null)) {
20260            mPrivateFlags |= PFLAG_SKIP_DRAW;
20261        }
20262        requestLayout();
20263        invalidate();
20264    }
20265
20266    /**
20267     * Magic bit used to support features of framework-internal window decor implementation details.
20268     * This used to live exclusively in FrameLayout.
20269     *
20270     * @return true if the foreground should draw inside the padding region or false
20271     *         if it should draw inset by the view's padding
20272     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20273     */
20274    public boolean isForegroundInsidePadding() {
20275        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20276    }
20277
20278    /**
20279     * Describes how the foreground is positioned.
20280     *
20281     * @return foreground gravity.
20282     *
20283     * @see #setForegroundGravity(int)
20284     *
20285     * @attr ref android.R.styleable#View_foregroundGravity
20286     */
20287    public int getForegroundGravity() {
20288        return mForegroundInfo != null ? mForegroundInfo.mGravity
20289                : Gravity.START | Gravity.TOP;
20290    }
20291
20292    /**
20293     * Describes how the foreground is positioned. Defaults to START and TOP.
20294     *
20295     * @param gravity see {@link android.view.Gravity}
20296     *
20297     * @see #getForegroundGravity()
20298     *
20299     * @attr ref android.R.styleable#View_foregroundGravity
20300     */
20301    public void setForegroundGravity(int gravity) {
20302        if (mForegroundInfo == null) {
20303            mForegroundInfo = new ForegroundInfo();
20304        }
20305
20306        if (mForegroundInfo.mGravity != gravity) {
20307            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20308                gravity |= Gravity.START;
20309            }
20310
20311            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20312                gravity |= Gravity.TOP;
20313            }
20314
20315            mForegroundInfo.mGravity = gravity;
20316            requestLayout();
20317        }
20318    }
20319
20320    /**
20321     * Applies a tint to the foreground drawable. Does not modify the current tint
20322     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20323     * <p>
20324     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20325     * mutate the drawable and apply the specified tint and tint mode using
20326     * {@link Drawable#setTintList(ColorStateList)}.
20327     *
20328     * @param tint the tint to apply, may be {@code null} to clear tint
20329     *
20330     * @attr ref android.R.styleable#View_foregroundTint
20331     * @see #getForegroundTintList()
20332     * @see Drawable#setTintList(ColorStateList)
20333     */
20334    public void setForegroundTintList(@Nullable ColorStateList tint) {
20335        if (mForegroundInfo == null) {
20336            mForegroundInfo = new ForegroundInfo();
20337        }
20338        if (mForegroundInfo.mTintInfo == null) {
20339            mForegroundInfo.mTintInfo = new TintInfo();
20340        }
20341        mForegroundInfo.mTintInfo.mTintList = tint;
20342        mForegroundInfo.mTintInfo.mHasTintList = true;
20343
20344        applyForegroundTint();
20345    }
20346
20347    /**
20348     * Return the tint applied to the foreground drawable, if specified.
20349     *
20350     * @return the tint applied to the foreground drawable
20351     * @attr ref android.R.styleable#View_foregroundTint
20352     * @see #setForegroundTintList(ColorStateList)
20353     */
20354    @Nullable
20355    public ColorStateList getForegroundTintList() {
20356        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20357                ? mForegroundInfo.mTintInfo.mTintList : null;
20358    }
20359
20360    /**
20361     * Specifies the blending mode used to apply the tint specified by
20362     * {@link #setForegroundTintList(ColorStateList)}} to the background
20363     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20364     *
20365     * @param tintMode the blending mode used to apply the tint, may be
20366     *                 {@code null} to clear tint
20367     * @attr ref android.R.styleable#View_foregroundTintMode
20368     * @see #getForegroundTintMode()
20369     * @see Drawable#setTintMode(PorterDuff.Mode)
20370     */
20371    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20372        if (mForegroundInfo == null) {
20373            mForegroundInfo = new ForegroundInfo();
20374        }
20375        if (mForegroundInfo.mTintInfo == null) {
20376            mForegroundInfo.mTintInfo = new TintInfo();
20377        }
20378        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20379        mForegroundInfo.mTintInfo.mHasTintMode = true;
20380
20381        applyForegroundTint();
20382    }
20383
20384    /**
20385     * Return the blending mode used to apply the tint to the foreground
20386     * drawable, if specified.
20387     *
20388     * @return the blending mode used to apply the tint to the foreground
20389     *         drawable
20390     * @attr ref android.R.styleable#View_foregroundTintMode
20391     * @see #setForegroundTintMode(PorterDuff.Mode)
20392     */
20393    @Nullable
20394    public PorterDuff.Mode getForegroundTintMode() {
20395        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20396                ? mForegroundInfo.mTintInfo.mTintMode : null;
20397    }
20398
20399    private void applyForegroundTint() {
20400        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20401                && mForegroundInfo.mTintInfo != null) {
20402            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20403            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20404                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20405
20406                if (tintInfo.mHasTintList) {
20407                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20408                }
20409
20410                if (tintInfo.mHasTintMode) {
20411                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20412                }
20413
20414                // The drawable (or one of its children) may not have been
20415                // stateful before applying the tint, so let's try again.
20416                if (mForegroundInfo.mDrawable.isStateful()) {
20417                    mForegroundInfo.mDrawable.setState(getDrawableState());
20418                }
20419            }
20420        }
20421    }
20422
20423    /**
20424     * Get the drawable to be overlayed when a view is autofilled
20425     *
20426     * @return The drawable
20427     *
20428     * @throws IllegalStateException if the drawable could not be found.
20429     */
20430    @Nullable private Drawable getAutofilledDrawable() {
20431        // Lazily load the isAutofilled drawable.
20432        if (mAttachInfo.mAutofilledDrawable == null) {
20433            TypedArray a = mContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20434            int attributeResourceId = a.getResourceId(0, 0);
20435            mAttachInfo.mAutofilledDrawable = mContext.getDrawable(attributeResourceId);
20436            a.recycle();
20437        }
20438
20439        return mAttachInfo.mAutofilledDrawable;
20440    }
20441
20442    /**
20443     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20444     *
20445     * @param canvas The canvas to draw on
20446     */
20447    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20448        if (isAutofilled()) {
20449            Drawable autofilledHighlight = getAutofilledDrawable();
20450
20451            if (autofilledHighlight != null) {
20452                autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20453                autofilledHighlight.draw(canvas);
20454            }
20455        }
20456    }
20457
20458    /**
20459     * Draw any foreground content for this view.
20460     *
20461     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20462     * drawable or other view-specific decorations. The foreground is drawn on top of the
20463     * primary view content.</p>
20464     *
20465     * @param canvas canvas to draw into
20466     */
20467    public void onDrawForeground(Canvas canvas) {
20468        onDrawScrollIndicators(canvas);
20469        onDrawScrollBars(canvas);
20470
20471        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20472        if (foreground != null) {
20473            if (mForegroundInfo.mBoundsChanged) {
20474                mForegroundInfo.mBoundsChanged = false;
20475                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20476                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20477
20478                if (mForegroundInfo.mInsidePadding) {
20479                    selfBounds.set(0, 0, getWidth(), getHeight());
20480                } else {
20481                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20482                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20483                }
20484
20485                final int ld = getLayoutDirection();
20486                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20487                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20488                foreground.setBounds(overlayBounds);
20489            }
20490
20491            foreground.draw(canvas);
20492        }
20493    }
20494
20495    /**
20496     * Sets the padding. The view may add on the space required to display
20497     * the scrollbars, depending on the style and visibility of the scrollbars.
20498     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20499     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20500     * from the values set in this call.
20501     *
20502     * @attr ref android.R.styleable#View_padding
20503     * @attr ref android.R.styleable#View_paddingBottom
20504     * @attr ref android.R.styleable#View_paddingLeft
20505     * @attr ref android.R.styleable#View_paddingRight
20506     * @attr ref android.R.styleable#View_paddingTop
20507     * @param left the left padding in pixels
20508     * @param top the top padding in pixels
20509     * @param right the right padding in pixels
20510     * @param bottom the bottom padding in pixels
20511     */
20512    public void setPadding(int left, int top, int right, int bottom) {
20513        resetResolvedPaddingInternal();
20514
20515        mUserPaddingStart = UNDEFINED_PADDING;
20516        mUserPaddingEnd = UNDEFINED_PADDING;
20517
20518        mUserPaddingLeftInitial = left;
20519        mUserPaddingRightInitial = right;
20520
20521        mLeftPaddingDefined = true;
20522        mRightPaddingDefined = true;
20523
20524        internalSetPadding(left, top, right, bottom);
20525    }
20526
20527    /**
20528     * @hide
20529     */
20530    protected void internalSetPadding(int left, int top, int right, int bottom) {
20531        mUserPaddingLeft = left;
20532        mUserPaddingRight = right;
20533        mUserPaddingBottom = bottom;
20534
20535        final int viewFlags = mViewFlags;
20536        boolean changed = false;
20537
20538        // Common case is there are no scroll bars.
20539        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20540            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20541                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20542                        ? 0 : getVerticalScrollbarWidth();
20543                switch (mVerticalScrollbarPosition) {
20544                    case SCROLLBAR_POSITION_DEFAULT:
20545                        if (isLayoutRtl()) {
20546                            left += offset;
20547                        } else {
20548                            right += offset;
20549                        }
20550                        break;
20551                    case SCROLLBAR_POSITION_RIGHT:
20552                        right += offset;
20553                        break;
20554                    case SCROLLBAR_POSITION_LEFT:
20555                        left += offset;
20556                        break;
20557                }
20558            }
20559            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20560                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20561                        ? 0 : getHorizontalScrollbarHeight();
20562            }
20563        }
20564
20565        if (mPaddingLeft != left) {
20566            changed = true;
20567            mPaddingLeft = left;
20568        }
20569        if (mPaddingTop != top) {
20570            changed = true;
20571            mPaddingTop = top;
20572        }
20573        if (mPaddingRight != right) {
20574            changed = true;
20575            mPaddingRight = right;
20576        }
20577        if (mPaddingBottom != bottom) {
20578            changed = true;
20579            mPaddingBottom = bottom;
20580        }
20581
20582        if (changed) {
20583            requestLayout();
20584            invalidateOutline();
20585        }
20586    }
20587
20588    /**
20589     * Sets the relative padding. The view may add on the space required to display
20590     * the scrollbars, depending on the style and visibility of the scrollbars.
20591     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20592     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20593     * from the values set in this call.
20594     *
20595     * @attr ref android.R.styleable#View_padding
20596     * @attr ref android.R.styleable#View_paddingBottom
20597     * @attr ref android.R.styleable#View_paddingStart
20598     * @attr ref android.R.styleable#View_paddingEnd
20599     * @attr ref android.R.styleable#View_paddingTop
20600     * @param start the start padding in pixels
20601     * @param top the top padding in pixels
20602     * @param end the end padding in pixels
20603     * @param bottom the bottom padding in pixels
20604     */
20605    public void setPaddingRelative(int start, int top, int end, int bottom) {
20606        resetResolvedPaddingInternal();
20607
20608        mUserPaddingStart = start;
20609        mUserPaddingEnd = end;
20610        mLeftPaddingDefined = true;
20611        mRightPaddingDefined = true;
20612
20613        switch(getLayoutDirection()) {
20614            case LAYOUT_DIRECTION_RTL:
20615                mUserPaddingLeftInitial = end;
20616                mUserPaddingRightInitial = start;
20617                internalSetPadding(end, top, start, bottom);
20618                break;
20619            case LAYOUT_DIRECTION_LTR:
20620            default:
20621                mUserPaddingLeftInitial = start;
20622                mUserPaddingRightInitial = end;
20623                internalSetPadding(start, top, end, bottom);
20624        }
20625    }
20626
20627    /**
20628     * Returns the top padding of this view.
20629     *
20630     * @return the top padding in pixels
20631     */
20632    public int getPaddingTop() {
20633        return mPaddingTop;
20634    }
20635
20636    /**
20637     * Returns the bottom padding of this view. If there are inset and enabled
20638     * scrollbars, this value may include the space required to display the
20639     * scrollbars as well.
20640     *
20641     * @return the bottom padding in pixels
20642     */
20643    public int getPaddingBottom() {
20644        return mPaddingBottom;
20645    }
20646
20647    /**
20648     * Returns the left padding of this view. If there are inset and enabled
20649     * scrollbars, this value may include the space required to display the
20650     * scrollbars as well.
20651     *
20652     * @return the left padding in pixels
20653     */
20654    public int getPaddingLeft() {
20655        if (!isPaddingResolved()) {
20656            resolvePadding();
20657        }
20658        return mPaddingLeft;
20659    }
20660
20661    /**
20662     * Returns the start padding of this view depending on its resolved layout direction.
20663     * If there are inset and enabled scrollbars, this value may include the space
20664     * required to display the scrollbars as well.
20665     *
20666     * @return the start padding in pixels
20667     */
20668    public int getPaddingStart() {
20669        if (!isPaddingResolved()) {
20670            resolvePadding();
20671        }
20672        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20673                mPaddingRight : mPaddingLeft;
20674    }
20675
20676    /**
20677     * Returns the right padding of this view. If there are inset and enabled
20678     * scrollbars, this value may include the space required to display the
20679     * scrollbars as well.
20680     *
20681     * @return the right padding in pixels
20682     */
20683    public int getPaddingRight() {
20684        if (!isPaddingResolved()) {
20685            resolvePadding();
20686        }
20687        return mPaddingRight;
20688    }
20689
20690    /**
20691     * Returns the end padding of this view depending on its resolved layout direction.
20692     * If there are inset and enabled scrollbars, this value may include the space
20693     * required to display the scrollbars as well.
20694     *
20695     * @return the end padding in pixels
20696     */
20697    public int getPaddingEnd() {
20698        if (!isPaddingResolved()) {
20699            resolvePadding();
20700        }
20701        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20702                mPaddingLeft : mPaddingRight;
20703    }
20704
20705    /**
20706     * Return if the padding has been set through relative values
20707     * {@link #setPaddingRelative(int, int, int, int)} or through
20708     * @attr ref android.R.styleable#View_paddingStart or
20709     * @attr ref android.R.styleable#View_paddingEnd
20710     *
20711     * @return true if the padding is relative or false if it is not.
20712     */
20713    public boolean isPaddingRelative() {
20714        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20715    }
20716
20717    Insets computeOpticalInsets() {
20718        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20719    }
20720
20721    /**
20722     * @hide
20723     */
20724    public void resetPaddingToInitialValues() {
20725        if (isRtlCompatibilityMode()) {
20726            mPaddingLeft = mUserPaddingLeftInitial;
20727            mPaddingRight = mUserPaddingRightInitial;
20728            return;
20729        }
20730        if (isLayoutRtl()) {
20731            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20732            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20733        } else {
20734            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20735            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20736        }
20737    }
20738
20739    /**
20740     * @hide
20741     */
20742    public Insets getOpticalInsets() {
20743        if (mLayoutInsets == null) {
20744            mLayoutInsets = computeOpticalInsets();
20745        }
20746        return mLayoutInsets;
20747    }
20748
20749    /**
20750     * Set this view's optical insets.
20751     *
20752     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20753     * property. Views that compute their own optical insets should call it as part of measurement.
20754     * This method does not request layout. If you are setting optical insets outside of
20755     * measure/layout itself you will want to call requestLayout() yourself.
20756     * </p>
20757     * @hide
20758     */
20759    public void setOpticalInsets(Insets insets) {
20760        mLayoutInsets = insets;
20761    }
20762
20763    /**
20764     * Changes the selection state of this view. A view can be selected or not.
20765     * Note that selection is not the same as focus. Views are typically
20766     * selected in the context of an AdapterView like ListView or GridView;
20767     * the selected view is the view that is highlighted.
20768     *
20769     * @param selected true if the view must be selected, false otherwise
20770     */
20771    public void setSelected(boolean selected) {
20772        //noinspection DoubleNegation
20773        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20774            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20775            if (!selected) resetPressedState();
20776            invalidate(true);
20777            refreshDrawableState();
20778            dispatchSetSelected(selected);
20779            if (selected) {
20780                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20781            } else {
20782                notifyViewAccessibilityStateChangedIfNeeded(
20783                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20784            }
20785        }
20786    }
20787
20788    /**
20789     * Dispatch setSelected to all of this View's children.
20790     *
20791     * @see #setSelected(boolean)
20792     *
20793     * @param selected The new selected state
20794     */
20795    protected void dispatchSetSelected(boolean selected) {
20796    }
20797
20798    /**
20799     * Indicates the selection state of this view.
20800     *
20801     * @return true if the view is selected, false otherwise
20802     */
20803    @ViewDebug.ExportedProperty
20804    public boolean isSelected() {
20805        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20806    }
20807
20808    /**
20809     * Changes the activated state of this view. A view can be activated or not.
20810     * Note that activation is not the same as selection.  Selection is
20811     * a transient property, representing the view (hierarchy) the user is
20812     * currently interacting with.  Activation is a longer-term state that the
20813     * user can move views in and out of.  For example, in a list view with
20814     * single or multiple selection enabled, the views in the current selection
20815     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20816     * here.)  The activated state is propagated down to children of the view it
20817     * is set on.
20818     *
20819     * @param activated true if the view must be activated, false otherwise
20820     */
20821    public void setActivated(boolean activated) {
20822        //noinspection DoubleNegation
20823        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20824            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20825            invalidate(true);
20826            refreshDrawableState();
20827            dispatchSetActivated(activated);
20828        }
20829    }
20830
20831    /**
20832     * Dispatch setActivated to all of this View's children.
20833     *
20834     * @see #setActivated(boolean)
20835     *
20836     * @param activated The new activated state
20837     */
20838    protected void dispatchSetActivated(boolean activated) {
20839    }
20840
20841    /**
20842     * Indicates the activation state of this view.
20843     *
20844     * @return true if the view is activated, false otherwise
20845     */
20846    @ViewDebug.ExportedProperty
20847    public boolean isActivated() {
20848        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20849    }
20850
20851    /**
20852     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20853     * observer can be used to get notifications when global events, like
20854     * layout, happen.
20855     *
20856     * The returned ViewTreeObserver observer is not guaranteed to remain
20857     * valid for the lifetime of this View. If the caller of this method keeps
20858     * a long-lived reference to ViewTreeObserver, it should always check for
20859     * the return value of {@link ViewTreeObserver#isAlive()}.
20860     *
20861     * @return The ViewTreeObserver for this view's hierarchy.
20862     */
20863    public ViewTreeObserver getViewTreeObserver() {
20864        if (mAttachInfo != null) {
20865            return mAttachInfo.mTreeObserver;
20866        }
20867        if (mFloatingTreeObserver == null) {
20868            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20869        }
20870        return mFloatingTreeObserver;
20871    }
20872
20873    /**
20874     * <p>Finds the topmost view in the current view hierarchy.</p>
20875     *
20876     * @return the topmost view containing this view
20877     */
20878    public View getRootView() {
20879        if (mAttachInfo != null) {
20880            final View v = mAttachInfo.mRootView;
20881            if (v != null) {
20882                return v;
20883            }
20884        }
20885
20886        View parent = this;
20887
20888        while (parent.mParent != null && parent.mParent instanceof View) {
20889            parent = (View) parent.mParent;
20890        }
20891
20892        return parent;
20893    }
20894
20895    /**
20896     * Transforms a motion event from view-local coordinates to on-screen
20897     * coordinates.
20898     *
20899     * @param ev the view-local motion event
20900     * @return false if the transformation could not be applied
20901     * @hide
20902     */
20903    public boolean toGlobalMotionEvent(MotionEvent ev) {
20904        final AttachInfo info = mAttachInfo;
20905        if (info == null) {
20906            return false;
20907        }
20908
20909        final Matrix m = info.mTmpMatrix;
20910        m.set(Matrix.IDENTITY_MATRIX);
20911        transformMatrixToGlobal(m);
20912        ev.transform(m);
20913        return true;
20914    }
20915
20916    /**
20917     * Transforms a motion event from on-screen coordinates to view-local
20918     * coordinates.
20919     *
20920     * @param ev the on-screen motion event
20921     * @return false if the transformation could not be applied
20922     * @hide
20923     */
20924    public boolean toLocalMotionEvent(MotionEvent ev) {
20925        final AttachInfo info = mAttachInfo;
20926        if (info == null) {
20927            return false;
20928        }
20929
20930        final Matrix m = info.mTmpMatrix;
20931        m.set(Matrix.IDENTITY_MATRIX);
20932        transformMatrixToLocal(m);
20933        ev.transform(m);
20934        return true;
20935    }
20936
20937    /**
20938     * Modifies the input matrix such that it maps view-local coordinates to
20939     * on-screen coordinates.
20940     *
20941     * @param m input matrix to modify
20942     * @hide
20943     */
20944    public void transformMatrixToGlobal(Matrix m) {
20945        final ViewParent parent = mParent;
20946        if (parent instanceof View) {
20947            final View vp = (View) parent;
20948            vp.transformMatrixToGlobal(m);
20949            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20950        } else if (parent instanceof ViewRootImpl) {
20951            final ViewRootImpl vr = (ViewRootImpl) parent;
20952            vr.transformMatrixToGlobal(m);
20953            m.preTranslate(0, -vr.mCurScrollY);
20954        }
20955
20956        m.preTranslate(mLeft, mTop);
20957
20958        if (!hasIdentityMatrix()) {
20959            m.preConcat(getMatrix());
20960        }
20961    }
20962
20963    /**
20964     * Modifies the input matrix such that it maps on-screen coordinates to
20965     * view-local coordinates.
20966     *
20967     * @param m input matrix to modify
20968     * @hide
20969     */
20970    public void transformMatrixToLocal(Matrix m) {
20971        final ViewParent parent = mParent;
20972        if (parent instanceof View) {
20973            final View vp = (View) parent;
20974            vp.transformMatrixToLocal(m);
20975            m.postTranslate(vp.mScrollX, vp.mScrollY);
20976        } else if (parent instanceof ViewRootImpl) {
20977            final ViewRootImpl vr = (ViewRootImpl) parent;
20978            vr.transformMatrixToLocal(m);
20979            m.postTranslate(0, vr.mCurScrollY);
20980        }
20981
20982        m.postTranslate(-mLeft, -mTop);
20983
20984        if (!hasIdentityMatrix()) {
20985            m.postConcat(getInverseMatrix());
20986        }
20987    }
20988
20989    /**
20990     * @hide
20991     */
20992    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20993            @ViewDebug.IntToString(from = 0, to = "x"),
20994            @ViewDebug.IntToString(from = 1, to = "y")
20995    })
20996    public int[] getLocationOnScreen() {
20997        int[] location = new int[2];
20998        getLocationOnScreen(location);
20999        return location;
21000    }
21001
21002    /**
21003     * <p>Computes the coordinates of this view on the screen. The argument
21004     * must be an array of two integers. After the method returns, the array
21005     * contains the x and y location in that order.</p>
21006     *
21007     * @param outLocation an array of two integers in which to hold the coordinates
21008     */
21009    public void getLocationOnScreen(@Size(2) int[] outLocation) {
21010        getLocationInWindow(outLocation);
21011
21012        final AttachInfo info = mAttachInfo;
21013        if (info != null) {
21014            outLocation[0] += info.mWindowLeft;
21015            outLocation[1] += info.mWindowTop;
21016        }
21017    }
21018
21019    /**
21020     * <p>Computes the coordinates of this view in its window. The argument
21021     * must be an array of two integers. After the method returns, the array
21022     * contains the x and y location in that order.</p>
21023     *
21024     * @param outLocation an array of two integers in which to hold the coordinates
21025     */
21026    public void getLocationInWindow(@Size(2) int[] outLocation) {
21027        if (outLocation == null || outLocation.length < 2) {
21028            throw new IllegalArgumentException("outLocation must be an array of two integers");
21029        }
21030
21031        outLocation[0] = 0;
21032        outLocation[1] = 0;
21033
21034        transformFromViewToWindowSpace(outLocation);
21035    }
21036
21037    /** @hide */
21038    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21039        if (inOutLocation == null || inOutLocation.length < 2) {
21040            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21041        }
21042
21043        if (mAttachInfo == null) {
21044            // When the view is not attached to a window, this method does not make sense
21045            inOutLocation[0] = inOutLocation[1] = 0;
21046            return;
21047        }
21048
21049        float position[] = mAttachInfo.mTmpTransformLocation;
21050        position[0] = inOutLocation[0];
21051        position[1] = inOutLocation[1];
21052
21053        if (!hasIdentityMatrix()) {
21054            getMatrix().mapPoints(position);
21055        }
21056
21057        position[0] += mLeft;
21058        position[1] += mTop;
21059
21060        ViewParent viewParent = mParent;
21061        while (viewParent instanceof View) {
21062            final View view = (View) viewParent;
21063
21064            position[0] -= view.mScrollX;
21065            position[1] -= view.mScrollY;
21066
21067            if (!view.hasIdentityMatrix()) {
21068                view.getMatrix().mapPoints(position);
21069            }
21070
21071            position[0] += view.mLeft;
21072            position[1] += view.mTop;
21073
21074            viewParent = view.mParent;
21075         }
21076
21077        if (viewParent instanceof ViewRootImpl) {
21078            // *cough*
21079            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21080            position[1] -= vr.mCurScrollY;
21081        }
21082
21083        inOutLocation[0] = Math.round(position[0]);
21084        inOutLocation[1] = Math.round(position[1]);
21085    }
21086
21087    /**
21088     * @param id the id of the view to be found
21089     * @return the view of the specified id, null if cannot be found
21090     * @hide
21091     */
21092    protected <T extends View> T findViewTraversal(@IdRes int id) {
21093        if (id == mID) {
21094            return (T) this;
21095        }
21096        return null;
21097    }
21098
21099    /**
21100     * @param tag the tag of the view to be found
21101     * @return the view of specified tag, null if cannot be found
21102     * @hide
21103     */
21104    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21105        if (tag != null && tag.equals(mTag)) {
21106            return (T) this;
21107        }
21108        return null;
21109    }
21110
21111    /**
21112     * @param predicate The predicate to evaluate.
21113     * @param childToSkip If not null, ignores this child during the recursive traversal.
21114     * @return The first view that matches the predicate or null.
21115     * @hide
21116     */
21117    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21118            View childToSkip) {
21119        if (predicate.test(this)) {
21120            return (T) this;
21121        }
21122        return null;
21123    }
21124
21125    /**
21126     * Finds the first descendant view with the given ID, the view itself if
21127     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21128     * (< 0) or there is no matching view in the hierarchy.
21129     * <p>
21130     * <strong>Note:</strong> In most cases -- depending on compiler support --
21131     * the resulting view is automatically cast to the target class type. If
21132     * the target class type is unconstrained, an explicit cast may be
21133     * necessary.
21134     *
21135     * @param id the ID to search for
21136     * @return a view with given ID if found, or {@code null} otherwise
21137     * @see View#findViewById(int)
21138     */
21139    @Nullable
21140    public final <T extends View> T findViewById(@IdRes int id) {
21141        if (id == NO_ID) {
21142            return null;
21143        }
21144        return findViewTraversal(id);
21145    }
21146
21147    /**
21148     * Finds a view by its unuque and stable accessibility id.
21149     *
21150     * @param accessibilityId The searched accessibility id.
21151     * @return The found view.
21152     */
21153    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
21154        if (accessibilityId < 0) {
21155            return null;
21156        }
21157        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21158        if (view != null) {
21159            return view.includeForAccessibility() ? view : null;
21160        }
21161        return null;
21162    }
21163
21164    /**
21165     * Performs the traversal to find a view by its unuque and stable accessibility id.
21166     *
21167     * <strong>Note:</strong>This method does not stop at the root namespace
21168     * boundary since the user can touch the screen at an arbitrary location
21169     * potentially crossing the root namespace bounday which will send an
21170     * accessibility event to accessibility services and they should be able
21171     * to obtain the event source. Also accessibility ids are guaranteed to be
21172     * unique in the window.
21173     *
21174     * @param accessibilityId The accessibility id.
21175     * @return The found view.
21176     * @hide
21177     */
21178    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21179        if (getAccessibilityViewId() == accessibilityId) {
21180            return (T) this;
21181        }
21182        return null;
21183    }
21184
21185    /**
21186     * Look for a child view with the given tag.  If this view has the given
21187     * tag, return this view.
21188     *
21189     * @param tag The tag to search for, using "tag.equals(getTag())".
21190     * @return The View that has the given tag in the hierarchy or null
21191     */
21192    public final <T extends View> T findViewWithTag(Object tag) {
21193        if (tag == null) {
21194            return null;
21195        }
21196        return findViewWithTagTraversal(tag);
21197    }
21198
21199    /**
21200     * Look for a child view that matches the specified predicate.
21201     * If this view matches the predicate, return this view.
21202     *
21203     * @param predicate The predicate to evaluate.
21204     * @return The first view that matches the predicate or null.
21205     * @hide
21206     */
21207    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21208        return findViewByPredicateTraversal(predicate, null);
21209    }
21210
21211    /**
21212     * Look for a child view that matches the specified predicate,
21213     * starting with the specified view and its descendents and then
21214     * recusively searching the ancestors and siblings of that view
21215     * until this view is reached.
21216     *
21217     * This method is useful in cases where the predicate does not match
21218     * a single unique view (perhaps multiple views use the same id)
21219     * and we are trying to find the view that is "closest" in scope to the
21220     * starting view.
21221     *
21222     * @param start The view to start from.
21223     * @param predicate The predicate to evaluate.
21224     * @return The first view that matches the predicate or null.
21225     * @hide
21226     */
21227    public final <T extends View> T findViewByPredicateInsideOut(
21228            View start, Predicate<View> predicate) {
21229        View childToSkip = null;
21230        for (;;) {
21231            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21232            if (view != null || start == this) {
21233                return view;
21234            }
21235
21236            ViewParent parent = start.getParent();
21237            if (parent == null || !(parent instanceof View)) {
21238                return null;
21239            }
21240
21241            childToSkip = start;
21242            start = (View) parent;
21243        }
21244    }
21245
21246    /**
21247     * Sets the identifier for this view. The identifier does not have to be
21248     * unique in this view's hierarchy. The identifier should be a positive
21249     * number.
21250     *
21251     * @see #NO_ID
21252     * @see #getId()
21253     * @see #findViewById(int)
21254     *
21255     * @param id a number used to identify the view
21256     *
21257     * @attr ref android.R.styleable#View_id
21258     */
21259    public void setId(@IdRes int id) {
21260        mID = id;
21261        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21262            mID = generateViewId();
21263        }
21264    }
21265
21266    /**
21267     * {@hide}
21268     *
21269     * @param isRoot true if the view belongs to the root namespace, false
21270     *        otherwise
21271     */
21272    public void setIsRootNamespace(boolean isRoot) {
21273        if (isRoot) {
21274            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21275        } else {
21276            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21277        }
21278    }
21279
21280    /**
21281     * {@hide}
21282     *
21283     * @return true if the view belongs to the root namespace, false otherwise
21284     */
21285    public boolean isRootNamespace() {
21286        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21287    }
21288
21289    /**
21290     * Returns this view's identifier.
21291     *
21292     * @return a positive integer used to identify the view or {@link #NO_ID}
21293     *         if the view has no ID
21294     *
21295     * @see #setId(int)
21296     * @see #findViewById(int)
21297     * @attr ref android.R.styleable#View_id
21298     */
21299    @IdRes
21300    @ViewDebug.CapturedViewProperty
21301    public int getId() {
21302        return mID;
21303    }
21304
21305    /**
21306     * Returns this view's tag.
21307     *
21308     * @return the Object stored in this view as a tag, or {@code null} if not
21309     *         set
21310     *
21311     * @see #setTag(Object)
21312     * @see #getTag(int)
21313     */
21314    @ViewDebug.ExportedProperty
21315    public Object getTag() {
21316        return mTag;
21317    }
21318
21319    /**
21320     * Sets the tag associated with this view. A tag can be used to mark
21321     * a view in its hierarchy and does not have to be unique within the
21322     * hierarchy. Tags can also be used to store data within a view without
21323     * resorting to another data structure.
21324     *
21325     * @param tag an Object to tag the view with
21326     *
21327     * @see #getTag()
21328     * @see #setTag(int, Object)
21329     */
21330    public void setTag(final Object tag) {
21331        mTag = tag;
21332    }
21333
21334    /**
21335     * Returns the tag associated with this view and the specified key.
21336     *
21337     * @param key The key identifying the tag
21338     *
21339     * @return the Object stored in this view as a tag, or {@code null} if not
21340     *         set
21341     *
21342     * @see #setTag(int, Object)
21343     * @see #getTag()
21344     */
21345    public Object getTag(int key) {
21346        if (mKeyedTags != null) return mKeyedTags.get(key);
21347        return null;
21348    }
21349
21350    /**
21351     * Sets a tag associated with this view and a key. A tag can be used
21352     * to mark a view in its hierarchy and does not have to be unique within
21353     * the hierarchy. Tags can also be used to store data within a view
21354     * without resorting to another data structure.
21355     *
21356     * The specified key should be an id declared in the resources of the
21357     * application to ensure it is unique (see the <a
21358     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21359     * Keys identified as belonging to
21360     * the Android framework or not associated with any package will cause
21361     * an {@link IllegalArgumentException} to be thrown.
21362     *
21363     * @param key The key identifying the tag
21364     * @param tag An Object to tag the view with
21365     *
21366     * @throws IllegalArgumentException If they specified key is not valid
21367     *
21368     * @see #setTag(Object)
21369     * @see #getTag(int)
21370     */
21371    public void setTag(int key, final Object tag) {
21372        // If the package id is 0x00 or 0x01, it's either an undefined package
21373        // or a framework id
21374        if ((key >>> 24) < 2) {
21375            throw new IllegalArgumentException("The key must be an application-specific "
21376                    + "resource id.");
21377        }
21378
21379        setKeyedTag(key, tag);
21380    }
21381
21382    /**
21383     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21384     * framework id.
21385     *
21386     * @hide
21387     */
21388    public void setTagInternal(int key, Object tag) {
21389        if ((key >>> 24) != 0x1) {
21390            throw new IllegalArgumentException("The key must be a framework-specific "
21391                    + "resource id.");
21392        }
21393
21394        setKeyedTag(key, tag);
21395    }
21396
21397    private void setKeyedTag(int key, Object tag) {
21398        if (mKeyedTags == null) {
21399            mKeyedTags = new SparseArray<Object>(2);
21400        }
21401
21402        mKeyedTags.put(key, tag);
21403    }
21404
21405    /**
21406     * Prints information about this view in the log output, with the tag
21407     * {@link #VIEW_LOG_TAG}.
21408     *
21409     * @hide
21410     */
21411    public void debug() {
21412        debug(0);
21413    }
21414
21415    /**
21416     * Prints information about this view in the log output, with the tag
21417     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21418     * indentation defined by the <code>depth</code>.
21419     *
21420     * @param depth the indentation level
21421     *
21422     * @hide
21423     */
21424    protected void debug(int depth) {
21425        String output = debugIndent(depth - 1);
21426
21427        output += "+ " + this;
21428        int id = getId();
21429        if (id != -1) {
21430            output += " (id=" + id + ")";
21431        }
21432        Object tag = getTag();
21433        if (tag != null) {
21434            output += " (tag=" + tag + ")";
21435        }
21436        Log.d(VIEW_LOG_TAG, output);
21437
21438        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21439            output = debugIndent(depth) + " FOCUSED";
21440            Log.d(VIEW_LOG_TAG, output);
21441        }
21442
21443        output = debugIndent(depth);
21444        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21445                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21446                + "} ";
21447        Log.d(VIEW_LOG_TAG, output);
21448
21449        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21450                || mPaddingBottom != 0) {
21451            output = debugIndent(depth);
21452            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21453                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21454            Log.d(VIEW_LOG_TAG, output);
21455        }
21456
21457        output = debugIndent(depth);
21458        output += "mMeasureWidth=" + mMeasuredWidth +
21459                " mMeasureHeight=" + mMeasuredHeight;
21460        Log.d(VIEW_LOG_TAG, output);
21461
21462        output = debugIndent(depth);
21463        if (mLayoutParams == null) {
21464            output += "BAD! no layout params";
21465        } else {
21466            output = mLayoutParams.debug(output);
21467        }
21468        Log.d(VIEW_LOG_TAG, output);
21469
21470        output = debugIndent(depth);
21471        output += "flags={";
21472        output += View.printFlags(mViewFlags);
21473        output += "}";
21474        Log.d(VIEW_LOG_TAG, output);
21475
21476        output = debugIndent(depth);
21477        output += "privateFlags={";
21478        output += View.printPrivateFlags(mPrivateFlags);
21479        output += "}";
21480        Log.d(VIEW_LOG_TAG, output);
21481    }
21482
21483    /**
21484     * Creates a string of whitespaces used for indentation.
21485     *
21486     * @param depth the indentation level
21487     * @return a String containing (depth * 2 + 3) * 2 white spaces
21488     *
21489     * @hide
21490     */
21491    protected static String debugIndent(int depth) {
21492        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21493        for (int i = 0; i < (depth * 2) + 3; i++) {
21494            spaces.append(' ').append(' ');
21495        }
21496        return spaces.toString();
21497    }
21498
21499    /**
21500     * <p>Return the offset of the widget's text baseline from the widget's top
21501     * boundary. If this widget does not support baseline alignment, this
21502     * method returns -1. </p>
21503     *
21504     * @return the offset of the baseline within the widget's bounds or -1
21505     *         if baseline alignment is not supported
21506     */
21507    @ViewDebug.ExportedProperty(category = "layout")
21508    public int getBaseline() {
21509        return -1;
21510    }
21511
21512    /**
21513     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21514     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21515     * a layout pass.
21516     *
21517     * @return whether the view hierarchy is currently undergoing a layout pass
21518     */
21519    public boolean isInLayout() {
21520        ViewRootImpl viewRoot = getViewRootImpl();
21521        return (viewRoot != null && viewRoot.isInLayout());
21522    }
21523
21524    /**
21525     * Call this when something has changed which has invalidated the
21526     * layout of this view. This will schedule a layout pass of the view
21527     * tree. This should not be called while the view hierarchy is currently in a layout
21528     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21529     * end of the current layout pass (and then layout will run again) or after the current
21530     * frame is drawn and the next layout occurs.
21531     *
21532     * <p>Subclasses which override this method should call the superclass method to
21533     * handle possible request-during-layout errors correctly.</p>
21534     */
21535    @CallSuper
21536    public void requestLayout() {
21537        if (mMeasureCache != null) mMeasureCache.clear();
21538
21539        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21540            // Only trigger request-during-layout logic if this is the view requesting it,
21541            // not the views in its parent hierarchy
21542            ViewRootImpl viewRoot = getViewRootImpl();
21543            if (viewRoot != null && viewRoot.isInLayout()) {
21544                if (!viewRoot.requestLayoutDuringLayout(this)) {
21545                    return;
21546                }
21547            }
21548            mAttachInfo.mViewRequestingLayout = this;
21549        }
21550
21551        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21552        mPrivateFlags |= PFLAG_INVALIDATED;
21553
21554        if (mParent != null && !mParent.isLayoutRequested()) {
21555            mParent.requestLayout();
21556        }
21557        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21558            mAttachInfo.mViewRequestingLayout = null;
21559        }
21560    }
21561
21562    /**
21563     * Forces this view to be laid out during the next layout pass.
21564     * This method does not call requestLayout() or forceLayout()
21565     * on the parent.
21566     */
21567    public void forceLayout() {
21568        if (mMeasureCache != null) mMeasureCache.clear();
21569
21570        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21571        mPrivateFlags |= PFLAG_INVALIDATED;
21572    }
21573
21574    /**
21575     * <p>
21576     * This is called to find out how big a view should be. The parent
21577     * supplies constraint information in the width and height parameters.
21578     * </p>
21579     *
21580     * <p>
21581     * The actual measurement work of a view is performed in
21582     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21583     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21584     * </p>
21585     *
21586     *
21587     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21588     *        parent
21589     * @param heightMeasureSpec Vertical space requirements as imposed by the
21590     *        parent
21591     *
21592     * @see #onMeasure(int, int)
21593     */
21594    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21595        boolean optical = isLayoutModeOptical(this);
21596        if (optical != isLayoutModeOptical(mParent)) {
21597            Insets insets = getOpticalInsets();
21598            int oWidth  = insets.left + insets.right;
21599            int oHeight = insets.top  + insets.bottom;
21600            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21601            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21602        }
21603
21604        // Suppress sign extension for the low bytes
21605        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21606        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21607
21608        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21609
21610        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21611        // already measured as the correct size. In API 23 and below, this
21612        // extra pass is required to make LinearLayout re-distribute weight.
21613        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21614                || heightMeasureSpec != mOldHeightMeasureSpec;
21615        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21616                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21617        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21618                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21619        final boolean needsLayout = specChanged
21620                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21621
21622        if (forceLayout || needsLayout) {
21623            // first clears the measured dimension flag
21624            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21625
21626            resolveRtlPropertiesIfNeeded();
21627
21628            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21629            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21630                // measure ourselves, this should set the measured dimension flag back
21631                onMeasure(widthMeasureSpec, heightMeasureSpec);
21632                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21633            } else {
21634                long value = mMeasureCache.valueAt(cacheIndex);
21635                // Casting a long to int drops the high 32 bits, no mask needed
21636                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21637                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21638            }
21639
21640            // flag not set, setMeasuredDimension() was not invoked, we raise
21641            // an exception to warn the developer
21642            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21643                throw new IllegalStateException("View with id " + getId() + ": "
21644                        + getClass().getName() + "#onMeasure() did not set the"
21645                        + " measured dimension by calling"
21646                        + " setMeasuredDimension()");
21647            }
21648
21649            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21650        }
21651
21652        mOldWidthMeasureSpec = widthMeasureSpec;
21653        mOldHeightMeasureSpec = heightMeasureSpec;
21654
21655        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21656                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21657    }
21658
21659    /**
21660     * <p>
21661     * Measure the view and its content to determine the measured width and the
21662     * measured height. This method is invoked by {@link #measure(int, int)} and
21663     * should be overridden by subclasses to provide accurate and efficient
21664     * measurement of their contents.
21665     * </p>
21666     *
21667     * <p>
21668     * <strong>CONTRACT:</strong> When overriding this method, you
21669     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21670     * measured width and height of this view. Failure to do so will trigger an
21671     * <code>IllegalStateException</code>, thrown by
21672     * {@link #measure(int, int)}. Calling the superclass'
21673     * {@link #onMeasure(int, int)} is a valid use.
21674     * </p>
21675     *
21676     * <p>
21677     * The base class implementation of measure defaults to the background size,
21678     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21679     * override {@link #onMeasure(int, int)} to provide better measurements of
21680     * their content.
21681     * </p>
21682     *
21683     * <p>
21684     * If this method is overridden, it is the subclass's responsibility to make
21685     * sure the measured height and width are at least the view's minimum height
21686     * and width ({@link #getSuggestedMinimumHeight()} and
21687     * {@link #getSuggestedMinimumWidth()}).
21688     * </p>
21689     *
21690     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21691     *                         The requirements are encoded with
21692     *                         {@link android.view.View.MeasureSpec}.
21693     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21694     *                         The requirements are encoded with
21695     *                         {@link android.view.View.MeasureSpec}.
21696     *
21697     * @see #getMeasuredWidth()
21698     * @see #getMeasuredHeight()
21699     * @see #setMeasuredDimension(int, int)
21700     * @see #getSuggestedMinimumHeight()
21701     * @see #getSuggestedMinimumWidth()
21702     * @see android.view.View.MeasureSpec#getMode(int)
21703     * @see android.view.View.MeasureSpec#getSize(int)
21704     */
21705    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21706        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21707                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21708    }
21709
21710    /**
21711     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21712     * measured width and measured height. Failing to do so will trigger an
21713     * exception at measurement time.</p>
21714     *
21715     * @param measuredWidth The measured width of this view.  May be a complex
21716     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21717     * {@link #MEASURED_STATE_TOO_SMALL}.
21718     * @param measuredHeight The measured height of this view.  May be a complex
21719     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21720     * {@link #MEASURED_STATE_TOO_SMALL}.
21721     */
21722    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21723        boolean optical = isLayoutModeOptical(this);
21724        if (optical != isLayoutModeOptical(mParent)) {
21725            Insets insets = getOpticalInsets();
21726            int opticalWidth  = insets.left + insets.right;
21727            int opticalHeight = insets.top  + insets.bottom;
21728
21729            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21730            measuredHeight += optical ? opticalHeight : -opticalHeight;
21731        }
21732        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21733    }
21734
21735    /**
21736     * Sets the measured dimension without extra processing for things like optical bounds.
21737     * Useful for reapplying consistent values that have already been cooked with adjustments
21738     * for optical bounds, etc. such as those from the measurement cache.
21739     *
21740     * @param measuredWidth The measured width of this view.  May be a complex
21741     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21742     * {@link #MEASURED_STATE_TOO_SMALL}.
21743     * @param measuredHeight The measured height of this view.  May be a complex
21744     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21745     * {@link #MEASURED_STATE_TOO_SMALL}.
21746     */
21747    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21748        mMeasuredWidth = measuredWidth;
21749        mMeasuredHeight = measuredHeight;
21750
21751        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21752    }
21753
21754    /**
21755     * Merge two states as returned by {@link #getMeasuredState()}.
21756     * @param curState The current state as returned from a view or the result
21757     * of combining multiple views.
21758     * @param newState The new view state to combine.
21759     * @return Returns a new integer reflecting the combination of the two
21760     * states.
21761     */
21762    public static int combineMeasuredStates(int curState, int newState) {
21763        return curState | newState;
21764    }
21765
21766    /**
21767     * Version of {@link #resolveSizeAndState(int, int, int)}
21768     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21769     */
21770    public static int resolveSize(int size, int measureSpec) {
21771        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21772    }
21773
21774    /**
21775     * Utility to reconcile a desired size and state, with constraints imposed
21776     * by a MeasureSpec. Will take the desired size, unless a different size
21777     * is imposed by the constraints. The returned value is a compound integer,
21778     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21779     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21780     * resulting size is smaller than the size the view wants to be.
21781     *
21782     * @param size How big the view wants to be.
21783     * @param measureSpec Constraints imposed by the parent.
21784     * @param childMeasuredState Size information bit mask for the view's
21785     *                           children.
21786     * @return Size information bit mask as defined by
21787     *         {@link #MEASURED_SIZE_MASK} and
21788     *         {@link #MEASURED_STATE_TOO_SMALL}.
21789     */
21790    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21791        final int specMode = MeasureSpec.getMode(measureSpec);
21792        final int specSize = MeasureSpec.getSize(measureSpec);
21793        final int result;
21794        switch (specMode) {
21795            case MeasureSpec.AT_MOST:
21796                if (specSize < size) {
21797                    result = specSize | MEASURED_STATE_TOO_SMALL;
21798                } else {
21799                    result = size;
21800                }
21801                break;
21802            case MeasureSpec.EXACTLY:
21803                result = specSize;
21804                break;
21805            case MeasureSpec.UNSPECIFIED:
21806            default:
21807                result = size;
21808        }
21809        return result | (childMeasuredState & MEASURED_STATE_MASK);
21810    }
21811
21812    /**
21813     * Utility to return a default size. Uses the supplied size if the
21814     * MeasureSpec imposed no constraints. Will get larger if allowed
21815     * by the MeasureSpec.
21816     *
21817     * @param size Default size for this view
21818     * @param measureSpec Constraints imposed by the parent
21819     * @return The size this view should be.
21820     */
21821    public static int getDefaultSize(int size, int measureSpec) {
21822        int result = size;
21823        int specMode = MeasureSpec.getMode(measureSpec);
21824        int specSize = MeasureSpec.getSize(measureSpec);
21825
21826        switch (specMode) {
21827        case MeasureSpec.UNSPECIFIED:
21828            result = size;
21829            break;
21830        case MeasureSpec.AT_MOST:
21831        case MeasureSpec.EXACTLY:
21832            result = specSize;
21833            break;
21834        }
21835        return result;
21836    }
21837
21838    /**
21839     * Returns the suggested minimum height that the view should use. This
21840     * returns the maximum of the view's minimum height
21841     * and the background's minimum height
21842     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21843     * <p>
21844     * When being used in {@link #onMeasure(int, int)}, the caller should still
21845     * ensure the returned height is within the requirements of the parent.
21846     *
21847     * @return The suggested minimum height of the view.
21848     */
21849    protected int getSuggestedMinimumHeight() {
21850        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21851
21852    }
21853
21854    /**
21855     * Returns the suggested minimum width that the view should use. This
21856     * returns the maximum of the view's minimum width
21857     * and the background's minimum width
21858     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21859     * <p>
21860     * When being used in {@link #onMeasure(int, int)}, the caller should still
21861     * ensure the returned width is within the requirements of the parent.
21862     *
21863     * @return The suggested minimum width of the view.
21864     */
21865    protected int getSuggestedMinimumWidth() {
21866        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21867    }
21868
21869    /**
21870     * Returns the minimum height of the view.
21871     *
21872     * @return the minimum height the view will try to be, in pixels
21873     *
21874     * @see #setMinimumHeight(int)
21875     *
21876     * @attr ref android.R.styleable#View_minHeight
21877     */
21878    public int getMinimumHeight() {
21879        return mMinHeight;
21880    }
21881
21882    /**
21883     * Sets the minimum height of the view. It is not guaranteed the view will
21884     * be able to achieve this minimum height (for example, if its parent layout
21885     * constrains it with less available height).
21886     *
21887     * @param minHeight The minimum height the view will try to be, in pixels
21888     *
21889     * @see #getMinimumHeight()
21890     *
21891     * @attr ref android.R.styleable#View_minHeight
21892     */
21893    @RemotableViewMethod
21894    public void setMinimumHeight(int minHeight) {
21895        mMinHeight = minHeight;
21896        requestLayout();
21897    }
21898
21899    /**
21900     * Returns the minimum width of the view.
21901     *
21902     * @return the minimum width the view will try to be, in pixels
21903     *
21904     * @see #setMinimumWidth(int)
21905     *
21906     * @attr ref android.R.styleable#View_minWidth
21907     */
21908    public int getMinimumWidth() {
21909        return mMinWidth;
21910    }
21911
21912    /**
21913     * Sets the minimum width of the view. It is not guaranteed the view will
21914     * be able to achieve this minimum width (for example, if its parent layout
21915     * constrains it with less available width).
21916     *
21917     * @param minWidth The minimum width the view will try to be, in pixels
21918     *
21919     * @see #getMinimumWidth()
21920     *
21921     * @attr ref android.R.styleable#View_minWidth
21922     */
21923    public void setMinimumWidth(int minWidth) {
21924        mMinWidth = minWidth;
21925        requestLayout();
21926
21927    }
21928
21929    /**
21930     * Get the animation currently associated with this view.
21931     *
21932     * @return The animation that is currently playing or
21933     *         scheduled to play for this view.
21934     */
21935    public Animation getAnimation() {
21936        return mCurrentAnimation;
21937    }
21938
21939    /**
21940     * Start the specified animation now.
21941     *
21942     * @param animation the animation to start now
21943     */
21944    public void startAnimation(Animation animation) {
21945        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21946        setAnimation(animation);
21947        invalidateParentCaches();
21948        invalidate(true);
21949    }
21950
21951    /**
21952     * Cancels any animations for this view.
21953     */
21954    public void clearAnimation() {
21955        if (mCurrentAnimation != null) {
21956            mCurrentAnimation.detach();
21957        }
21958        mCurrentAnimation = null;
21959        invalidateParentIfNeeded();
21960    }
21961
21962    /**
21963     * Sets the next animation to play for this view.
21964     * If you want the animation to play immediately, use
21965     * {@link #startAnimation(android.view.animation.Animation)} instead.
21966     * This method provides allows fine-grained
21967     * control over the start time and invalidation, but you
21968     * must make sure that 1) the animation has a start time set, and
21969     * 2) the view's parent (which controls animations on its children)
21970     * will be invalidated when the animation is supposed to
21971     * start.
21972     *
21973     * @param animation The next animation, or null.
21974     */
21975    public void setAnimation(Animation animation) {
21976        mCurrentAnimation = animation;
21977
21978        if (animation != null) {
21979            // If the screen is off assume the animation start time is now instead of
21980            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21981            // would cause the animation to start when the screen turns back on
21982            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21983                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21984                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21985            }
21986            animation.reset();
21987        }
21988    }
21989
21990    /**
21991     * Invoked by a parent ViewGroup to notify the start of the animation
21992     * currently associated with this view. If you override this method,
21993     * always call super.onAnimationStart();
21994     *
21995     * @see #setAnimation(android.view.animation.Animation)
21996     * @see #getAnimation()
21997     */
21998    @CallSuper
21999    protected void onAnimationStart() {
22000        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22001    }
22002
22003    /**
22004     * Invoked by a parent ViewGroup to notify the end of the animation
22005     * currently associated with this view. If you override this method,
22006     * always call super.onAnimationEnd();
22007     *
22008     * @see #setAnimation(android.view.animation.Animation)
22009     * @see #getAnimation()
22010     */
22011    @CallSuper
22012    protected void onAnimationEnd() {
22013        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22014    }
22015
22016    /**
22017     * Invoked if there is a Transform that involves alpha. Subclass that can
22018     * draw themselves with the specified alpha should return true, and then
22019     * respect that alpha when their onDraw() is called. If this returns false
22020     * then the view may be redirected to draw into an offscreen buffer to
22021     * fulfill the request, which will look fine, but may be slower than if the
22022     * subclass handles it internally. The default implementation returns false.
22023     *
22024     * @param alpha The alpha (0..255) to apply to the view's drawing
22025     * @return true if the view can draw with the specified alpha.
22026     */
22027    protected boolean onSetAlpha(int alpha) {
22028        return false;
22029    }
22030
22031    /**
22032     * This is used by the RootView to perform an optimization when
22033     * the view hierarchy contains one or several SurfaceView.
22034     * SurfaceView is always considered transparent, but its children are not,
22035     * therefore all View objects remove themselves from the global transparent
22036     * region (passed as a parameter to this function).
22037     *
22038     * @param region The transparent region for this ViewAncestor (window).
22039     *
22040     * @return Returns true if the effective visibility of the view at this
22041     * point is opaque, regardless of the transparent region; returns false
22042     * if it is possible for underlying windows to be seen behind the view.
22043     *
22044     * {@hide}
22045     */
22046    public boolean gatherTransparentRegion(Region region) {
22047        final AttachInfo attachInfo = mAttachInfo;
22048        if (region != null && attachInfo != null) {
22049            final int pflags = mPrivateFlags;
22050            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22051                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22052                // remove it from the transparent region.
22053                final int[] location = attachInfo.mTransparentLocation;
22054                getLocationInWindow(location);
22055                // When a view has Z value, then it will be better to leave some area below the view
22056                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22057                // the bottom part needs more offset than the left, top and right parts due to the
22058                // spot light effects.
22059                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22060                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22061                        location[0] + mRight - mLeft + shadowOffset,
22062                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22063            } else {
22064                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22065                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22066                    // the background drawable's non-transparent parts from this transparent region.
22067                    applyDrawableToTransparentRegion(mBackground, region);
22068                }
22069                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22070                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22071                    // Similarly, we remove the foreground drawable's non-transparent parts.
22072                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22073                }
22074                if (mDefaultFocusHighlight != null
22075                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22076                    // Similarly, we remove the default focus highlight's non-transparent parts.
22077                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22078                }
22079            }
22080        }
22081        return true;
22082    }
22083
22084    /**
22085     * Play a sound effect for this view.
22086     *
22087     * <p>The framework will play sound effects for some built in actions, such as
22088     * clicking, but you may wish to play these effects in your widget,
22089     * for instance, for internal navigation.
22090     *
22091     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22092     * {@link #isSoundEffectsEnabled()} is true.
22093     *
22094     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22095     */
22096    public void playSoundEffect(int soundConstant) {
22097        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22098            return;
22099        }
22100        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22101    }
22102
22103    /**
22104     * BZZZTT!!1!
22105     *
22106     * <p>Provide haptic feedback to the user for this view.
22107     *
22108     * <p>The framework will provide haptic feedback for some built in actions,
22109     * such as long presses, but you may wish to provide feedback for your
22110     * own widget.
22111     *
22112     * <p>The feedback will only be performed if
22113     * {@link #isHapticFeedbackEnabled()} is true.
22114     *
22115     * @param feedbackConstant One of the constants defined in
22116     * {@link HapticFeedbackConstants}
22117     */
22118    public boolean performHapticFeedback(int feedbackConstant) {
22119        return performHapticFeedback(feedbackConstant, 0);
22120    }
22121
22122    /**
22123     * BZZZTT!!1!
22124     *
22125     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22126     *
22127     * @param feedbackConstant One of the constants defined in
22128     * {@link HapticFeedbackConstants}
22129     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22130     */
22131    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22132        if (mAttachInfo == null) {
22133            return false;
22134        }
22135        //noinspection SimplifiableIfStatement
22136        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22137                && !isHapticFeedbackEnabled()) {
22138            return false;
22139        }
22140        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22141                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22142    }
22143
22144    /**
22145     * Request that the visibility of the status bar or other screen/window
22146     * decorations be changed.
22147     *
22148     * <p>This method is used to put the over device UI into temporary modes
22149     * where the user's attention is focused more on the application content,
22150     * by dimming or hiding surrounding system affordances.  This is typically
22151     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22152     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22153     * to be placed behind the action bar (and with these flags other system
22154     * affordances) so that smooth transitions between hiding and showing them
22155     * can be done.
22156     *
22157     * <p>Two representative examples of the use of system UI visibility is
22158     * implementing a content browsing application (like a magazine reader)
22159     * and a video playing application.
22160     *
22161     * <p>The first code shows a typical implementation of a View in a content
22162     * browsing application.  In this implementation, the application goes
22163     * into a content-oriented mode by hiding the status bar and action bar,
22164     * and putting the navigation elements into lights out mode.  The user can
22165     * then interact with content while in this mode.  Such an application should
22166     * provide an easy way for the user to toggle out of the mode (such as to
22167     * check information in the status bar or access notifications).  In the
22168     * implementation here, this is done simply by tapping on the content.
22169     *
22170     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22171     *      content}
22172     *
22173     * <p>This second code sample shows a typical implementation of a View
22174     * in a video playing application.  In this situation, while the video is
22175     * playing the application would like to go into a complete full-screen mode,
22176     * to use as much of the display as possible for the video.  When in this state
22177     * the user can not interact with the application; the system intercepts
22178     * touching on the screen to pop the UI out of full screen mode.  See
22179     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22180     *
22181     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22182     *      content}
22183     *
22184     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22185     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22186     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22187     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22188     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22189     */
22190    public void setSystemUiVisibility(int visibility) {
22191        if (visibility != mSystemUiVisibility) {
22192            mSystemUiVisibility = visibility;
22193            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22194                mParent.recomputeViewAttributes(this);
22195            }
22196        }
22197    }
22198
22199    /**
22200     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22201     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22202     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22203     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22204     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22205     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22206     */
22207    public int getSystemUiVisibility() {
22208        return mSystemUiVisibility;
22209    }
22210
22211    /**
22212     * Returns the current system UI visibility that is currently set for
22213     * the entire window.  This is the combination of the
22214     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22215     * views in the window.
22216     */
22217    public int getWindowSystemUiVisibility() {
22218        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22219    }
22220
22221    /**
22222     * Override to find out when the window's requested system UI visibility
22223     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22224     * This is different from the callbacks received through
22225     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22226     * in that this is only telling you about the local request of the window,
22227     * not the actual values applied by the system.
22228     */
22229    public void onWindowSystemUiVisibilityChanged(int visible) {
22230    }
22231
22232    /**
22233     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22234     * the view hierarchy.
22235     */
22236    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22237        onWindowSystemUiVisibilityChanged(visible);
22238    }
22239
22240    /**
22241     * Set a listener to receive callbacks when the visibility of the system bar changes.
22242     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22243     */
22244    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22245        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22246        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22247            mParent.recomputeViewAttributes(this);
22248        }
22249    }
22250
22251    /**
22252     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22253     * the view hierarchy.
22254     */
22255    public void dispatchSystemUiVisibilityChanged(int visibility) {
22256        ListenerInfo li = mListenerInfo;
22257        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22258            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22259                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22260        }
22261    }
22262
22263    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22264        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22265        if (val != mSystemUiVisibility) {
22266            setSystemUiVisibility(val);
22267            return true;
22268        }
22269        return false;
22270    }
22271
22272    /** @hide */
22273    public void setDisabledSystemUiVisibility(int flags) {
22274        if (mAttachInfo != null) {
22275            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22276                mAttachInfo.mDisabledSystemUiVisibility = flags;
22277                if (mParent != null) {
22278                    mParent.recomputeViewAttributes(this);
22279                }
22280            }
22281        }
22282    }
22283
22284    /**
22285     * Creates an image that the system displays during the drag and drop
22286     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22287     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22288     * appearance as the given View. The default also positions the center of the drag shadow
22289     * directly under the touch point. If no View is provided (the constructor with no parameters
22290     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22291     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22292     * default is an invisible drag shadow.
22293     * <p>
22294     * You are not required to use the View you provide to the constructor as the basis of the
22295     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22296     * anything you want as the drag shadow.
22297     * </p>
22298     * <p>
22299     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22300     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22301     *  size and position of the drag shadow. It uses this data to construct a
22302     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22303     *  so that your application can draw the shadow image in the Canvas.
22304     * </p>
22305     *
22306     * <div class="special reference">
22307     * <h3>Developer Guides</h3>
22308     * <p>For a guide to implementing drag and drop features, read the
22309     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22310     * </div>
22311     */
22312    public static class DragShadowBuilder {
22313        private final WeakReference<View> mView;
22314
22315        /**
22316         * Constructs a shadow image builder based on a View. By default, the resulting drag
22317         * shadow will have the same appearance and dimensions as the View, with the touch point
22318         * over the center of the View.
22319         * @param view A View. Any View in scope can be used.
22320         */
22321        public DragShadowBuilder(View view) {
22322            mView = new WeakReference<View>(view);
22323        }
22324
22325        /**
22326         * Construct a shadow builder object with no associated View.  This
22327         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22328         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22329         * to supply the drag shadow's dimensions and appearance without
22330         * reference to any View object. If they are not overridden, then the result is an
22331         * invisible drag shadow.
22332         */
22333        public DragShadowBuilder() {
22334            mView = new WeakReference<View>(null);
22335        }
22336
22337        /**
22338         * Returns the View object that had been passed to the
22339         * {@link #View.DragShadowBuilder(View)}
22340         * constructor.  If that View parameter was {@code null} or if the
22341         * {@link #View.DragShadowBuilder()}
22342         * constructor was used to instantiate the builder object, this method will return
22343         * null.
22344         *
22345         * @return The View object associate with this builder object.
22346         */
22347        @SuppressWarnings({"JavadocReference"})
22348        final public View getView() {
22349            return mView.get();
22350        }
22351
22352        /**
22353         * Provides the metrics for the shadow image. These include the dimensions of
22354         * the shadow image, and the point within that shadow that should
22355         * be centered under the touch location while dragging.
22356         * <p>
22357         * The default implementation sets the dimensions of the shadow to be the
22358         * same as the dimensions of the View itself and centers the shadow under
22359         * the touch point.
22360         * </p>
22361         *
22362         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22363         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22364         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22365         * image.
22366         *
22367         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22368         * shadow image that should be underneath the touch point during the drag and drop
22369         * operation. Your application must set {@link android.graphics.Point#x} to the
22370         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22371         */
22372        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22373            final View view = mView.get();
22374            if (view != null) {
22375                outShadowSize.set(view.getWidth(), view.getHeight());
22376                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22377            } else {
22378                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22379            }
22380        }
22381
22382        /**
22383         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22384         * based on the dimensions it received from the
22385         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22386         *
22387         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22388         */
22389        public void onDrawShadow(Canvas canvas) {
22390            final View view = mView.get();
22391            if (view != null) {
22392                view.draw(canvas);
22393            } else {
22394                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22395            }
22396        }
22397    }
22398
22399    /**
22400     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22401     * startDragAndDrop()} for newer platform versions.
22402     */
22403    @Deprecated
22404    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22405                                   Object myLocalState, int flags) {
22406        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22407    }
22408
22409    /**
22410     * Starts a drag and drop operation. When your application calls this method, it passes a
22411     * {@link android.view.View.DragShadowBuilder} object to the system. The
22412     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22413     * to get metrics for the drag shadow, and then calls the object's
22414     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22415     * <p>
22416     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22417     *  drag events to all the View objects in your application that are currently visible. It does
22418     *  this either by calling the View object's drag listener (an implementation of
22419     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22420     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22421     *  Both are passed a {@link android.view.DragEvent} object that has a
22422     *  {@link android.view.DragEvent#getAction()} value of
22423     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22424     * </p>
22425     * <p>
22426     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22427     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22428     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22429     * to the View the user selected for dragging.
22430     * </p>
22431     * @param data A {@link android.content.ClipData} object pointing to the data to be
22432     * transferred by the drag and drop operation.
22433     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22434     * drag shadow.
22435     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22436     * drop operation. When dispatching drag events to views in the same activity this object
22437     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22438     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22439     * will return null).
22440     * <p>
22441     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22442     * to the target Views. For example, it can contain flags that differentiate between a
22443     * a copy operation and a move operation.
22444     * </p>
22445     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22446     * flags, or any combination of the following:
22447     *     <ul>
22448     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22449     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22450     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22451     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22452     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22453     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22454     *     </ul>
22455     * @return {@code true} if the method completes successfully, or
22456     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22457     * do a drag, and so no drag operation is in progress.
22458     */
22459    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22460            Object myLocalState, int flags) {
22461        if (ViewDebug.DEBUG_DRAG) {
22462            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22463        }
22464        if (mAttachInfo == null) {
22465            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22466            return false;
22467        }
22468
22469        if (data != null) {
22470            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22471        }
22472
22473        boolean okay = false;
22474
22475        Point shadowSize = new Point();
22476        Point shadowTouchPoint = new Point();
22477        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22478
22479        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22480                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22481            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22482        }
22483
22484        if (ViewDebug.DEBUG_DRAG) {
22485            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22486                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22487        }
22488        if (mAttachInfo.mDragSurface != null) {
22489            mAttachInfo.mDragSurface.release();
22490        }
22491        mAttachInfo.mDragSurface = new Surface();
22492        try {
22493            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22494                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22495            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22496                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22497            if (mAttachInfo.mDragToken != null) {
22498                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22499                try {
22500                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22501                    shadowBuilder.onDrawShadow(canvas);
22502                } finally {
22503                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22504                }
22505
22506                final ViewRootImpl root = getViewRootImpl();
22507
22508                // Cache the local state object for delivery with DragEvents
22509                root.setLocalDragState(myLocalState);
22510
22511                // repurpose 'shadowSize' for the last touch point
22512                root.getLastTouchPoint(shadowSize);
22513
22514                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22515                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22516                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22517                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22518            }
22519        } catch (Exception e) {
22520            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22521            mAttachInfo.mDragSurface.destroy();
22522            mAttachInfo.mDragSurface = null;
22523        }
22524
22525        return okay;
22526    }
22527
22528    /**
22529     * Cancels an ongoing drag and drop operation.
22530     * <p>
22531     * A {@link android.view.DragEvent} object with
22532     * {@link android.view.DragEvent#getAction()} value of
22533     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22534     * {@link android.view.DragEvent#getResult()} value of {@code false}
22535     * will be sent to every
22536     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22537     * even if they are not currently visible.
22538     * </p>
22539     * <p>
22540     * This method can be called on any View in the same window as the View on which
22541     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22542     * was called.
22543     * </p>
22544     */
22545    public final void cancelDragAndDrop() {
22546        if (ViewDebug.DEBUG_DRAG) {
22547            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22548        }
22549        if (mAttachInfo == null) {
22550            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22551            return;
22552        }
22553        if (mAttachInfo.mDragToken != null) {
22554            try {
22555                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22556            } catch (Exception e) {
22557                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22558            }
22559            mAttachInfo.mDragToken = null;
22560        } else {
22561            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22562        }
22563    }
22564
22565    /**
22566     * Updates the drag shadow for the ongoing drag and drop operation.
22567     *
22568     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22569     * new drag shadow.
22570     */
22571    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22572        if (ViewDebug.DEBUG_DRAG) {
22573            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22574        }
22575        if (mAttachInfo == null) {
22576            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22577            return;
22578        }
22579        if (mAttachInfo.mDragToken != null) {
22580            try {
22581                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22582                try {
22583                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22584                    shadowBuilder.onDrawShadow(canvas);
22585                } finally {
22586                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22587                }
22588            } catch (Exception e) {
22589                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22590            }
22591        } else {
22592            Log.e(VIEW_LOG_TAG, "No active drag");
22593        }
22594    }
22595
22596    /**
22597     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22598     * between {startX, startY} and the new cursor positon.
22599     * @param startX horizontal coordinate where the move started.
22600     * @param startY vertical coordinate where the move started.
22601     * @return whether moving was started successfully.
22602     * @hide
22603     */
22604    public final boolean startMovingTask(float startX, float startY) {
22605        if (ViewDebug.DEBUG_POSITIONING) {
22606            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22607        }
22608        try {
22609            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22610        } catch (RemoteException e) {
22611            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22612        }
22613        return false;
22614    }
22615
22616    /**
22617     * Handles drag events sent by the system following a call to
22618     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22619     * startDragAndDrop()}.
22620     *<p>
22621     * When the system calls this method, it passes a
22622     * {@link android.view.DragEvent} object. A call to
22623     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22624     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22625     * operation.
22626     * @param event The {@link android.view.DragEvent} sent by the system.
22627     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22628     * in DragEvent, indicating the type of drag event represented by this object.
22629     * @return {@code true} if the method was successful, otherwise {@code false}.
22630     * <p>
22631     *  The method should return {@code true} in response to an action type of
22632     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22633     *  operation.
22634     * </p>
22635     * <p>
22636     *  The method should also return {@code true} in response to an action type of
22637     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22638     *  {@code false} if it didn't.
22639     * </p>
22640     * <p>
22641     *  For all other events, the return value is ignored.
22642     * </p>
22643     */
22644    public boolean onDragEvent(DragEvent event) {
22645        return false;
22646    }
22647
22648    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22649    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22650        return callDragEventHandler(event);
22651    }
22652
22653    /**
22654     * Detects if this View is enabled and has a drag event listener.
22655     * If both are true, then it calls the drag event listener with the
22656     * {@link android.view.DragEvent} it received. If the drag event listener returns
22657     * {@code true}, then dispatchDragEvent() returns {@code true}.
22658     * <p>
22659     * For all other cases, the method calls the
22660     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22661     * method and returns its result.
22662     * </p>
22663     * <p>
22664     * This ensures that a drag event is always consumed, even if the View does not have a drag
22665     * event listener. However, if the View has a listener and the listener returns true, then
22666     * onDragEvent() is not called.
22667     * </p>
22668     */
22669    public boolean dispatchDragEvent(DragEvent event) {
22670        event.mEventHandlerWasCalled = true;
22671        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22672            event.mAction == DragEvent.ACTION_DROP) {
22673            // About to deliver an event with coordinates to this view. Notify that now this view
22674            // has drag focus. This will send exit/enter events as needed.
22675            getViewRootImpl().setDragFocus(this, event);
22676        }
22677        return callDragEventHandler(event);
22678    }
22679
22680    final boolean callDragEventHandler(DragEvent event) {
22681        final boolean result;
22682
22683        ListenerInfo li = mListenerInfo;
22684        //noinspection SimplifiableIfStatement
22685        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22686                && li.mOnDragListener.onDrag(this, event)) {
22687            result = true;
22688        } else {
22689            result = onDragEvent(event);
22690        }
22691
22692        switch (event.mAction) {
22693            case DragEvent.ACTION_DRAG_ENTERED: {
22694                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22695                refreshDrawableState();
22696            } break;
22697            case DragEvent.ACTION_DRAG_EXITED: {
22698                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22699                refreshDrawableState();
22700            } break;
22701            case DragEvent.ACTION_DRAG_ENDED: {
22702                mPrivateFlags2 &= ~View.DRAG_MASK;
22703                refreshDrawableState();
22704            } break;
22705        }
22706
22707        return result;
22708    }
22709
22710    boolean canAcceptDrag() {
22711        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22712    }
22713
22714    /**
22715     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22716     * it is ever exposed at all.
22717     * @hide
22718     */
22719    public void onCloseSystemDialogs(String reason) {
22720    }
22721
22722    /**
22723     * Given a Drawable whose bounds have been set to draw into this view,
22724     * update a Region being computed for
22725     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22726     * that any non-transparent parts of the Drawable are removed from the
22727     * given transparent region.
22728     *
22729     * @param dr The Drawable whose transparency is to be applied to the region.
22730     * @param region A Region holding the current transparency information,
22731     * where any parts of the region that are set are considered to be
22732     * transparent.  On return, this region will be modified to have the
22733     * transparency information reduced by the corresponding parts of the
22734     * Drawable that are not transparent.
22735     * {@hide}
22736     */
22737    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22738        if (DBG) {
22739            Log.i("View", "Getting transparent region for: " + this);
22740        }
22741        final Region r = dr.getTransparentRegion();
22742        final Rect db = dr.getBounds();
22743        final AttachInfo attachInfo = mAttachInfo;
22744        if (r != null && attachInfo != null) {
22745            final int w = getRight()-getLeft();
22746            final int h = getBottom()-getTop();
22747            if (db.left > 0) {
22748                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22749                r.op(0, 0, db.left, h, Region.Op.UNION);
22750            }
22751            if (db.right < w) {
22752                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22753                r.op(db.right, 0, w, h, Region.Op.UNION);
22754            }
22755            if (db.top > 0) {
22756                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22757                r.op(0, 0, w, db.top, Region.Op.UNION);
22758            }
22759            if (db.bottom < h) {
22760                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22761                r.op(0, db.bottom, w, h, Region.Op.UNION);
22762            }
22763            final int[] location = attachInfo.mTransparentLocation;
22764            getLocationInWindow(location);
22765            r.translate(location[0], location[1]);
22766            region.op(r, Region.Op.INTERSECT);
22767        } else {
22768            region.op(db, Region.Op.DIFFERENCE);
22769        }
22770    }
22771
22772    private void checkForLongClick(int delayOffset, float x, float y) {
22773        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22774            mHasPerformedLongPress = false;
22775
22776            if (mPendingCheckForLongPress == null) {
22777                mPendingCheckForLongPress = new CheckForLongPress();
22778            }
22779            mPendingCheckForLongPress.setAnchor(x, y);
22780            mPendingCheckForLongPress.rememberWindowAttachCount();
22781            mPendingCheckForLongPress.rememberPressedState();
22782            postDelayed(mPendingCheckForLongPress,
22783                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22784        }
22785    }
22786
22787    /**
22788     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22789     * LayoutInflater} class, which provides a full range of options for view inflation.
22790     *
22791     * @param context The Context object for your activity or application.
22792     * @param resource The resource ID to inflate
22793     * @param root A view group that will be the parent.  Used to properly inflate the
22794     * layout_* parameters.
22795     * @see LayoutInflater
22796     */
22797    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22798        LayoutInflater factory = LayoutInflater.from(context);
22799        return factory.inflate(resource, root);
22800    }
22801
22802    /**
22803     * Scroll the view with standard behavior for scrolling beyond the normal
22804     * content boundaries. Views that call this method should override
22805     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22806     * results of an over-scroll operation.
22807     *
22808     * Views can use this method to handle any touch or fling-based scrolling.
22809     *
22810     * @param deltaX Change in X in pixels
22811     * @param deltaY Change in Y in pixels
22812     * @param scrollX Current X scroll value in pixels before applying deltaX
22813     * @param scrollY Current Y scroll value in pixels before applying deltaY
22814     * @param scrollRangeX Maximum content scroll range along the X axis
22815     * @param scrollRangeY Maximum content scroll range along the Y axis
22816     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22817     *          along the X axis.
22818     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22819     *          along the Y axis.
22820     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22821     * @return true if scrolling was clamped to an over-scroll boundary along either
22822     *          axis, false otherwise.
22823     */
22824    @SuppressWarnings({"UnusedParameters"})
22825    protected boolean overScrollBy(int deltaX, int deltaY,
22826            int scrollX, int scrollY,
22827            int scrollRangeX, int scrollRangeY,
22828            int maxOverScrollX, int maxOverScrollY,
22829            boolean isTouchEvent) {
22830        final int overScrollMode = mOverScrollMode;
22831        final boolean canScrollHorizontal =
22832                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22833        final boolean canScrollVertical =
22834                computeVerticalScrollRange() > computeVerticalScrollExtent();
22835        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22836                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22837        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22838                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22839
22840        int newScrollX = scrollX + deltaX;
22841        if (!overScrollHorizontal) {
22842            maxOverScrollX = 0;
22843        }
22844
22845        int newScrollY = scrollY + deltaY;
22846        if (!overScrollVertical) {
22847            maxOverScrollY = 0;
22848        }
22849
22850        // Clamp values if at the limits and record
22851        final int left = -maxOverScrollX;
22852        final int right = maxOverScrollX + scrollRangeX;
22853        final int top = -maxOverScrollY;
22854        final int bottom = maxOverScrollY + scrollRangeY;
22855
22856        boolean clampedX = false;
22857        if (newScrollX > right) {
22858            newScrollX = right;
22859            clampedX = true;
22860        } else if (newScrollX < left) {
22861            newScrollX = left;
22862            clampedX = true;
22863        }
22864
22865        boolean clampedY = false;
22866        if (newScrollY > bottom) {
22867            newScrollY = bottom;
22868            clampedY = true;
22869        } else if (newScrollY < top) {
22870            newScrollY = top;
22871            clampedY = true;
22872        }
22873
22874        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22875
22876        return clampedX || clampedY;
22877    }
22878
22879    /**
22880     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22881     * respond to the results of an over-scroll operation.
22882     *
22883     * @param scrollX New X scroll value in pixels
22884     * @param scrollY New Y scroll value in pixels
22885     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22886     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22887     */
22888    protected void onOverScrolled(int scrollX, int scrollY,
22889            boolean clampedX, boolean clampedY) {
22890        // Intentionally empty.
22891    }
22892
22893    /**
22894     * Returns the over-scroll mode for this view. The result will be
22895     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22896     * (allow over-scrolling only if the view content is larger than the container),
22897     * or {@link #OVER_SCROLL_NEVER}.
22898     *
22899     * @return This view's over-scroll mode.
22900     */
22901    public int getOverScrollMode() {
22902        return mOverScrollMode;
22903    }
22904
22905    /**
22906     * Set the over-scroll mode for this view. Valid over-scroll modes are
22907     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22908     * (allow over-scrolling only if the view content is larger than the container),
22909     * or {@link #OVER_SCROLL_NEVER}.
22910     *
22911     * Setting the over-scroll mode of a view will have an effect only if the
22912     * view is capable of scrolling.
22913     *
22914     * @param overScrollMode The new over-scroll mode for this view.
22915     */
22916    public void setOverScrollMode(int overScrollMode) {
22917        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22918                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22919                overScrollMode != OVER_SCROLL_NEVER) {
22920            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22921        }
22922        mOverScrollMode = overScrollMode;
22923    }
22924
22925    /**
22926     * Enable or disable nested scrolling for this view.
22927     *
22928     * <p>If this property is set to true the view will be permitted to initiate nested
22929     * scrolling operations with a compatible parent view in the current hierarchy. If this
22930     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22931     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22932     * the nested scroll.</p>
22933     *
22934     * @param enabled true to enable nested scrolling, false to disable
22935     *
22936     * @see #isNestedScrollingEnabled()
22937     */
22938    public void setNestedScrollingEnabled(boolean enabled) {
22939        if (enabled) {
22940            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22941        } else {
22942            stopNestedScroll();
22943            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22944        }
22945    }
22946
22947    /**
22948     * Returns true if nested scrolling is enabled for this view.
22949     *
22950     * <p>If nested scrolling is enabled and this View class implementation supports it,
22951     * this view will act as a nested scrolling child view when applicable, forwarding data
22952     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22953     * parent.</p>
22954     *
22955     * @return true if nested scrolling is enabled
22956     *
22957     * @see #setNestedScrollingEnabled(boolean)
22958     */
22959    public boolean isNestedScrollingEnabled() {
22960        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22961                PFLAG3_NESTED_SCROLLING_ENABLED;
22962    }
22963
22964    /**
22965     * Begin a nestable scroll operation along the given axes.
22966     *
22967     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22968     *
22969     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22970     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22971     * In the case of touch scrolling the nested scroll will be terminated automatically in
22972     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22973     * In the event of programmatic scrolling the caller must explicitly call
22974     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22975     *
22976     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22977     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22978     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22979     *
22980     * <p>At each incremental step of the scroll the caller should invoke
22981     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22982     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22983     * parent at least partially consumed the scroll and the caller should adjust the amount it
22984     * scrolls by.</p>
22985     *
22986     * <p>After applying the remainder of the scroll delta the caller should invoke
22987     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22988     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22989     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22990     * </p>
22991     *
22992     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22993     *             {@link #SCROLL_AXIS_VERTICAL}.
22994     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22995     *         the current gesture.
22996     *
22997     * @see #stopNestedScroll()
22998     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22999     * @see #dispatchNestedScroll(int, int, int, int, int[])
23000     */
23001    public boolean startNestedScroll(int axes) {
23002        if (hasNestedScrollingParent()) {
23003            // Already in progress
23004            return true;
23005        }
23006        if (isNestedScrollingEnabled()) {
23007            ViewParent p = getParent();
23008            View child = this;
23009            while (p != null) {
23010                try {
23011                    if (p.onStartNestedScroll(child, this, axes)) {
23012                        mNestedScrollingParent = p;
23013                        p.onNestedScrollAccepted(child, this, axes);
23014                        return true;
23015                    }
23016                } catch (AbstractMethodError e) {
23017                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23018                            "method onStartNestedScroll", e);
23019                    // Allow the search upward to continue
23020                }
23021                if (p instanceof View) {
23022                    child = (View) p;
23023                }
23024                p = p.getParent();
23025            }
23026        }
23027        return false;
23028    }
23029
23030    /**
23031     * Stop a nested scroll in progress.
23032     *
23033     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23034     *
23035     * @see #startNestedScroll(int)
23036     */
23037    public void stopNestedScroll() {
23038        if (mNestedScrollingParent != null) {
23039            mNestedScrollingParent.onStopNestedScroll(this);
23040            mNestedScrollingParent = null;
23041        }
23042    }
23043
23044    /**
23045     * Returns true if this view has a nested scrolling parent.
23046     *
23047     * <p>The presence of a nested scrolling parent indicates that this view has initiated
23048     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23049     *
23050     * @return whether this view has a nested scrolling parent
23051     */
23052    public boolean hasNestedScrollingParent() {
23053        return mNestedScrollingParent != null;
23054    }
23055
23056    /**
23057     * Dispatch one step of a nested scroll in progress.
23058     *
23059     * <p>Implementations of views that support nested scrolling should call this to report
23060     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23061     * is not currently in progress or nested scrolling is not
23062     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23063     *
23064     * <p>Compatible View implementations should also call
23065     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23066     * consuming a component of the scroll event themselves.</p>
23067     *
23068     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23069     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23070     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23071     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23072     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23073     *                       in local view coordinates of this view from before this operation
23074     *                       to after it completes. View implementations may use this to adjust
23075     *                       expected input coordinate tracking.
23076     * @return true if the event was dispatched, false if it could not be dispatched.
23077     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23078     */
23079    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23080            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23081        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23082            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23083                int startX = 0;
23084                int startY = 0;
23085                if (offsetInWindow != null) {
23086                    getLocationInWindow(offsetInWindow);
23087                    startX = offsetInWindow[0];
23088                    startY = offsetInWindow[1];
23089                }
23090
23091                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23092                        dxUnconsumed, dyUnconsumed);
23093
23094                if (offsetInWindow != null) {
23095                    getLocationInWindow(offsetInWindow);
23096                    offsetInWindow[0] -= startX;
23097                    offsetInWindow[1] -= startY;
23098                }
23099                return true;
23100            } else if (offsetInWindow != null) {
23101                // No motion, no dispatch. Keep offsetInWindow up to date.
23102                offsetInWindow[0] = 0;
23103                offsetInWindow[1] = 0;
23104            }
23105        }
23106        return false;
23107    }
23108
23109    /**
23110     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23111     *
23112     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23113     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23114     * scrolling operation to consume some or all of the scroll operation before the child view
23115     * consumes it.</p>
23116     *
23117     * @param dx Horizontal scroll distance in pixels
23118     * @param dy Vertical scroll distance in pixels
23119     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23120     *                 and consumed[1] the consumed dy.
23121     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23122     *                       in local view coordinates of this view from before this operation
23123     *                       to after it completes. View implementations may use this to adjust
23124     *                       expected input coordinate tracking.
23125     * @return true if the parent consumed some or all of the scroll delta
23126     * @see #dispatchNestedScroll(int, int, int, int, int[])
23127     */
23128    public boolean dispatchNestedPreScroll(int dx, int dy,
23129            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23130        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23131            if (dx != 0 || dy != 0) {
23132                int startX = 0;
23133                int startY = 0;
23134                if (offsetInWindow != null) {
23135                    getLocationInWindow(offsetInWindow);
23136                    startX = offsetInWindow[0];
23137                    startY = offsetInWindow[1];
23138                }
23139
23140                if (consumed == null) {
23141                    if (mTempNestedScrollConsumed == null) {
23142                        mTempNestedScrollConsumed = new int[2];
23143                    }
23144                    consumed = mTempNestedScrollConsumed;
23145                }
23146                consumed[0] = 0;
23147                consumed[1] = 0;
23148                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23149
23150                if (offsetInWindow != null) {
23151                    getLocationInWindow(offsetInWindow);
23152                    offsetInWindow[0] -= startX;
23153                    offsetInWindow[1] -= startY;
23154                }
23155                return consumed[0] != 0 || consumed[1] != 0;
23156            } else if (offsetInWindow != null) {
23157                offsetInWindow[0] = 0;
23158                offsetInWindow[1] = 0;
23159            }
23160        }
23161        return false;
23162    }
23163
23164    /**
23165     * Dispatch a fling to a nested scrolling parent.
23166     *
23167     * <p>This method should be used to indicate that a nested scrolling child has detected
23168     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23169     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23170     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23171     * along a scrollable axis.</p>
23172     *
23173     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23174     * its own content, it can use this method to delegate the fling to its nested scrolling
23175     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23176     *
23177     * @param velocityX Horizontal fling velocity in pixels per second
23178     * @param velocityY Vertical fling velocity in pixels per second
23179     * @param consumed true if the child consumed the fling, false otherwise
23180     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23181     */
23182    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23183        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23184            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23185        }
23186        return false;
23187    }
23188
23189    /**
23190     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23191     *
23192     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23193     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23194     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23195     * before the child view consumes it. If this method returns <code>true</code>, a nested
23196     * parent view consumed the fling and this view should not scroll as a result.</p>
23197     *
23198     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23199     * the fling at a time. If a parent view consumed the fling this method will return false.
23200     * Custom view implementations should account for this in two ways:</p>
23201     *
23202     * <ul>
23203     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23204     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23205     *     position regardless.</li>
23206     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23207     *     even to settle back to a valid idle position.</li>
23208     * </ul>
23209     *
23210     * <p>Views should also not offer fling velocities to nested parent views along an axis
23211     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23212     * should not offer a horizontal fling velocity to its parents since scrolling along that
23213     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23214     *
23215     * @param velocityX Horizontal fling velocity in pixels per second
23216     * @param velocityY Vertical fling velocity in pixels per second
23217     * @return true if a nested scrolling parent consumed the fling
23218     */
23219    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23220        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23221            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23222        }
23223        return false;
23224    }
23225
23226    /**
23227     * Gets a scale factor that determines the distance the view should scroll
23228     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23229     * @return The vertical scroll scale factor.
23230     * @hide
23231     */
23232    protected float getVerticalScrollFactor() {
23233        if (mVerticalScrollFactor == 0) {
23234            TypedValue outValue = new TypedValue();
23235            if (!mContext.getTheme().resolveAttribute(
23236                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23237                throw new IllegalStateException(
23238                        "Expected theme to define listPreferredItemHeight.");
23239            }
23240            mVerticalScrollFactor = outValue.getDimension(
23241                    mContext.getResources().getDisplayMetrics());
23242        }
23243        return mVerticalScrollFactor;
23244    }
23245
23246    /**
23247     * Gets a scale factor that determines the distance the view should scroll
23248     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23249     * @return The horizontal scroll scale factor.
23250     * @hide
23251     */
23252    protected float getHorizontalScrollFactor() {
23253        // TODO: Should use something else.
23254        return getVerticalScrollFactor();
23255    }
23256
23257    /**
23258     * Return the value specifying the text direction or policy that was set with
23259     * {@link #setTextDirection(int)}.
23260     *
23261     * @return the defined text direction. It can be one of:
23262     *
23263     * {@link #TEXT_DIRECTION_INHERIT},
23264     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23265     * {@link #TEXT_DIRECTION_ANY_RTL},
23266     * {@link #TEXT_DIRECTION_LTR},
23267     * {@link #TEXT_DIRECTION_RTL},
23268     * {@link #TEXT_DIRECTION_LOCALE},
23269     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23270     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23271     *
23272     * @attr ref android.R.styleable#View_textDirection
23273     *
23274     * @hide
23275     */
23276    @ViewDebug.ExportedProperty(category = "text", mapping = {
23277            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23278            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23279            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23280            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23281            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23282            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23283            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23284            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23285    })
23286    public int getRawTextDirection() {
23287        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23288    }
23289
23290    /**
23291     * Set the text direction.
23292     *
23293     * @param textDirection the direction to set. Should be one of:
23294     *
23295     * {@link #TEXT_DIRECTION_INHERIT},
23296     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23297     * {@link #TEXT_DIRECTION_ANY_RTL},
23298     * {@link #TEXT_DIRECTION_LTR},
23299     * {@link #TEXT_DIRECTION_RTL},
23300     * {@link #TEXT_DIRECTION_LOCALE}
23301     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23302     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23303     *
23304     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23305     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23306     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23307     *
23308     * @attr ref android.R.styleable#View_textDirection
23309     */
23310    public void setTextDirection(int textDirection) {
23311        if (getRawTextDirection() != textDirection) {
23312            // Reset the current text direction and the resolved one
23313            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23314            resetResolvedTextDirection();
23315            // Set the new text direction
23316            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23317            // Do resolution
23318            resolveTextDirection();
23319            // Notify change
23320            onRtlPropertiesChanged(getLayoutDirection());
23321            // Refresh
23322            requestLayout();
23323            invalidate(true);
23324        }
23325    }
23326
23327    /**
23328     * Return the resolved text direction.
23329     *
23330     * @return the resolved text direction. Returns one of:
23331     *
23332     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23333     * {@link #TEXT_DIRECTION_ANY_RTL},
23334     * {@link #TEXT_DIRECTION_LTR},
23335     * {@link #TEXT_DIRECTION_RTL},
23336     * {@link #TEXT_DIRECTION_LOCALE},
23337     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23338     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23339     *
23340     * @attr ref android.R.styleable#View_textDirection
23341     */
23342    @ViewDebug.ExportedProperty(category = "text", mapping = {
23343            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23344            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23345            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23346            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23347            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23348            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23349            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23350            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23351    })
23352    public int getTextDirection() {
23353        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23354    }
23355
23356    /**
23357     * Resolve the text direction.
23358     *
23359     * @return true if resolution has been done, false otherwise.
23360     *
23361     * @hide
23362     */
23363    public boolean resolveTextDirection() {
23364        // Reset any previous text direction resolution
23365        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23366
23367        if (hasRtlSupport()) {
23368            // Set resolved text direction flag depending on text direction flag
23369            final int textDirection = getRawTextDirection();
23370            switch(textDirection) {
23371                case TEXT_DIRECTION_INHERIT:
23372                    if (!canResolveTextDirection()) {
23373                        // We cannot do the resolution if there is no parent, so use the default one
23374                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23375                        // Resolution will need to happen again later
23376                        return false;
23377                    }
23378
23379                    // Parent has not yet resolved, so we still return the default
23380                    try {
23381                        if (!mParent.isTextDirectionResolved()) {
23382                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23383                            // Resolution will need to happen again later
23384                            return false;
23385                        }
23386                    } catch (AbstractMethodError e) {
23387                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23388                                " does not fully implement ViewParent", e);
23389                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23390                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23391                        return true;
23392                    }
23393
23394                    // Set current resolved direction to the same value as the parent's one
23395                    int parentResolvedDirection;
23396                    try {
23397                        parentResolvedDirection = mParent.getTextDirection();
23398                    } catch (AbstractMethodError e) {
23399                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23400                                " does not fully implement ViewParent", e);
23401                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23402                    }
23403                    switch (parentResolvedDirection) {
23404                        case TEXT_DIRECTION_FIRST_STRONG:
23405                        case TEXT_DIRECTION_ANY_RTL:
23406                        case TEXT_DIRECTION_LTR:
23407                        case TEXT_DIRECTION_RTL:
23408                        case TEXT_DIRECTION_LOCALE:
23409                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23410                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23411                            mPrivateFlags2 |=
23412                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23413                            break;
23414                        default:
23415                            // Default resolved direction is "first strong" heuristic
23416                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23417                    }
23418                    break;
23419                case TEXT_DIRECTION_FIRST_STRONG:
23420                case TEXT_DIRECTION_ANY_RTL:
23421                case TEXT_DIRECTION_LTR:
23422                case TEXT_DIRECTION_RTL:
23423                case TEXT_DIRECTION_LOCALE:
23424                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23425                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23426                    // Resolved direction is the same as text direction
23427                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23428                    break;
23429                default:
23430                    // Default resolved direction is "first strong" heuristic
23431                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23432            }
23433        } else {
23434            // Default resolved direction is "first strong" heuristic
23435            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23436        }
23437
23438        // Set to resolved
23439        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23440        return true;
23441    }
23442
23443    /**
23444     * Check if text direction resolution can be done.
23445     *
23446     * @return true if text direction resolution can be done otherwise return false.
23447     */
23448    public boolean canResolveTextDirection() {
23449        switch (getRawTextDirection()) {
23450            case TEXT_DIRECTION_INHERIT:
23451                if (mParent != null) {
23452                    try {
23453                        return mParent.canResolveTextDirection();
23454                    } catch (AbstractMethodError e) {
23455                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23456                                " does not fully implement ViewParent", e);
23457                    }
23458                }
23459                return false;
23460
23461            default:
23462                return true;
23463        }
23464    }
23465
23466    /**
23467     * Reset resolved text direction. Text direction will be resolved during a call to
23468     * {@link #onMeasure(int, int)}.
23469     *
23470     * @hide
23471     */
23472    public void resetResolvedTextDirection() {
23473        // Reset any previous text direction resolution
23474        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23475        // Set to default value
23476        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23477    }
23478
23479    /**
23480     * @return true if text direction is inherited.
23481     *
23482     * @hide
23483     */
23484    public boolean isTextDirectionInherited() {
23485        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23486    }
23487
23488    /**
23489     * @return true if text direction is resolved.
23490     */
23491    public boolean isTextDirectionResolved() {
23492        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23493    }
23494
23495    /**
23496     * Return the value specifying the text alignment or policy that was set with
23497     * {@link #setTextAlignment(int)}.
23498     *
23499     * @return the defined text alignment. It can be one of:
23500     *
23501     * {@link #TEXT_ALIGNMENT_INHERIT},
23502     * {@link #TEXT_ALIGNMENT_GRAVITY},
23503     * {@link #TEXT_ALIGNMENT_CENTER},
23504     * {@link #TEXT_ALIGNMENT_TEXT_START},
23505     * {@link #TEXT_ALIGNMENT_TEXT_END},
23506     * {@link #TEXT_ALIGNMENT_VIEW_START},
23507     * {@link #TEXT_ALIGNMENT_VIEW_END}
23508     *
23509     * @attr ref android.R.styleable#View_textAlignment
23510     *
23511     * @hide
23512     */
23513    @ViewDebug.ExportedProperty(category = "text", mapping = {
23514            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23515            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23516            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23517            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23518            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23519            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23520            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23521    })
23522    @TextAlignment
23523    public int getRawTextAlignment() {
23524        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23525    }
23526
23527    /**
23528     * Set the text alignment.
23529     *
23530     * @param textAlignment The text alignment to set. Should be one of
23531     *
23532     * {@link #TEXT_ALIGNMENT_INHERIT},
23533     * {@link #TEXT_ALIGNMENT_GRAVITY},
23534     * {@link #TEXT_ALIGNMENT_CENTER},
23535     * {@link #TEXT_ALIGNMENT_TEXT_START},
23536     * {@link #TEXT_ALIGNMENT_TEXT_END},
23537     * {@link #TEXT_ALIGNMENT_VIEW_START},
23538     * {@link #TEXT_ALIGNMENT_VIEW_END}
23539     *
23540     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23541     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23542     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23543     *
23544     * @attr ref android.R.styleable#View_textAlignment
23545     */
23546    public void setTextAlignment(@TextAlignment int textAlignment) {
23547        if (textAlignment != getRawTextAlignment()) {
23548            // Reset the current and resolved text alignment
23549            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23550            resetResolvedTextAlignment();
23551            // Set the new text alignment
23552            mPrivateFlags2 |=
23553                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23554            // Do resolution
23555            resolveTextAlignment();
23556            // Notify change
23557            onRtlPropertiesChanged(getLayoutDirection());
23558            // Refresh
23559            requestLayout();
23560            invalidate(true);
23561        }
23562    }
23563
23564    /**
23565     * Return the resolved text alignment.
23566     *
23567     * @return the resolved text alignment. Returns one of:
23568     *
23569     * {@link #TEXT_ALIGNMENT_GRAVITY},
23570     * {@link #TEXT_ALIGNMENT_CENTER},
23571     * {@link #TEXT_ALIGNMENT_TEXT_START},
23572     * {@link #TEXT_ALIGNMENT_TEXT_END},
23573     * {@link #TEXT_ALIGNMENT_VIEW_START},
23574     * {@link #TEXT_ALIGNMENT_VIEW_END}
23575     *
23576     * @attr ref android.R.styleable#View_textAlignment
23577     */
23578    @ViewDebug.ExportedProperty(category = "text", mapping = {
23579            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23580            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23581            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23582            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23583            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23584            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23585            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23586    })
23587    @TextAlignment
23588    public int getTextAlignment() {
23589        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23590                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23591    }
23592
23593    /**
23594     * Resolve the text alignment.
23595     *
23596     * @return true if resolution has been done, false otherwise.
23597     *
23598     * @hide
23599     */
23600    public boolean resolveTextAlignment() {
23601        // Reset any previous text alignment resolution
23602        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23603
23604        if (hasRtlSupport()) {
23605            // Set resolved text alignment flag depending on text alignment flag
23606            final int textAlignment = getRawTextAlignment();
23607            switch (textAlignment) {
23608                case TEXT_ALIGNMENT_INHERIT:
23609                    // Check if we can resolve the text alignment
23610                    if (!canResolveTextAlignment()) {
23611                        // We cannot do the resolution if there is no parent so use the default
23612                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23613                        // Resolution will need to happen again later
23614                        return false;
23615                    }
23616
23617                    // Parent has not yet resolved, so we still return the default
23618                    try {
23619                        if (!mParent.isTextAlignmentResolved()) {
23620                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23621                            // Resolution will need to happen again later
23622                            return false;
23623                        }
23624                    } catch (AbstractMethodError e) {
23625                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23626                                " does not fully implement ViewParent", e);
23627                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23628                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23629                        return true;
23630                    }
23631
23632                    int parentResolvedTextAlignment;
23633                    try {
23634                        parentResolvedTextAlignment = mParent.getTextAlignment();
23635                    } catch (AbstractMethodError e) {
23636                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23637                                " does not fully implement ViewParent", e);
23638                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23639                    }
23640                    switch (parentResolvedTextAlignment) {
23641                        case TEXT_ALIGNMENT_GRAVITY:
23642                        case TEXT_ALIGNMENT_TEXT_START:
23643                        case TEXT_ALIGNMENT_TEXT_END:
23644                        case TEXT_ALIGNMENT_CENTER:
23645                        case TEXT_ALIGNMENT_VIEW_START:
23646                        case TEXT_ALIGNMENT_VIEW_END:
23647                            // Resolved text alignment is the same as the parent resolved
23648                            // text alignment
23649                            mPrivateFlags2 |=
23650                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23651                            break;
23652                        default:
23653                            // Use default resolved text alignment
23654                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23655                    }
23656                    break;
23657                case TEXT_ALIGNMENT_GRAVITY:
23658                case TEXT_ALIGNMENT_TEXT_START:
23659                case TEXT_ALIGNMENT_TEXT_END:
23660                case TEXT_ALIGNMENT_CENTER:
23661                case TEXT_ALIGNMENT_VIEW_START:
23662                case TEXT_ALIGNMENT_VIEW_END:
23663                    // Resolved text alignment is the same as text alignment
23664                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23665                    break;
23666                default:
23667                    // Use default resolved text alignment
23668                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23669            }
23670        } else {
23671            // Use default resolved text alignment
23672            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23673        }
23674
23675        // Set the resolved
23676        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23677        return true;
23678    }
23679
23680    /**
23681     * Check if text alignment resolution can be done.
23682     *
23683     * @return true if text alignment resolution can be done otherwise return false.
23684     */
23685    public boolean canResolveTextAlignment() {
23686        switch (getRawTextAlignment()) {
23687            case TEXT_DIRECTION_INHERIT:
23688                if (mParent != null) {
23689                    try {
23690                        return mParent.canResolveTextAlignment();
23691                    } catch (AbstractMethodError e) {
23692                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23693                                " does not fully implement ViewParent", e);
23694                    }
23695                }
23696                return false;
23697
23698            default:
23699                return true;
23700        }
23701    }
23702
23703    /**
23704     * Reset resolved text alignment. Text alignment will be resolved during a call to
23705     * {@link #onMeasure(int, int)}.
23706     *
23707     * @hide
23708     */
23709    public void resetResolvedTextAlignment() {
23710        // Reset any previous text alignment resolution
23711        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23712        // Set to default
23713        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23714    }
23715
23716    /**
23717     * @return true if text alignment is inherited.
23718     *
23719     * @hide
23720     */
23721    public boolean isTextAlignmentInherited() {
23722        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23723    }
23724
23725    /**
23726     * @return true if text alignment is resolved.
23727     */
23728    public boolean isTextAlignmentResolved() {
23729        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23730    }
23731
23732    /**
23733     * Generate a value suitable for use in {@link #setId(int)}.
23734     * This value will not collide with ID values generated at build time by aapt for R.id.
23735     *
23736     * @return a generated ID value
23737     */
23738    public static int generateViewId() {
23739        for (;;) {
23740            final int result = sNextGeneratedId.get();
23741            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23742            int newValue = result + 1;
23743            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23744            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23745                return result;
23746            }
23747        }
23748    }
23749
23750    private static boolean isViewIdGenerated(int id) {
23751        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23752    }
23753
23754    /**
23755     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23756     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23757     *                           a normal View or a ViewGroup with
23758     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23759     * @hide
23760     */
23761    public void captureTransitioningViews(List<View> transitioningViews) {
23762        if (getVisibility() == View.VISIBLE) {
23763            transitioningViews.add(this);
23764        }
23765    }
23766
23767    /**
23768     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23769     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23770     * @hide
23771     */
23772    public void findNamedViews(Map<String, View> namedElements) {
23773        if (getVisibility() == VISIBLE || mGhostView != null) {
23774            String transitionName = getTransitionName();
23775            if (transitionName != null) {
23776                namedElements.put(transitionName, this);
23777            }
23778        }
23779    }
23780
23781    /**
23782     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23783     * The default implementation does not care the location or event types, but some subclasses
23784     * may use it (such as WebViews).
23785     * @param event The MotionEvent from a mouse
23786     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23787     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23788     * @see PointerIcon
23789     */
23790    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23791        final float x = event.getX(pointerIndex);
23792        final float y = event.getY(pointerIndex);
23793        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23794            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23795        }
23796        return mPointerIcon;
23797    }
23798
23799    /**
23800     * Set the pointer icon for the current view.
23801     * Passing {@code null} will restore the pointer icon to its default value.
23802     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23803     */
23804    public void setPointerIcon(PointerIcon pointerIcon) {
23805        mPointerIcon = pointerIcon;
23806        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23807            return;
23808        }
23809        try {
23810            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23811        } catch (RemoteException e) {
23812        }
23813    }
23814
23815    /**
23816     * Gets the pointer icon for the current view.
23817     */
23818    public PointerIcon getPointerIcon() {
23819        return mPointerIcon;
23820    }
23821
23822    /**
23823     * Checks pointer capture status.
23824     *
23825     * @return true if the view has pointer capture.
23826     * @see #requestPointerCapture()
23827     * @see #hasPointerCapture()
23828     */
23829    public boolean hasPointerCapture() {
23830        final ViewRootImpl viewRootImpl = getViewRootImpl();
23831        if (viewRootImpl == null) {
23832            return false;
23833        }
23834        return viewRootImpl.hasPointerCapture();
23835    }
23836
23837    /**
23838     * Requests pointer capture mode.
23839     * <p>
23840     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23841     * change its position. Further mouse will be dispatched with the source
23842     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23843     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23844     * (touchscreens, or stylus) will not be affected.
23845     * <p>
23846     * If the window already has pointer capture, this call does nothing.
23847     * <p>
23848     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23849     * automatically when the window loses focus.
23850     *
23851     * @see #releasePointerCapture()
23852     * @see #hasPointerCapture()
23853     */
23854    public void requestPointerCapture() {
23855        final ViewRootImpl viewRootImpl = getViewRootImpl();
23856        if (viewRootImpl != null) {
23857            viewRootImpl.requestPointerCapture(true);
23858        }
23859    }
23860
23861
23862    /**
23863     * Releases the pointer capture.
23864     * <p>
23865     * If the window does not have pointer capture, this call will do nothing.
23866     * @see #requestPointerCapture()
23867     * @see #hasPointerCapture()
23868     */
23869    public void releasePointerCapture() {
23870        final ViewRootImpl viewRootImpl = getViewRootImpl();
23871        if (viewRootImpl != null) {
23872            viewRootImpl.requestPointerCapture(false);
23873        }
23874    }
23875
23876    /**
23877     * Called when the window has just acquired or lost pointer capture.
23878     *
23879     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23880     */
23881    @CallSuper
23882    public void onPointerCaptureChange(boolean hasCapture) {
23883    }
23884
23885    /**
23886     * @see #onPointerCaptureChange
23887     */
23888    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23889        onPointerCaptureChange(hasCapture);
23890    }
23891
23892    /**
23893     * Implement this method to handle captured pointer events
23894     *
23895     * @param event The captured pointer event.
23896     * @return True if the event was handled, false otherwise.
23897     * @see #requestPointerCapture()
23898     */
23899    public boolean onCapturedPointerEvent(MotionEvent event) {
23900        return false;
23901    }
23902
23903    /**
23904     * Interface definition for a callback to be invoked when a captured pointer event
23905     * is being dispatched this view. The callback will be invoked before the event is
23906     * given to the view.
23907     */
23908    public interface OnCapturedPointerListener {
23909        /**
23910         * Called when a captured pointer event is dispatched to a view.
23911         * @param view The view this event has been dispatched to.
23912         * @param event The captured event.
23913         * @return True if the listener has consumed the event, false otherwise.
23914         */
23915        boolean onCapturedPointer(View view, MotionEvent event);
23916    }
23917
23918    /**
23919     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23920     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23921     */
23922    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23923        getListenerInfo().mOnCapturedPointerListener = l;
23924    }
23925
23926    // Properties
23927    //
23928    /**
23929     * A Property wrapper around the <code>alpha</code> functionality handled by the
23930     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23931     */
23932    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23933        @Override
23934        public void setValue(View object, float value) {
23935            object.setAlpha(value);
23936        }
23937
23938        @Override
23939        public Float get(View object) {
23940            return object.getAlpha();
23941        }
23942    };
23943
23944    /**
23945     * A Property wrapper around the <code>translationX</code> functionality handled by the
23946     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23947     */
23948    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23949        @Override
23950        public void setValue(View object, float value) {
23951            object.setTranslationX(value);
23952        }
23953
23954                @Override
23955        public Float get(View object) {
23956            return object.getTranslationX();
23957        }
23958    };
23959
23960    /**
23961     * A Property wrapper around the <code>translationY</code> functionality handled by the
23962     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23963     */
23964    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23965        @Override
23966        public void setValue(View object, float value) {
23967            object.setTranslationY(value);
23968        }
23969
23970        @Override
23971        public Float get(View object) {
23972            return object.getTranslationY();
23973        }
23974    };
23975
23976    /**
23977     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23978     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23979     */
23980    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23981        @Override
23982        public void setValue(View object, float value) {
23983            object.setTranslationZ(value);
23984        }
23985
23986        @Override
23987        public Float get(View object) {
23988            return object.getTranslationZ();
23989        }
23990    };
23991
23992    /**
23993     * A Property wrapper around the <code>x</code> functionality handled by the
23994     * {@link View#setX(float)} and {@link View#getX()} methods.
23995     */
23996    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23997        @Override
23998        public void setValue(View object, float value) {
23999            object.setX(value);
24000        }
24001
24002        @Override
24003        public Float get(View object) {
24004            return object.getX();
24005        }
24006    };
24007
24008    /**
24009     * A Property wrapper around the <code>y</code> functionality handled by the
24010     * {@link View#setY(float)} and {@link View#getY()} methods.
24011     */
24012    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24013        @Override
24014        public void setValue(View object, float value) {
24015            object.setY(value);
24016        }
24017
24018        @Override
24019        public Float get(View object) {
24020            return object.getY();
24021        }
24022    };
24023
24024    /**
24025     * A Property wrapper around the <code>z</code> functionality handled by the
24026     * {@link View#setZ(float)} and {@link View#getZ()} methods.
24027     */
24028    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24029        @Override
24030        public void setValue(View object, float value) {
24031            object.setZ(value);
24032        }
24033
24034        @Override
24035        public Float get(View object) {
24036            return object.getZ();
24037        }
24038    };
24039
24040    /**
24041     * A Property wrapper around the <code>rotation</code> functionality handled by the
24042     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24043     */
24044    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24045        @Override
24046        public void setValue(View object, float value) {
24047            object.setRotation(value);
24048        }
24049
24050        @Override
24051        public Float get(View object) {
24052            return object.getRotation();
24053        }
24054    };
24055
24056    /**
24057     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24058     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24059     */
24060    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24061        @Override
24062        public void setValue(View object, float value) {
24063            object.setRotationX(value);
24064        }
24065
24066        @Override
24067        public Float get(View object) {
24068            return object.getRotationX();
24069        }
24070    };
24071
24072    /**
24073     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24074     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24075     */
24076    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24077        @Override
24078        public void setValue(View object, float value) {
24079            object.setRotationY(value);
24080        }
24081
24082        @Override
24083        public Float get(View object) {
24084            return object.getRotationY();
24085        }
24086    };
24087
24088    /**
24089     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24090     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24091     */
24092    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24093        @Override
24094        public void setValue(View object, float value) {
24095            object.setScaleX(value);
24096        }
24097
24098        @Override
24099        public Float get(View object) {
24100            return object.getScaleX();
24101        }
24102    };
24103
24104    /**
24105     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24106     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24107     */
24108    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24109        @Override
24110        public void setValue(View object, float value) {
24111            object.setScaleY(value);
24112        }
24113
24114        @Override
24115        public Float get(View object) {
24116            return object.getScaleY();
24117        }
24118    };
24119
24120    /**
24121     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24122     * Each MeasureSpec represents a requirement for either the width or the height.
24123     * A MeasureSpec is comprised of a size and a mode. There are three possible
24124     * modes:
24125     * <dl>
24126     * <dt>UNSPECIFIED</dt>
24127     * <dd>
24128     * The parent has not imposed any constraint on the child. It can be whatever size
24129     * it wants.
24130     * </dd>
24131     *
24132     * <dt>EXACTLY</dt>
24133     * <dd>
24134     * The parent has determined an exact size for the child. The child is going to be
24135     * given those bounds regardless of how big it wants to be.
24136     * </dd>
24137     *
24138     * <dt>AT_MOST</dt>
24139     * <dd>
24140     * The child can be as large as it wants up to the specified size.
24141     * </dd>
24142     * </dl>
24143     *
24144     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24145     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24146     */
24147    public static class MeasureSpec {
24148        private static final int MODE_SHIFT = 30;
24149        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24150
24151        /** @hide */
24152        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24153        @Retention(RetentionPolicy.SOURCE)
24154        public @interface MeasureSpecMode {}
24155
24156        /**
24157         * Measure specification mode: The parent has not imposed any constraint
24158         * on the child. It can be whatever size it wants.
24159         */
24160        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24161
24162        /**
24163         * Measure specification mode: The parent has determined an exact size
24164         * for the child. The child is going to be given those bounds regardless
24165         * of how big it wants to be.
24166         */
24167        public static final int EXACTLY     = 1 << MODE_SHIFT;
24168
24169        /**
24170         * Measure specification mode: The child can be as large as it wants up
24171         * to the specified size.
24172         */
24173        public static final int AT_MOST     = 2 << MODE_SHIFT;
24174
24175        /**
24176         * Creates a measure specification based on the supplied size and mode.
24177         *
24178         * The mode must always be one of the following:
24179         * <ul>
24180         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24181         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24182         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24183         * </ul>
24184         *
24185         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24186         * implementation was such that the order of arguments did not matter
24187         * and overflow in either value could impact the resulting MeasureSpec.
24188         * {@link android.widget.RelativeLayout} was affected by this bug.
24189         * Apps targeting API levels greater than 17 will get the fixed, more strict
24190         * behavior.</p>
24191         *
24192         * @param size the size of the measure specification
24193         * @param mode the mode of the measure specification
24194         * @return the measure specification based on size and mode
24195         */
24196        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24197                                          @MeasureSpecMode int mode) {
24198            if (sUseBrokenMakeMeasureSpec) {
24199                return size + mode;
24200            } else {
24201                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24202            }
24203        }
24204
24205        /**
24206         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24207         * will automatically get a size of 0. Older apps expect this.
24208         *
24209         * @hide internal use only for compatibility with system widgets and older apps
24210         */
24211        public static int makeSafeMeasureSpec(int size, int mode) {
24212            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24213                return 0;
24214            }
24215            return makeMeasureSpec(size, mode);
24216        }
24217
24218        /**
24219         * Extracts the mode from the supplied measure specification.
24220         *
24221         * @param measureSpec the measure specification to extract the mode from
24222         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24223         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24224         *         {@link android.view.View.MeasureSpec#EXACTLY}
24225         */
24226        @MeasureSpecMode
24227        public static int getMode(int measureSpec) {
24228            //noinspection ResourceType
24229            return (measureSpec & MODE_MASK);
24230        }
24231
24232        /**
24233         * Extracts the size from the supplied measure specification.
24234         *
24235         * @param measureSpec the measure specification to extract the size from
24236         * @return the size in pixels defined in the supplied measure specification
24237         */
24238        public static int getSize(int measureSpec) {
24239            return (measureSpec & ~MODE_MASK);
24240        }
24241
24242        static int adjust(int measureSpec, int delta) {
24243            final int mode = getMode(measureSpec);
24244            int size = getSize(measureSpec);
24245            if (mode == UNSPECIFIED) {
24246                // No need to adjust size for UNSPECIFIED mode.
24247                return makeMeasureSpec(size, UNSPECIFIED);
24248            }
24249            size += delta;
24250            if (size < 0) {
24251                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24252                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24253                size = 0;
24254            }
24255            return makeMeasureSpec(size, mode);
24256        }
24257
24258        /**
24259         * Returns a String representation of the specified measure
24260         * specification.
24261         *
24262         * @param measureSpec the measure specification to convert to a String
24263         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24264         */
24265        public static String toString(int measureSpec) {
24266            int mode = getMode(measureSpec);
24267            int size = getSize(measureSpec);
24268
24269            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24270
24271            if (mode == UNSPECIFIED)
24272                sb.append("UNSPECIFIED ");
24273            else if (mode == EXACTLY)
24274                sb.append("EXACTLY ");
24275            else if (mode == AT_MOST)
24276                sb.append("AT_MOST ");
24277            else
24278                sb.append(mode).append(" ");
24279
24280            sb.append(size);
24281            return sb.toString();
24282        }
24283    }
24284
24285    private final class CheckForLongPress implements Runnable {
24286        private int mOriginalWindowAttachCount;
24287        private float mX;
24288        private float mY;
24289        private boolean mOriginalPressedState;
24290
24291        @Override
24292        public void run() {
24293            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24294                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24295                if (performLongClick(mX, mY)) {
24296                    mHasPerformedLongPress = true;
24297                }
24298            }
24299        }
24300
24301        public void setAnchor(float x, float y) {
24302            mX = x;
24303            mY = y;
24304        }
24305
24306        public void rememberWindowAttachCount() {
24307            mOriginalWindowAttachCount = mWindowAttachCount;
24308        }
24309
24310        public void rememberPressedState() {
24311            mOriginalPressedState = isPressed();
24312        }
24313    }
24314
24315    private final class CheckForTap implements Runnable {
24316        public float x;
24317        public float y;
24318
24319        @Override
24320        public void run() {
24321            mPrivateFlags &= ~PFLAG_PREPRESSED;
24322            setPressed(true, x, y);
24323            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24324        }
24325    }
24326
24327    private final class PerformClick implements Runnable {
24328        @Override
24329        public void run() {
24330            performClick();
24331        }
24332    }
24333
24334    /**
24335     * This method returns a ViewPropertyAnimator object, which can be used to animate
24336     * specific properties on this View.
24337     *
24338     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24339     */
24340    public ViewPropertyAnimator animate() {
24341        if (mAnimator == null) {
24342            mAnimator = new ViewPropertyAnimator(this);
24343        }
24344        return mAnimator;
24345    }
24346
24347    /**
24348     * Sets the name of the View to be used to identify Views in Transitions.
24349     * Names should be unique in the View hierarchy.
24350     *
24351     * @param transitionName The name of the View to uniquely identify it for Transitions.
24352     */
24353    public final void setTransitionName(String transitionName) {
24354        mTransitionName = transitionName;
24355    }
24356
24357    /**
24358     * Returns the name of the View to be used to identify Views in Transitions.
24359     * Names should be unique in the View hierarchy.
24360     *
24361     * <p>This returns null if the View has not been given a name.</p>
24362     *
24363     * @return The name used of the View to be used to identify Views in Transitions or null
24364     * if no name has been given.
24365     */
24366    @ViewDebug.ExportedProperty
24367    public String getTransitionName() {
24368        return mTransitionName;
24369    }
24370
24371    /**
24372     * @hide
24373     */
24374    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24375        // Do nothing.
24376    }
24377
24378    /**
24379     * Interface definition for a callback to be invoked when a hardware key event is
24380     * dispatched to this view. The callback will be invoked before the key event is
24381     * given to the view. This is only useful for hardware keyboards; a software input
24382     * method has no obligation to trigger this listener.
24383     */
24384    public interface OnKeyListener {
24385        /**
24386         * Called when a hardware key is dispatched to a view. This allows listeners to
24387         * get a chance to respond before the target view.
24388         * <p>Key presses in software keyboards will generally NOT trigger this method,
24389         * although some may elect to do so in some situations. Do not assume a
24390         * software input method has to be key-based; even if it is, it may use key presses
24391         * in a different way than you expect, so there is no way to reliably catch soft
24392         * input key presses.
24393         *
24394         * @param v The view the key has been dispatched to.
24395         * @param keyCode The code for the physical key that was pressed
24396         * @param event The KeyEvent object containing full information about
24397         *        the event.
24398         * @return True if the listener has consumed the event, false otherwise.
24399         */
24400        boolean onKey(View v, int keyCode, KeyEvent event);
24401    }
24402
24403    /**
24404     * Interface definition for a callback to be invoked when a touch event is
24405     * dispatched to this view. The callback will be invoked before the touch
24406     * event is given to the view.
24407     */
24408    public interface OnTouchListener {
24409        /**
24410         * Called when a touch event is dispatched to a view. This allows listeners to
24411         * get a chance to respond before the target view.
24412         *
24413         * @param v The view the touch event has been dispatched to.
24414         * @param event The MotionEvent object containing full information about
24415         *        the event.
24416         * @return True if the listener has consumed the event, false otherwise.
24417         */
24418        boolean onTouch(View v, MotionEvent event);
24419    }
24420
24421    /**
24422     * Interface definition for a callback to be invoked when a hover event is
24423     * dispatched to this view. The callback will be invoked before the hover
24424     * event is given to the view.
24425     */
24426    public interface OnHoverListener {
24427        /**
24428         * Called when a hover event is dispatched to a view. This allows listeners to
24429         * get a chance to respond before the target view.
24430         *
24431         * @param v The view the hover event has been dispatched to.
24432         * @param event The MotionEvent object containing full information about
24433         *        the event.
24434         * @return True if the listener has consumed the event, false otherwise.
24435         */
24436        boolean onHover(View v, MotionEvent event);
24437    }
24438
24439    /**
24440     * Interface definition for a callback to be invoked when a generic motion event is
24441     * dispatched to this view. The callback will be invoked before the generic motion
24442     * event is given to the view.
24443     */
24444    public interface OnGenericMotionListener {
24445        /**
24446         * Called when a generic motion event is dispatched to a view. This allows listeners to
24447         * get a chance to respond before the target view.
24448         *
24449         * @param v The view the generic motion event has been dispatched to.
24450         * @param event The MotionEvent object containing full information about
24451         *        the event.
24452         * @return True if the listener has consumed the event, false otherwise.
24453         */
24454        boolean onGenericMotion(View v, MotionEvent event);
24455    }
24456
24457    /**
24458     * Interface definition for a callback to be invoked when a view has been clicked and held.
24459     */
24460    public interface OnLongClickListener {
24461        /**
24462         * Called when a view has been clicked and held.
24463         *
24464         * @param v The view that was clicked and held.
24465         *
24466         * @return true if the callback consumed the long click, false otherwise.
24467         */
24468        boolean onLongClick(View v);
24469    }
24470
24471    /**
24472     * Interface definition for a callback to be invoked when a drag is being dispatched
24473     * to this view.  The callback will be invoked before the hosting view's own
24474     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24475     * onDrag(event) behavior, it should return 'false' from this callback.
24476     *
24477     * <div class="special reference">
24478     * <h3>Developer Guides</h3>
24479     * <p>For a guide to implementing drag and drop features, read the
24480     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24481     * </div>
24482     */
24483    public interface OnDragListener {
24484        /**
24485         * Called when a drag event is dispatched to a view. This allows listeners
24486         * to get a chance to override base View behavior.
24487         *
24488         * @param v The View that received the drag event.
24489         * @param event The {@link android.view.DragEvent} object for the drag event.
24490         * @return {@code true} if the drag event was handled successfully, or {@code false}
24491         * if the drag event was not handled. Note that {@code false} will trigger the View
24492         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24493         */
24494        boolean onDrag(View v, DragEvent event);
24495    }
24496
24497    /**
24498     * Interface definition for a callback to be invoked when the focus state of
24499     * a view changed.
24500     */
24501    public interface OnFocusChangeListener {
24502        /**
24503         * Called when the focus state of a view has changed.
24504         *
24505         * @param v The view whose state has changed.
24506         * @param hasFocus The new focus state of v.
24507         */
24508        void onFocusChange(View v, boolean hasFocus);
24509    }
24510
24511    /**
24512     * Interface definition for a callback to be invoked when a view is clicked.
24513     */
24514    public interface OnClickListener {
24515        /**
24516         * Called when a view has been clicked.
24517         *
24518         * @param v The view that was clicked.
24519         */
24520        void onClick(View v);
24521    }
24522
24523    /**
24524     * Interface definition for a callback to be invoked when a view is context clicked.
24525     */
24526    public interface OnContextClickListener {
24527        /**
24528         * Called when a view is context clicked.
24529         *
24530         * @param v The view that has been context clicked.
24531         * @return true if the callback consumed the context click, false otherwise.
24532         */
24533        boolean onContextClick(View v);
24534    }
24535
24536    /**
24537     * Interface definition for a callback to be invoked when the context menu
24538     * for this view is being built.
24539     */
24540    public interface OnCreateContextMenuListener {
24541        /**
24542         * Called when the context menu for this view is being built. It is not
24543         * safe to hold onto the menu after this method returns.
24544         *
24545         * @param menu The context menu that is being built
24546         * @param v The view for which the context menu is being built
24547         * @param menuInfo Extra information about the item for which the
24548         *            context menu should be shown. This information will vary
24549         *            depending on the class of v.
24550         */
24551        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24552    }
24553
24554    /**
24555     * Interface definition for a callback to be invoked when the status bar changes
24556     * visibility.  This reports <strong>global</strong> changes to the system UI
24557     * state, not what the application is requesting.
24558     *
24559     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24560     */
24561    public interface OnSystemUiVisibilityChangeListener {
24562        /**
24563         * Called when the status bar changes visibility because of a call to
24564         * {@link View#setSystemUiVisibility(int)}.
24565         *
24566         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24567         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24568         * This tells you the <strong>global</strong> state of these UI visibility
24569         * flags, not what your app is currently applying.
24570         */
24571        public void onSystemUiVisibilityChange(int visibility);
24572    }
24573
24574    /**
24575     * Interface definition for a callback to be invoked when this view is attached
24576     * or detached from its window.
24577     */
24578    public interface OnAttachStateChangeListener {
24579        /**
24580         * Called when the view is attached to a window.
24581         * @param v The view that was attached
24582         */
24583        public void onViewAttachedToWindow(View v);
24584        /**
24585         * Called when the view is detached from a window.
24586         * @param v The view that was detached
24587         */
24588        public void onViewDetachedFromWindow(View v);
24589    }
24590
24591    /**
24592     * Listener for applying window insets on a view in a custom way.
24593     *
24594     * <p>Apps may choose to implement this interface if they want to apply custom policy
24595     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24596     * is set, its
24597     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24598     * method will be called instead of the View's own
24599     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24600     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24601     * the View's normal behavior as part of its own.</p>
24602     */
24603    public interface OnApplyWindowInsetsListener {
24604        /**
24605         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24606         * on a View, this listener method will be called instead of the view's own
24607         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24608         *
24609         * @param v The view applying window insets
24610         * @param insets The insets to apply
24611         * @return The insets supplied, minus any insets that were consumed
24612         */
24613        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24614    }
24615
24616    private final class UnsetPressedState implements Runnable {
24617        @Override
24618        public void run() {
24619            setPressed(false);
24620        }
24621    }
24622
24623    /**
24624     * When a view becomes invisible checks if autofill considers the view invisible too. This
24625     * happens after the regular removal operation to make sure the operation is finished by the
24626     * time this is called.
24627     */
24628    private static class VisibilityChangeForAutofillHandler extends Handler {
24629        private final AutofillManager mAfm;
24630        private final View mView;
24631
24632        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
24633                @NonNull View view) {
24634            mAfm = afm;
24635            mView = view;
24636        }
24637
24638        @Override
24639        public void handleMessage(Message msg) {
24640            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
24641        }
24642    }
24643
24644    /**
24645     * Base class for derived classes that want to save and restore their own
24646     * state in {@link android.view.View#onSaveInstanceState()}.
24647     */
24648    public static class BaseSavedState extends AbsSavedState {
24649        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24650        static final int IS_AUTOFILLED = 0b10;
24651        static final int ACCESSIBILITY_ID = 0b100;
24652
24653        // Flags that describe what data in this state is valid
24654        int mSavedData;
24655        String mStartActivityRequestWhoSaved;
24656        boolean mIsAutofilled;
24657        int mAccessibilityViewId;
24658
24659        /**
24660         * Constructor used when reading from a parcel. Reads the state of the superclass.
24661         *
24662         * @param source parcel to read from
24663         */
24664        public BaseSavedState(Parcel source) {
24665            this(source, null);
24666        }
24667
24668        /**
24669         * Constructor used when reading from a parcel using a given class loader.
24670         * Reads the state of the superclass.
24671         *
24672         * @param source parcel to read from
24673         * @param loader ClassLoader to use for reading
24674         */
24675        public BaseSavedState(Parcel source, ClassLoader loader) {
24676            super(source, loader);
24677            mSavedData = source.readInt();
24678            mStartActivityRequestWhoSaved = source.readString();
24679            mIsAutofilled = source.readBoolean();
24680            mAccessibilityViewId = source.readInt();
24681        }
24682
24683        /**
24684         * Constructor called by derived classes when creating their SavedState objects
24685         *
24686         * @param superState The state of the superclass of this view
24687         */
24688        public BaseSavedState(Parcelable superState) {
24689            super(superState);
24690        }
24691
24692        @Override
24693        public void writeToParcel(Parcel out, int flags) {
24694            super.writeToParcel(out, flags);
24695
24696            out.writeInt(mSavedData);
24697            out.writeString(mStartActivityRequestWhoSaved);
24698            out.writeBoolean(mIsAutofilled);
24699            out.writeInt(mAccessibilityViewId);
24700        }
24701
24702        public static final Parcelable.Creator<BaseSavedState> CREATOR
24703                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24704            @Override
24705            public BaseSavedState createFromParcel(Parcel in) {
24706                return new BaseSavedState(in);
24707            }
24708
24709            @Override
24710            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24711                return new BaseSavedState(in, loader);
24712            }
24713
24714            @Override
24715            public BaseSavedState[] newArray(int size) {
24716                return new BaseSavedState[size];
24717            }
24718        };
24719    }
24720
24721    /**
24722     * A set of information given to a view when it is attached to its parent
24723     * window.
24724     */
24725    final static class AttachInfo {
24726        interface Callbacks {
24727            void playSoundEffect(int effectId);
24728            boolean performHapticFeedback(int effectId, boolean always);
24729        }
24730
24731        /**
24732         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24733         * to a Handler. This class contains the target (View) to invalidate and
24734         * the coordinates of the dirty rectangle.
24735         *
24736         * For performance purposes, this class also implements a pool of up to
24737         * POOL_LIMIT objects that get reused. This reduces memory allocations
24738         * whenever possible.
24739         */
24740        static class InvalidateInfo {
24741            private static final int POOL_LIMIT = 10;
24742
24743            private static final SynchronizedPool<InvalidateInfo> sPool =
24744                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24745
24746            View target;
24747
24748            int left;
24749            int top;
24750            int right;
24751            int bottom;
24752
24753            public static InvalidateInfo obtain() {
24754                InvalidateInfo instance = sPool.acquire();
24755                return (instance != null) ? instance : new InvalidateInfo();
24756            }
24757
24758            public void recycle() {
24759                target = null;
24760                sPool.release(this);
24761            }
24762        }
24763
24764        final IWindowSession mSession;
24765
24766        final IWindow mWindow;
24767
24768        final IBinder mWindowToken;
24769
24770        Display mDisplay;
24771
24772        final Callbacks mRootCallbacks;
24773
24774        IWindowId mIWindowId;
24775        WindowId mWindowId;
24776
24777        /**
24778         * The top view of the hierarchy.
24779         */
24780        View mRootView;
24781
24782        IBinder mPanelParentWindowToken;
24783
24784        boolean mHardwareAccelerated;
24785        boolean mHardwareAccelerationRequested;
24786        ThreadedRenderer mThreadedRenderer;
24787        List<RenderNode> mPendingAnimatingRenderNodes;
24788
24789        /**
24790         * The state of the display to which the window is attached, as reported
24791         * by {@link Display#getState()}.  Note that the display state constants
24792         * declared by {@link Display} do not exactly line up with the screen state
24793         * constants declared by {@link View} (there are more display states than
24794         * screen states).
24795         */
24796        int mDisplayState = Display.STATE_UNKNOWN;
24797
24798        /**
24799         * Scale factor used by the compatibility mode
24800         */
24801        float mApplicationScale;
24802
24803        /**
24804         * Indicates whether the application is in compatibility mode
24805         */
24806        boolean mScalingRequired;
24807
24808        /**
24809         * Left position of this view's window
24810         */
24811        int mWindowLeft;
24812
24813        /**
24814         * Top position of this view's window
24815         */
24816        int mWindowTop;
24817
24818        /**
24819         * Indicates whether views need to use 32-bit drawing caches
24820         */
24821        boolean mUse32BitDrawingCache;
24822
24823        /**
24824         * For windows that are full-screen but using insets to layout inside
24825         * of the screen areas, these are the current insets to appear inside
24826         * the overscan area of the display.
24827         */
24828        final Rect mOverscanInsets = new Rect();
24829
24830        /**
24831         * For windows that are full-screen but using insets to layout inside
24832         * of the screen decorations, these are the current insets for the
24833         * content of the window.
24834         */
24835        final Rect mContentInsets = new Rect();
24836
24837        /**
24838         * For windows that are full-screen but using insets to layout inside
24839         * of the screen decorations, these are the current insets for the
24840         * actual visible parts of the window.
24841         */
24842        final Rect mVisibleInsets = new Rect();
24843
24844        /**
24845         * For windows that are full-screen but using insets to layout inside
24846         * of the screen decorations, these are the current insets for the
24847         * stable system windows.
24848         */
24849        final Rect mStableInsets = new Rect();
24850
24851        /**
24852         * For windows that include areas that are not covered by real surface these are the outsets
24853         * for real surface.
24854         */
24855        final Rect mOutsets = new Rect();
24856
24857        /**
24858         * In multi-window we force show the navigation bar. Because we don't want that the surface
24859         * size changes in this mode, we instead have a flag whether the navigation bar size should
24860         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24861         */
24862        boolean mAlwaysConsumeNavBar;
24863
24864        /**
24865         * The internal insets given by this window.  This value is
24866         * supplied by the client (through
24867         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24868         * be given to the window manager when changed to be used in laying
24869         * out windows behind it.
24870         */
24871        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24872                = new ViewTreeObserver.InternalInsetsInfo();
24873
24874        /**
24875         * Set to true when mGivenInternalInsets is non-empty.
24876         */
24877        boolean mHasNonEmptyGivenInternalInsets;
24878
24879        /**
24880         * All views in the window's hierarchy that serve as scroll containers,
24881         * used to determine if the window can be resized or must be panned
24882         * to adjust for a soft input area.
24883         */
24884        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24885
24886        final KeyEvent.DispatcherState mKeyDispatchState
24887                = new KeyEvent.DispatcherState();
24888
24889        /**
24890         * Indicates whether the view's window currently has the focus.
24891         */
24892        boolean mHasWindowFocus;
24893
24894        /**
24895         * The current visibility of the window.
24896         */
24897        int mWindowVisibility;
24898
24899        /**
24900         * Indicates the time at which drawing started to occur.
24901         */
24902        long mDrawingTime;
24903
24904        /**
24905         * Indicates whether or not ignoring the DIRTY_MASK flags.
24906         */
24907        boolean mIgnoreDirtyState;
24908
24909        /**
24910         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24911         * to avoid clearing that flag prematurely.
24912         */
24913        boolean mSetIgnoreDirtyState = false;
24914
24915        /**
24916         * Indicates whether the view's window is currently in touch mode.
24917         */
24918        boolean mInTouchMode;
24919
24920        /**
24921         * Indicates whether the view has requested unbuffered input dispatching for the current
24922         * event stream.
24923         */
24924        boolean mUnbufferedDispatchRequested;
24925
24926        /**
24927         * Indicates that ViewAncestor should trigger a global layout change
24928         * the next time it performs a traversal
24929         */
24930        boolean mRecomputeGlobalAttributes;
24931
24932        /**
24933         * Always report new attributes at next traversal.
24934         */
24935        boolean mForceReportNewAttributes;
24936
24937        /**
24938         * Set during a traveral if any views want to keep the screen on.
24939         */
24940        boolean mKeepScreenOn;
24941
24942        /**
24943         * Set during a traveral if the light center needs to be updated.
24944         */
24945        boolean mNeedsUpdateLightCenter;
24946
24947        /**
24948         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24949         */
24950        int mSystemUiVisibility;
24951
24952        /**
24953         * Hack to force certain system UI visibility flags to be cleared.
24954         */
24955        int mDisabledSystemUiVisibility;
24956
24957        /**
24958         * Last global system UI visibility reported by the window manager.
24959         */
24960        int mGlobalSystemUiVisibility = -1;
24961
24962        /**
24963         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24964         * attached.
24965         */
24966        boolean mHasSystemUiListeners;
24967
24968        /**
24969         * Set if the window has requested to extend into the overscan region
24970         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24971         */
24972        boolean mOverscanRequested;
24973
24974        /**
24975         * Set if the visibility of any views has changed.
24976         */
24977        boolean mViewVisibilityChanged;
24978
24979        /**
24980         * Set to true if a view has been scrolled.
24981         */
24982        boolean mViewScrollChanged;
24983
24984        /**
24985         * Set to true if high contrast mode enabled
24986         */
24987        boolean mHighContrastText;
24988
24989        /**
24990         * Set to true if a pointer event is currently being handled.
24991         */
24992        boolean mHandlingPointerEvent;
24993
24994        /**
24995         * Global to the view hierarchy used as a temporary for dealing with
24996         * x/y points in the transparent region computations.
24997         */
24998        final int[] mTransparentLocation = new int[2];
24999
25000        /**
25001         * Global to the view hierarchy used as a temporary for dealing with
25002         * x/y points in the ViewGroup.invalidateChild implementation.
25003         */
25004        final int[] mInvalidateChildLocation = new int[2];
25005
25006        /**
25007         * Global to the view hierarchy used as a temporary for dealing with
25008         * computing absolute on-screen location.
25009         */
25010        final int[] mTmpLocation = new int[2];
25011
25012        /**
25013         * Global to the view hierarchy used as a temporary for dealing with
25014         * x/y location when view is transformed.
25015         */
25016        final float[] mTmpTransformLocation = new float[2];
25017
25018        /**
25019         * The view tree observer used to dispatch global events like
25020         * layout, pre-draw, touch mode change, etc.
25021         */
25022        final ViewTreeObserver mTreeObserver;
25023
25024        /**
25025         * A Canvas used by the view hierarchy to perform bitmap caching.
25026         */
25027        Canvas mCanvas;
25028
25029        /**
25030         * The view root impl.
25031         */
25032        final ViewRootImpl mViewRootImpl;
25033
25034        /**
25035         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25036         * handler can be used to pump events in the UI events queue.
25037         */
25038        final Handler mHandler;
25039
25040        /**
25041         * Temporary for use in computing invalidate rectangles while
25042         * calling up the hierarchy.
25043         */
25044        final Rect mTmpInvalRect = new Rect();
25045
25046        /**
25047         * Temporary for use in computing hit areas with transformed views
25048         */
25049        final RectF mTmpTransformRect = new RectF();
25050
25051        /**
25052         * Temporary for use in computing hit areas with transformed views
25053         */
25054        final RectF mTmpTransformRect1 = new RectF();
25055
25056        /**
25057         * Temporary list of rectanges.
25058         */
25059        final List<RectF> mTmpRectList = new ArrayList<>();
25060
25061        /**
25062         * Temporary for use in transforming invalidation rect
25063         */
25064        final Matrix mTmpMatrix = new Matrix();
25065
25066        /**
25067         * Temporary for use in transforming invalidation rect
25068         */
25069        final Transformation mTmpTransformation = new Transformation();
25070
25071        /**
25072         * Temporary for use in querying outlines from OutlineProviders
25073         */
25074        final Outline mTmpOutline = new Outline();
25075
25076        /**
25077         * Temporary list for use in collecting focusable descendents of a view.
25078         */
25079        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25080
25081        /**
25082         * The id of the window for accessibility purposes.
25083         */
25084        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25085
25086        /**
25087         * Flags related to accessibility processing.
25088         *
25089         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25090         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25091         */
25092        int mAccessibilityFetchFlags;
25093
25094        /**
25095         * The drawable for highlighting accessibility focus.
25096         */
25097        Drawable mAccessibilityFocusDrawable;
25098
25099        /**
25100         * The drawable for highlighting autofilled views.
25101         *
25102         * @see #isAutofilled()
25103         */
25104        Drawable mAutofilledDrawable;
25105
25106        /**
25107         * Show where the margins, bounds and layout bounds are for each view.
25108         */
25109        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25110
25111        /**
25112         * Point used to compute visible regions.
25113         */
25114        final Point mPoint = new Point();
25115
25116        /**
25117         * Used to track which View originated a requestLayout() call, used when
25118         * requestLayout() is called during layout.
25119         */
25120        View mViewRequestingLayout;
25121
25122        /**
25123         * Used to track views that need (at least) a partial relayout at their current size
25124         * during the next traversal.
25125         */
25126        List<View> mPartialLayoutViews = new ArrayList<>();
25127
25128        /**
25129         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25130         * modification. Lazily assigned during ViewRootImpl layout.
25131         */
25132        List<View> mEmptyPartialLayoutViews;
25133
25134        /**
25135         * Used to track the identity of the current drag operation.
25136         */
25137        IBinder mDragToken;
25138
25139        /**
25140         * The drag shadow surface for the current drag operation.
25141         */
25142        public Surface mDragSurface;
25143
25144
25145        /**
25146         * The view that currently has a tooltip displayed.
25147         */
25148        View mTooltipHost;
25149
25150        /**
25151         * Creates a new set of attachment information with the specified
25152         * events handler and thread.
25153         *
25154         * @param handler the events handler the view must use
25155         */
25156        AttachInfo(IWindowSession session, IWindow window, Display display,
25157                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25158                Context context) {
25159            mSession = session;
25160            mWindow = window;
25161            mWindowToken = window.asBinder();
25162            mDisplay = display;
25163            mViewRootImpl = viewRootImpl;
25164            mHandler = handler;
25165            mRootCallbacks = effectPlayer;
25166            mTreeObserver = new ViewTreeObserver(context);
25167        }
25168    }
25169
25170    /**
25171     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25172     * is supported. This avoids keeping too many unused fields in most
25173     * instances of View.</p>
25174     */
25175    private static class ScrollabilityCache implements Runnable {
25176
25177        /**
25178         * Scrollbars are not visible
25179         */
25180        public static final int OFF = 0;
25181
25182        /**
25183         * Scrollbars are visible
25184         */
25185        public static final int ON = 1;
25186
25187        /**
25188         * Scrollbars are fading away
25189         */
25190        public static final int FADING = 2;
25191
25192        public boolean fadeScrollBars;
25193
25194        public int fadingEdgeLength;
25195        public int scrollBarDefaultDelayBeforeFade;
25196        public int scrollBarFadeDuration;
25197
25198        public int scrollBarSize;
25199        public int scrollBarMinTouchTarget;
25200        public ScrollBarDrawable scrollBar;
25201        public float[] interpolatorValues;
25202        public View host;
25203
25204        public final Paint paint;
25205        public final Matrix matrix;
25206        public Shader shader;
25207
25208        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25209
25210        private static final float[] OPAQUE = { 255 };
25211        private static final float[] TRANSPARENT = { 0.0f };
25212
25213        /**
25214         * When fading should start. This time moves into the future every time
25215         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25216         */
25217        public long fadeStartTime;
25218
25219
25220        /**
25221         * The current state of the scrollbars: ON, OFF, or FADING
25222         */
25223        public int state = OFF;
25224
25225        private int mLastColor;
25226
25227        public final Rect mScrollBarBounds = new Rect();
25228        public final Rect mScrollBarTouchBounds = new Rect();
25229
25230        public static final int NOT_DRAGGING = 0;
25231        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25232        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25233        public int mScrollBarDraggingState = NOT_DRAGGING;
25234
25235        public float mScrollBarDraggingPos = 0;
25236
25237        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25238            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25239            scrollBarSize = configuration.getScaledScrollBarSize();
25240            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25241            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25242            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25243
25244            paint = new Paint();
25245            matrix = new Matrix();
25246            // use use a height of 1, and then wack the matrix each time we
25247            // actually use it.
25248            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25249            paint.setShader(shader);
25250            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25251
25252            this.host = host;
25253        }
25254
25255        public void setFadeColor(int color) {
25256            if (color != mLastColor) {
25257                mLastColor = color;
25258
25259                if (color != 0) {
25260                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25261                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25262                    paint.setShader(shader);
25263                    // Restore the default transfer mode (src_over)
25264                    paint.setXfermode(null);
25265                } else {
25266                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25267                    paint.setShader(shader);
25268                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25269                }
25270            }
25271        }
25272
25273        public void run() {
25274            long now = AnimationUtils.currentAnimationTimeMillis();
25275            if (now >= fadeStartTime) {
25276
25277                // the animation fades the scrollbars out by changing
25278                // the opacity (alpha) from fully opaque to fully
25279                // transparent
25280                int nextFrame = (int) now;
25281                int framesCount = 0;
25282
25283                Interpolator interpolator = scrollBarInterpolator;
25284
25285                // Start opaque
25286                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25287
25288                // End transparent
25289                nextFrame += scrollBarFadeDuration;
25290                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25291
25292                state = FADING;
25293
25294                // Kick off the fade animation
25295                host.invalidate(true);
25296            }
25297        }
25298    }
25299
25300    /**
25301     * Resuable callback for sending
25302     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25303     */
25304    private class SendViewScrolledAccessibilityEvent implements Runnable {
25305        public volatile boolean mIsPending;
25306
25307        public void run() {
25308            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25309            mIsPending = false;
25310        }
25311    }
25312
25313    /**
25314     * <p>
25315     * This class represents a delegate that can be registered in a {@link View}
25316     * to enhance accessibility support via composition rather via inheritance.
25317     * It is specifically targeted to widget developers that extend basic View
25318     * classes i.e. classes in package android.view, that would like their
25319     * applications to be backwards compatible.
25320     * </p>
25321     * <div class="special reference">
25322     * <h3>Developer Guides</h3>
25323     * <p>For more information about making applications accessible, read the
25324     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25325     * developer guide.</p>
25326     * </div>
25327     * <p>
25328     * A scenario in which a developer would like to use an accessibility delegate
25329     * is overriding a method introduced in a later API version than the minimal API
25330     * version supported by the application. For example, the method
25331     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25332     * in API version 4 when the accessibility APIs were first introduced. If a
25333     * developer would like his application to run on API version 4 devices (assuming
25334     * all other APIs used by the application are version 4 or lower) and take advantage
25335     * of this method, instead of overriding the method which would break the application's
25336     * backwards compatibility, he can override the corresponding method in this
25337     * delegate and register the delegate in the target View if the API version of
25338     * the system is high enough, i.e. the API version is the same as or higher than the API
25339     * version that introduced
25340     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25341     * </p>
25342     * <p>
25343     * Here is an example implementation:
25344     * </p>
25345     * <code><pre><p>
25346     * if (Build.VERSION.SDK_INT >= 14) {
25347     *     // If the API version is equal of higher than the version in
25348     *     // which onInitializeAccessibilityNodeInfo was introduced we
25349     *     // register a delegate with a customized implementation.
25350     *     View view = findViewById(R.id.view_id);
25351     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25352     *         public void onInitializeAccessibilityNodeInfo(View host,
25353     *                 AccessibilityNodeInfo info) {
25354     *             // Let the default implementation populate the info.
25355     *             super.onInitializeAccessibilityNodeInfo(host, info);
25356     *             // Set some other information.
25357     *             info.setEnabled(host.isEnabled());
25358     *         }
25359     *     });
25360     * }
25361     * </code></pre></p>
25362     * <p>
25363     * This delegate contains methods that correspond to the accessibility methods
25364     * in View. If a delegate has been specified the implementation in View hands
25365     * off handling to the corresponding method in this delegate. The default
25366     * implementation the delegate methods behaves exactly as the corresponding
25367     * method in View for the case of no accessibility delegate been set. Hence,
25368     * to customize the behavior of a View method, clients can override only the
25369     * corresponding delegate method without altering the behavior of the rest
25370     * accessibility related methods of the host view.
25371     * </p>
25372     * <p>
25373     * <strong>Note:</strong> On platform versions prior to
25374     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25375     * views in the {@code android.widget.*} package are called <i>before</i>
25376     * host methods. This prevents certain properties such as class name from
25377     * being modified by overriding
25378     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25379     * as any changes will be overwritten by the host class.
25380     * <p>
25381     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25382     * methods are called <i>after</i> host methods, which all properties to be
25383     * modified without being overwritten by the host class.
25384     */
25385    public static class AccessibilityDelegate {
25386
25387        /**
25388         * Sends an accessibility event of the given type. If accessibility is not
25389         * enabled this method has no effect.
25390         * <p>
25391         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25392         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25393         * been set.
25394         * </p>
25395         *
25396         * @param host The View hosting the delegate.
25397         * @param eventType The type of the event to send.
25398         *
25399         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25400         */
25401        public void sendAccessibilityEvent(View host, int eventType) {
25402            host.sendAccessibilityEventInternal(eventType);
25403        }
25404
25405        /**
25406         * Performs the specified accessibility action on the view. For
25407         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25408         * <p>
25409         * The default implementation behaves as
25410         * {@link View#performAccessibilityAction(int, Bundle)
25411         *  View#performAccessibilityAction(int, Bundle)} for the case of
25412         *  no accessibility delegate been set.
25413         * </p>
25414         *
25415         * @param action The action to perform.
25416         * @return Whether the action was performed.
25417         *
25418         * @see View#performAccessibilityAction(int, Bundle)
25419         *      View#performAccessibilityAction(int, Bundle)
25420         */
25421        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25422            return host.performAccessibilityActionInternal(action, args);
25423        }
25424
25425        /**
25426         * Sends an accessibility event. This method behaves exactly as
25427         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25428         * empty {@link AccessibilityEvent} and does not perform a check whether
25429         * accessibility is enabled.
25430         * <p>
25431         * The default implementation behaves as
25432         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25433         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25434         * the case of no accessibility delegate been set.
25435         * </p>
25436         *
25437         * @param host The View hosting the delegate.
25438         * @param event The event to send.
25439         *
25440         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25441         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25442         */
25443        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25444            host.sendAccessibilityEventUncheckedInternal(event);
25445        }
25446
25447        /**
25448         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25449         * to its children for adding their text content to the event.
25450         * <p>
25451         * The default implementation behaves as
25452         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25453         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25454         * the case of no accessibility delegate been set.
25455         * </p>
25456         *
25457         * @param host The View hosting the delegate.
25458         * @param event The event.
25459         * @return True if the event population was completed.
25460         *
25461         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25462         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25463         */
25464        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25465            return host.dispatchPopulateAccessibilityEventInternal(event);
25466        }
25467
25468        /**
25469         * Gives a chance to the host View to populate the accessibility event with its
25470         * text content.
25471         * <p>
25472         * The default implementation behaves as
25473         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25474         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25475         * the case of no accessibility delegate been set.
25476         * </p>
25477         *
25478         * @param host The View hosting the delegate.
25479         * @param event The accessibility event which to populate.
25480         *
25481         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25482         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25483         */
25484        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25485            host.onPopulateAccessibilityEventInternal(event);
25486        }
25487
25488        /**
25489         * Initializes an {@link AccessibilityEvent} with information about the
25490         * the host View which is the event source.
25491         * <p>
25492         * The default implementation behaves as
25493         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25494         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25495         * the case of no accessibility delegate been set.
25496         * </p>
25497         *
25498         * @param host The View hosting the delegate.
25499         * @param event The event to initialize.
25500         *
25501         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25502         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25503         */
25504        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25505            host.onInitializeAccessibilityEventInternal(event);
25506        }
25507
25508        /**
25509         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25510         * <p>
25511         * The default implementation behaves as
25512         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25513         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25514         * the case of no accessibility delegate been set.
25515         * </p>
25516         *
25517         * @param host The View hosting the delegate.
25518         * @param info The instance to initialize.
25519         *
25520         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25521         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25522         */
25523        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25524            host.onInitializeAccessibilityNodeInfoInternal(info);
25525        }
25526
25527        /**
25528         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25529         * additional data.
25530         * <p>
25531         * This method only needs to be implemented if the View offers to provide additional data.
25532         * </p>
25533         * <p>
25534         * The default implementation behaves as
25535         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
25536         * for the case where no accessibility delegate is set.
25537         * </p>
25538         *
25539         * @param host The View hosting the delegate. Never {@code null}.
25540         * @param info The info to which to add the extra data. Never {@code null}.
25541         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25542         *                     extra data should be added to the {@link Bundle} returned by
25543         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25544         *                     {@code null}.
25545         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25546         *                  May be {@code null} if the if the service provided no arguments.
25547         *
25548         * @see AccessibilityNodeInfo#setExtraAvailableData
25549         */
25550        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25551                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25552                @Nullable Bundle arguments) {
25553            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25554        }
25555
25556        /**
25557         * Called when a child of the host View has requested sending an
25558         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25559         * to augment the event.
25560         * <p>
25561         * The default implementation behaves as
25562         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25563         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25564         * the case of no accessibility delegate been set.
25565         * </p>
25566         *
25567         * @param host The View hosting the delegate.
25568         * @param child The child which requests sending the event.
25569         * @param event The event to be sent.
25570         * @return True if the event should be sent
25571         *
25572         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25573         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25574         */
25575        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25576                AccessibilityEvent event) {
25577            return host.onRequestSendAccessibilityEventInternal(child, event);
25578        }
25579
25580        /**
25581         * Gets the provider for managing a virtual view hierarchy rooted at this View
25582         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25583         * that explore the window content.
25584         * <p>
25585         * The default implementation behaves as
25586         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25587         * the case of no accessibility delegate been set.
25588         * </p>
25589         *
25590         * @return The provider.
25591         *
25592         * @see AccessibilityNodeProvider
25593         */
25594        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25595            return null;
25596        }
25597
25598        /**
25599         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25600         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25601         * This method is responsible for obtaining an accessibility node info from a
25602         * pool of reusable instances and calling
25603         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25604         * view to initialize the former.
25605         * <p>
25606         * <strong>Note:</strong> The client is responsible for recycling the obtained
25607         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25608         * creation.
25609         * </p>
25610         * <p>
25611         * The default implementation behaves as
25612         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25613         * the case of no accessibility delegate been set.
25614         * </p>
25615         * @return A populated {@link AccessibilityNodeInfo}.
25616         *
25617         * @see AccessibilityNodeInfo
25618         *
25619         * @hide
25620         */
25621        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25622            return host.createAccessibilityNodeInfoInternal();
25623        }
25624    }
25625
25626    private static class MatchIdPredicate implements Predicate<View> {
25627        public int mId;
25628
25629        @Override
25630        public boolean test(View view) {
25631            return (view.mID == mId);
25632        }
25633    }
25634
25635    private static class MatchLabelForPredicate implements Predicate<View> {
25636        private int mLabeledId;
25637
25638        @Override
25639        public boolean test(View view) {
25640            return (view.mLabelForId == mLabeledId);
25641        }
25642    }
25643
25644    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25645        private int mChangeTypes = 0;
25646        private boolean mPosted;
25647        private boolean mPostedWithDelay;
25648        private long mLastEventTimeMillis;
25649
25650        @Override
25651        public void run() {
25652            mPosted = false;
25653            mPostedWithDelay = false;
25654            mLastEventTimeMillis = SystemClock.uptimeMillis();
25655            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25656                final AccessibilityEvent event = AccessibilityEvent.obtain();
25657                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25658                event.setContentChangeTypes(mChangeTypes);
25659                sendAccessibilityEventUnchecked(event);
25660            }
25661            mChangeTypes = 0;
25662        }
25663
25664        public void runOrPost(int changeType) {
25665            mChangeTypes |= changeType;
25666
25667            // If this is a live region or the child of a live region, collect
25668            // all events from this frame and send them on the next frame.
25669            if (inLiveRegion()) {
25670                // If we're already posted with a delay, remove that.
25671                if (mPostedWithDelay) {
25672                    removeCallbacks(this);
25673                    mPostedWithDelay = false;
25674                }
25675                // Only post if we're not already posted.
25676                if (!mPosted) {
25677                    post(this);
25678                    mPosted = true;
25679                }
25680                return;
25681            }
25682
25683            if (mPosted) {
25684                return;
25685            }
25686
25687            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25688            final long minEventIntevalMillis =
25689                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25690            if (timeSinceLastMillis >= minEventIntevalMillis) {
25691                removeCallbacks(this);
25692                run();
25693            } else {
25694                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25695                mPostedWithDelay = true;
25696            }
25697        }
25698    }
25699
25700    private boolean inLiveRegion() {
25701        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25702            return true;
25703        }
25704
25705        ViewParent parent = getParent();
25706        while (parent instanceof View) {
25707            if (((View) parent).getAccessibilityLiveRegion()
25708                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25709                return true;
25710            }
25711            parent = parent.getParent();
25712        }
25713
25714        return false;
25715    }
25716
25717    /**
25718     * Dump all private flags in readable format, useful for documentation and
25719     * sanity checking.
25720     */
25721    private static void dumpFlags() {
25722        final HashMap<String, String> found = Maps.newHashMap();
25723        try {
25724            for (Field field : View.class.getDeclaredFields()) {
25725                final int modifiers = field.getModifiers();
25726                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25727                    if (field.getType().equals(int.class)) {
25728                        final int value = field.getInt(null);
25729                        dumpFlag(found, field.getName(), value);
25730                    } else if (field.getType().equals(int[].class)) {
25731                        final int[] values = (int[]) field.get(null);
25732                        for (int i = 0; i < values.length; i++) {
25733                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25734                        }
25735                    }
25736                }
25737            }
25738        } catch (IllegalAccessException e) {
25739            throw new RuntimeException(e);
25740        }
25741
25742        final ArrayList<String> keys = Lists.newArrayList();
25743        keys.addAll(found.keySet());
25744        Collections.sort(keys);
25745        for (String key : keys) {
25746            Log.d(VIEW_LOG_TAG, found.get(key));
25747        }
25748    }
25749
25750    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25751        // Sort flags by prefix, then by bits, always keeping unique keys
25752        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25753        final int prefix = name.indexOf('_');
25754        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25755        final String output = bits + " " + name;
25756        found.put(key, output);
25757    }
25758
25759    /** {@hide} */
25760    public void encode(@NonNull ViewHierarchyEncoder stream) {
25761        stream.beginObject(this);
25762        encodeProperties(stream);
25763        stream.endObject();
25764    }
25765
25766    /** {@hide} */
25767    @CallSuper
25768    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25769        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25770        if (resolveId instanceof String) {
25771            stream.addProperty("id", (String) resolveId);
25772        } else {
25773            stream.addProperty("id", mID);
25774        }
25775
25776        stream.addProperty("misc:transformation.alpha",
25777                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25778        stream.addProperty("misc:transitionName", getTransitionName());
25779
25780        // layout
25781        stream.addProperty("layout:left", mLeft);
25782        stream.addProperty("layout:right", mRight);
25783        stream.addProperty("layout:top", mTop);
25784        stream.addProperty("layout:bottom", mBottom);
25785        stream.addProperty("layout:width", getWidth());
25786        stream.addProperty("layout:height", getHeight());
25787        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25788        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25789        stream.addProperty("layout:hasTransientState", hasTransientState());
25790        stream.addProperty("layout:baseline", getBaseline());
25791
25792        // layout params
25793        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25794        if (layoutParams != null) {
25795            stream.addPropertyKey("layoutParams");
25796            layoutParams.encode(stream);
25797        }
25798
25799        // scrolling
25800        stream.addProperty("scrolling:scrollX", mScrollX);
25801        stream.addProperty("scrolling:scrollY", mScrollY);
25802
25803        // padding
25804        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25805        stream.addProperty("padding:paddingRight", mPaddingRight);
25806        stream.addProperty("padding:paddingTop", mPaddingTop);
25807        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25808        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25809        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25810        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25811        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25812        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25813
25814        // measurement
25815        stream.addProperty("measurement:minHeight", mMinHeight);
25816        stream.addProperty("measurement:minWidth", mMinWidth);
25817        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25818        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25819
25820        // drawing
25821        stream.addProperty("drawing:elevation", getElevation());
25822        stream.addProperty("drawing:translationX", getTranslationX());
25823        stream.addProperty("drawing:translationY", getTranslationY());
25824        stream.addProperty("drawing:translationZ", getTranslationZ());
25825        stream.addProperty("drawing:rotation", getRotation());
25826        stream.addProperty("drawing:rotationX", getRotationX());
25827        stream.addProperty("drawing:rotationY", getRotationY());
25828        stream.addProperty("drawing:scaleX", getScaleX());
25829        stream.addProperty("drawing:scaleY", getScaleY());
25830        stream.addProperty("drawing:pivotX", getPivotX());
25831        stream.addProperty("drawing:pivotY", getPivotY());
25832        stream.addProperty("drawing:opaque", isOpaque());
25833        stream.addProperty("drawing:alpha", getAlpha());
25834        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25835        stream.addProperty("drawing:shadow", hasShadow());
25836        stream.addProperty("drawing:solidColor", getSolidColor());
25837        stream.addProperty("drawing:layerType", mLayerType);
25838        stream.addProperty("drawing:willNotDraw", willNotDraw());
25839        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25840        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25841        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25842        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25843
25844        // focus
25845        stream.addProperty("focus:hasFocus", hasFocus());
25846        stream.addProperty("focus:isFocused", isFocused());
25847        stream.addProperty("focus:focusable", getFocusable());
25848        stream.addProperty("focus:isFocusable", isFocusable());
25849        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25850
25851        stream.addProperty("misc:clickable", isClickable());
25852        stream.addProperty("misc:pressed", isPressed());
25853        stream.addProperty("misc:selected", isSelected());
25854        stream.addProperty("misc:touchMode", isInTouchMode());
25855        stream.addProperty("misc:hovered", isHovered());
25856        stream.addProperty("misc:activated", isActivated());
25857
25858        stream.addProperty("misc:visibility", getVisibility());
25859        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25860        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25861
25862        stream.addProperty("misc:enabled", isEnabled());
25863        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25864        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25865
25866        // theme attributes
25867        Resources.Theme theme = getContext().getTheme();
25868        if (theme != null) {
25869            stream.addPropertyKey("theme");
25870            theme.encode(stream);
25871        }
25872
25873        // view attribute information
25874        int n = mAttributes != null ? mAttributes.length : 0;
25875        stream.addProperty("meta:__attrCount__", n/2);
25876        for (int i = 0; i < n; i += 2) {
25877            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25878        }
25879
25880        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25881
25882        // text
25883        stream.addProperty("text:textDirection", getTextDirection());
25884        stream.addProperty("text:textAlignment", getTextAlignment());
25885
25886        // accessibility
25887        CharSequence contentDescription = getContentDescription();
25888        stream.addProperty("accessibility:contentDescription",
25889                contentDescription == null ? "" : contentDescription.toString());
25890        stream.addProperty("accessibility:labelFor", getLabelFor());
25891        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25892    }
25893
25894    /**
25895     * Determine if this view is rendered on a round wearable device and is the main view
25896     * on the screen.
25897     */
25898    boolean shouldDrawRoundScrollbar() {
25899        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25900            return false;
25901        }
25902
25903        final View rootView = getRootView();
25904        final WindowInsets insets = getRootWindowInsets();
25905
25906        int height = getHeight();
25907        int width = getWidth();
25908        int displayHeight = rootView.getHeight();
25909        int displayWidth = rootView.getWidth();
25910
25911        if (height != displayHeight || width != displayWidth) {
25912            return false;
25913        }
25914
25915        getLocationInWindow(mAttachInfo.mTmpLocation);
25916        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25917                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25918    }
25919
25920    /**
25921     * Sets the tooltip text which will be displayed in a small popup next to the view.
25922     * <p>
25923     * The tooltip will be displayed:
25924     * <ul>
25925     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
25926     * menu). </li>
25927     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25928     * </ul>
25929     * <p>
25930     * <strong>Note:</strong> Do not override this method, as it will have no
25931     * effect on the text displayed in the tooltip.
25932     *
25933     * @param tooltipText the tooltip text, or null if no tooltip is required
25934     * @see #getTooltipText()
25935     * @attr ref android.R.styleable#View_tooltipText
25936     */
25937    public void setTooltipText(@Nullable CharSequence tooltipText) {
25938        if (TextUtils.isEmpty(tooltipText)) {
25939            setFlags(0, TOOLTIP);
25940            hideTooltip();
25941            mTooltipInfo = null;
25942        } else {
25943            setFlags(TOOLTIP, TOOLTIP);
25944            if (mTooltipInfo == null) {
25945                mTooltipInfo = new TooltipInfo();
25946                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25947                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25948            }
25949            mTooltipInfo.mTooltipText = tooltipText;
25950            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25951                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25952            }
25953        }
25954    }
25955
25956    /**
25957     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25958     */
25959    public void setTooltip(@Nullable CharSequence tooltipText) {
25960        setTooltipText(tooltipText);
25961    }
25962
25963    /**
25964     * Returns the view's tooltip text.
25965     *
25966     * <strong>Note:</strong> Do not override this method, as it will have no
25967     * effect on the text displayed in the tooltip. You must call
25968     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25969     *
25970     * @return the tooltip text
25971     * @see #setTooltipText(CharSequence)
25972     * @attr ref android.R.styleable#View_tooltipText
25973     */
25974    @Nullable
25975    public CharSequence getTooltipText() {
25976        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25977    }
25978
25979    /**
25980     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25981     */
25982    @Nullable
25983    public CharSequence getTooltip() {
25984        return getTooltipText();
25985    }
25986
25987    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25988        if (mAttachInfo == null || mTooltipInfo == null) {
25989            return false;
25990        }
25991        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25992            return false;
25993        }
25994        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25995            return false;
25996        }
25997        hideTooltip();
25998        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25999        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
26000        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
26001        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
26002        mAttachInfo.mTooltipHost = this;
26003        return true;
26004    }
26005
26006    void hideTooltip() {
26007        if (mTooltipInfo == null) {
26008            return;
26009        }
26010        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26011        if (mTooltipInfo.mTooltipPopup == null) {
26012            return;
26013        }
26014        mTooltipInfo.mTooltipPopup.hide();
26015        mTooltipInfo.mTooltipPopup = null;
26016        mTooltipInfo.mTooltipFromLongClick = false;
26017        if (mAttachInfo != null) {
26018            mAttachInfo.mTooltipHost = null;
26019        }
26020    }
26021
26022    private boolean showLongClickTooltip(int x, int y) {
26023        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26024        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26025        return showTooltip(x, y, true);
26026    }
26027
26028    private void showHoverTooltip() {
26029        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
26030    }
26031
26032    boolean dispatchTooltipHoverEvent(MotionEvent event) {
26033        if (mTooltipInfo == null) {
26034            return false;
26035        }
26036        switch(event.getAction()) {
26037            case MotionEvent.ACTION_HOVER_MOVE:
26038                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
26039                    break;
26040                }
26041                if (!mTooltipInfo.mTooltipFromLongClick) {
26042                    if (mTooltipInfo.mTooltipPopup == null) {
26043                        // Schedule showing the tooltip after a timeout.
26044                        mTooltipInfo.mAnchorX = (int) event.getX();
26045                        mTooltipInfo.mAnchorY = (int) event.getY();
26046                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26047                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
26048                                ViewConfiguration.getHoverTooltipShowTimeout());
26049                    }
26050
26051                    // Hide hover-triggered tooltip after a period of inactivity.
26052                    // Match the timeout used by NativeInputManager to hide the mouse pointer
26053                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26054                    final int timeout;
26055                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26056                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
26057                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26058                    } else {
26059                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26060                    }
26061                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26062                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26063                }
26064                return true;
26065
26066            case MotionEvent.ACTION_HOVER_EXIT:
26067                if (!mTooltipInfo.mTooltipFromLongClick) {
26068                    hideTooltip();
26069                }
26070                break;
26071        }
26072        return false;
26073    }
26074
26075    void handleTooltipKey(KeyEvent event) {
26076        switch (event.getAction()) {
26077            case KeyEvent.ACTION_DOWN:
26078                if (event.getRepeatCount() == 0) {
26079                    hideTooltip();
26080                }
26081                break;
26082
26083            case KeyEvent.ACTION_UP:
26084                handleTooltipUp();
26085                break;
26086        }
26087    }
26088
26089    private void handleTooltipUp() {
26090        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26091            return;
26092        }
26093        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26094        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26095                ViewConfiguration.getLongPressTooltipHideTimeout());
26096    }
26097
26098    private int getFocusableAttribute(TypedArray attributes) {
26099        TypedValue val = new TypedValue();
26100        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26101            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26102                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26103            } else {
26104                return val.data;
26105            }
26106        } else {
26107            return FOCUSABLE_AUTO;
26108        }
26109    }
26110
26111    /**
26112     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26113     * is not showing.
26114     * @hide
26115     */
26116    @TestApi
26117    public View getTooltipView() {
26118        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26119            return null;
26120        }
26121        return mTooltipInfo.mTooltipPopup.getContentView();
26122    }
26123}
26124