View.java revision 2f6fc72efcb67737f45edb881eb2aed120a1b0bf
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import static java.lang.Math.max;
20
21import android.animation.AnimatorInflater;
22import android.animation.StateListAnimator;
23import android.annotation.CallSuper;
24import android.annotation.ColorInt;
25import android.annotation.DrawableRes;
26import android.annotation.FloatRange;
27import android.annotation.IdRes;
28import android.annotation.IntDef;
29import android.annotation.IntRange;
30import android.annotation.LayoutRes;
31import android.annotation.NonNull;
32import android.annotation.Nullable;
33import android.annotation.Size;
34import android.annotation.TestApi;
35import android.annotation.UiThread;
36import android.content.ClipData;
37import android.content.Context;
38import android.content.ContextWrapper;
39import android.content.Intent;
40import android.content.res.ColorStateList;
41import android.content.res.Configuration;
42import android.content.res.Resources;
43import android.content.res.TypedArray;
44import android.graphics.Bitmap;
45import android.graphics.Canvas;
46import android.graphics.Color;
47import android.graphics.Insets;
48import android.graphics.Interpolator;
49import android.graphics.LinearGradient;
50import android.graphics.Matrix;
51import android.graphics.Outline;
52import android.graphics.Paint;
53import android.graphics.PixelFormat;
54import android.graphics.Point;
55import android.graphics.PorterDuff;
56import android.graphics.PorterDuffXfermode;
57import android.graphics.Rect;
58import android.graphics.RectF;
59import android.graphics.Region;
60import android.graphics.Shader;
61import android.graphics.drawable.ColorDrawable;
62import android.graphics.drawable.Drawable;
63import android.hardware.display.DisplayManagerGlobal;
64import android.net.Uri;
65import android.os.Build;
66import android.os.Bundle;
67import android.os.Handler;
68import android.os.IBinder;
69import android.os.Message;
70import android.os.Parcel;
71import android.os.Parcelable;
72import android.os.RemoteException;
73import android.os.SystemClock;
74import android.os.SystemProperties;
75import android.os.Trace;
76import android.text.TextUtils;
77import android.util.AttributeSet;
78import android.util.FloatProperty;
79import android.util.LayoutDirection;
80import android.util.Log;
81import android.util.LongSparseLongArray;
82import android.util.Pools.SynchronizedPool;
83import android.util.Property;
84import android.util.SparseArray;
85import android.util.StateSet;
86import android.util.SuperNotCalledException;
87import android.util.TypedValue;
88import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
89import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
90import android.view.AccessibilityIterators.TextSegmentIterator;
91import android.view.AccessibilityIterators.WordTextSegmentIterator;
92import android.view.ContextMenu.ContextMenuInfo;
93import android.view.accessibility.AccessibilityEvent;
94import android.view.accessibility.AccessibilityEventSource;
95import android.view.accessibility.AccessibilityManager;
96import android.view.accessibility.AccessibilityNodeInfo;
97import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
98import android.view.accessibility.AccessibilityNodeProvider;
99import android.view.accessibility.AccessibilityWindowInfo;
100import android.view.animation.Animation;
101import android.view.animation.AnimationUtils;
102import android.view.animation.Transformation;
103import android.view.autofill.AutofillId;
104import android.view.autofill.AutofillManager;
105import android.view.autofill.AutofillValue;
106import android.view.inputmethod.EditorInfo;
107import android.view.inputmethod.InputConnection;
108import android.view.inputmethod.InputMethodManager;
109import android.widget.Checkable;
110import android.widget.FrameLayout;
111import android.widget.ScrollBarDrawable;
112
113import com.android.internal.R;
114import com.android.internal.view.TooltipPopup;
115import com.android.internal.view.menu.MenuBuilder;
116import com.android.internal.widget.ScrollBarUtils;
117
118import com.google.android.collect.Lists;
119import com.google.android.collect.Maps;
120
121import java.lang.annotation.Retention;
122import java.lang.annotation.RetentionPolicy;
123import java.lang.ref.WeakReference;
124import java.lang.reflect.Field;
125import java.lang.reflect.InvocationTargetException;
126import java.lang.reflect.Method;
127import java.lang.reflect.Modifier;
128import java.util.ArrayList;
129import java.util.Arrays;
130import java.util.Collection;
131import java.util.Collections;
132import java.util.HashMap;
133import java.util.List;
134import java.util.Locale;
135import java.util.Map;
136import java.util.concurrent.CopyOnWriteArrayList;
137import java.util.concurrent.atomic.AtomicInteger;
138import java.util.function.Predicate;
139
140/**
141 * <p>
142 * This class represents the basic building block for user interface components. A View
143 * occupies a rectangular area on the screen and is responsible for drawing and
144 * event handling. View is the base class for <em>widgets</em>, which are
145 * used to create interactive UI components (buttons, text fields, etc.). The
146 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
147 * are invisible containers that hold other Views (or other ViewGroups) and define
148 * their layout properties.
149 * </p>
150 *
151 * <div class="special reference">
152 * <h3>Developer Guides</h3>
153 * <p>For information about using this class to develop your application's user interface,
154 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
155 * </div>
156 *
157 * <a name="Using"></a>
158 * <h3>Using Views</h3>
159 * <p>
160 * All of the views in a window are arranged in a single tree. You can add views
161 * either from code or by specifying a tree of views in one or more XML layout
162 * files. There are many specialized subclasses of views that act as controls or
163 * are capable of displaying text, images, or other content.
164 * </p>
165 * <p>
166 * Once you have created a tree of views, there are typically a few types of
167 * common operations you may wish to perform:
168 * <ul>
169 * <li><strong>Set properties:</strong> for example setting the text of a
170 * {@link android.widget.TextView}. The available properties and the methods
171 * that set them will vary among the different subclasses of views. Note that
172 * properties that are known at build time can be set in the XML layout
173 * files.</li>
174 * <li><strong>Set focus:</strong> The framework will handle moving focus in
175 * response to user input. To force focus to a specific view, call
176 * {@link #requestFocus}.</li>
177 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
178 * that will be notified when something interesting happens to the view. For
179 * example, all views will let you set a listener to be notified when the view
180 * gains or loses focus. You can register such a listener using
181 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
182 * Other view subclasses offer more specialized listeners. For example, a Button
183 * exposes a listener to notify clients when the button is clicked.</li>
184 * <li><strong>Set visibility:</strong> You can hide or show views using
185 * {@link #setVisibility(int)}.</li>
186 * </ul>
187 * </p>
188 * <p><em>
189 * Note: The Android framework is responsible for measuring, laying out and
190 * drawing views. You should not call methods that perform these actions on
191 * views yourself unless you are actually implementing a
192 * {@link android.view.ViewGroup}.
193 * </em></p>
194 *
195 * <a name="Lifecycle"></a>
196 * <h3>Implementing a Custom View</h3>
197 *
198 * <p>
199 * To implement a custom view, you will usually begin by providing overrides for
200 * some of the standard methods that the framework calls on all views. You do
201 * not need to override all of these methods. In fact, you can start by just
202 * overriding {@link #onDraw(android.graphics.Canvas)}.
203 * <table border="2" width="85%" align="center" cellpadding="5">
204 *     <thead>
205 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
206 *     </thead>
207 *
208 *     <tbody>
209 *     <tr>
210 *         <td rowspan="2">Creation</td>
211 *         <td>Constructors</td>
212 *         <td>There is a form of the constructor that are called when the view
213 *         is created from code and a form that is called when the view is
214 *         inflated from a layout file. The second form should parse and apply
215 *         any attributes defined in the layout file.
216 *         </td>
217 *     </tr>
218 *     <tr>
219 *         <td><code>{@link #onFinishInflate()}</code></td>
220 *         <td>Called after a view and all of its children has been inflated
221 *         from XML.</td>
222 *     </tr>
223 *
224 *     <tr>
225 *         <td rowspan="3">Layout</td>
226 *         <td><code>{@link #onMeasure(int, int)}</code></td>
227 *         <td>Called to determine the size requirements for this view and all
228 *         of its children.
229 *         </td>
230 *     </tr>
231 *     <tr>
232 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
233 *         <td>Called when this view should assign a size and position to all
234 *         of its children.
235 *         </td>
236 *     </tr>
237 *     <tr>
238 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
239 *         <td>Called when the size of this view has changed.
240 *         </td>
241 *     </tr>
242 *
243 *     <tr>
244 *         <td>Drawing</td>
245 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
246 *         <td>Called when the view should render its content.
247 *         </td>
248 *     </tr>
249 *
250 *     <tr>
251 *         <td rowspan="4">Event processing</td>
252 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
253 *         <td>Called when a new hardware key event occurs.
254 *         </td>
255 *     </tr>
256 *     <tr>
257 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
258 *         <td>Called when a hardware key up event occurs.
259 *         </td>
260 *     </tr>
261 *     <tr>
262 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
263 *         <td>Called when a trackball motion event occurs.
264 *         </td>
265 *     </tr>
266 *     <tr>
267 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
268 *         <td>Called when a touch screen motion event occurs.
269 *         </td>
270 *     </tr>
271 *
272 *     <tr>
273 *         <td rowspan="2">Focus</td>
274 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
275 *         <td>Called when the view gains or loses focus.
276 *         </td>
277 *     </tr>
278 *
279 *     <tr>
280 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
281 *         <td>Called when the window containing the view gains or loses focus.
282 *         </td>
283 *     </tr>
284 *
285 *     <tr>
286 *         <td rowspan="3">Attaching</td>
287 *         <td><code>{@link #onAttachedToWindow()}</code></td>
288 *         <td>Called when the view is attached to a window.
289 *         </td>
290 *     </tr>
291 *
292 *     <tr>
293 *         <td><code>{@link #onDetachedFromWindow}</code></td>
294 *         <td>Called when the view is detached from its window.
295 *         </td>
296 *     </tr>
297 *
298 *     <tr>
299 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
300 *         <td>Called when the visibility of the window containing the view
301 *         has changed.
302 *         </td>
303 *     </tr>
304 *     </tbody>
305 *
306 * </table>
307 * </p>
308 *
309 * <a name="IDs"></a>
310 * <h3>IDs</h3>
311 * Views may have an integer id associated with them. These ids are typically
312 * assigned in the layout XML files, and are used to find specific views within
313 * the view tree. A common pattern is to:
314 * <ul>
315 * <li>Define a Button in the layout file and assign it a unique ID.
316 * <pre>
317 * &lt;Button
318 *     android:id="@+id/my_button"
319 *     android:layout_width="wrap_content"
320 *     android:layout_height="wrap_content"
321 *     android:text="@string/my_button_text"/&gt;
322 * </pre></li>
323 * <li>From the onCreate method of an Activity, find the Button
324 * <pre class="prettyprint">
325 *      Button myButton = findViewById(R.id.my_button);
326 * </pre></li>
327 * </ul>
328 * <p>
329 * View IDs need not be unique throughout the tree, but it is good practice to
330 * ensure that they are at least unique within the part of the tree you are
331 * searching.
332 * </p>
333 *
334 * <a name="Position"></a>
335 * <h3>Position</h3>
336 * <p>
337 * The geometry of a view is that of a rectangle. A view has a location,
338 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
339 * two dimensions, expressed as a width and a height. The unit for location
340 * and dimensions is the pixel.
341 * </p>
342 *
343 * <p>
344 * It is possible to retrieve the location of a view by invoking the methods
345 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
346 * coordinate of the rectangle representing the view. The latter returns the
347 * top, or Y, coordinate of the rectangle representing the view. These methods
348 * both return the location of the view relative to its parent. For instance,
349 * when getLeft() returns 20, that means the view is located 20 pixels to the
350 * right of the left edge of its direct parent.
351 * </p>
352 *
353 * <p>
354 * In addition, several convenience methods are offered to avoid unnecessary
355 * computations, namely {@link #getRight()} and {@link #getBottom()}.
356 * These methods return the coordinates of the right and bottom edges of the
357 * rectangle representing the view. For instance, calling {@link #getRight()}
358 * is similar to the following computation: <code>getLeft() + getWidth()</code>
359 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
360 * </p>
361 *
362 * <a name="SizePaddingMargins"></a>
363 * <h3>Size, padding and margins</h3>
364 * <p>
365 * The size of a view is expressed with a width and a height. A view actually
366 * possess two pairs of width and height values.
367 * </p>
368 *
369 * <p>
370 * The first pair is known as <em>measured width</em> and
371 * <em>measured height</em>. These dimensions define how big a view wants to be
372 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
373 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
374 * and {@link #getMeasuredHeight()}.
375 * </p>
376 *
377 * <p>
378 * The second pair is simply known as <em>width</em> and <em>height</em>, or
379 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
380 * dimensions define the actual size of the view on screen, at drawing time and
381 * after layout. These values may, but do not have to, be different from the
382 * measured width and height. The width and height can be obtained by calling
383 * {@link #getWidth()} and {@link #getHeight()}.
384 * </p>
385 *
386 * <p>
387 * To measure its dimensions, a view takes into account its padding. The padding
388 * is expressed in pixels for the left, top, right and bottom parts of the view.
389 * Padding can be used to offset the content of the view by a specific amount of
390 * pixels. For instance, a left padding of 2 will push the view's content by
391 * 2 pixels to the right of the left edge. Padding can be set using the
392 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
393 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
394 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
395 * {@link #getPaddingEnd()}.
396 * </p>
397 *
398 * <p>
399 * Even though a view can define a padding, it does not provide any support for
400 * margins. However, view groups provide such a support. Refer to
401 * {@link android.view.ViewGroup} and
402 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
403 * </p>
404 *
405 * <a name="Layout"></a>
406 * <h3>Layout</h3>
407 * <p>
408 * Layout is a two pass process: a measure pass and a layout pass. The measuring
409 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
410 * of the view tree. Each view pushes dimension specifications down the tree
411 * during the recursion. At the end of the measure pass, every view has stored
412 * its measurements. The second pass happens in
413 * {@link #layout(int,int,int,int)} and is also top-down. During
414 * this pass each parent is responsible for positioning all of its children
415 * using the sizes computed in the measure pass.
416 * </p>
417 *
418 * <p>
419 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
420 * {@link #getMeasuredHeight()} values must be set, along with those for all of
421 * that view's descendants. A view's measured width and measured height values
422 * must respect the constraints imposed by the view's parents. This guarantees
423 * that at the end of the measure pass, all parents accept all of their
424 * children's measurements. A parent view may call measure() more than once on
425 * its children. For example, the parent may measure each child once with
426 * unspecified dimensions to find out how big they want to be, then call
427 * measure() on them again with actual numbers if the sum of all the children's
428 * unconstrained sizes is too big or too small.
429 * </p>
430 *
431 * <p>
432 * The measure pass uses two classes to communicate dimensions. The
433 * {@link MeasureSpec} class is used by views to tell their parents how they
434 * want to be measured and positioned. The base LayoutParams class just
435 * describes how big the view wants to be for both width and height. For each
436 * dimension, it can specify one of:
437 * <ul>
438 * <li> an exact number
439 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
440 * (minus padding)
441 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
442 * enclose its content (plus padding).
443 * </ul>
444 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
445 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
446 * an X and Y value.
447 * </p>
448 *
449 * <p>
450 * MeasureSpecs are used to push requirements down the tree from parent to
451 * child. A MeasureSpec can be in one of three modes:
452 * <ul>
453 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
454 * of a child view. For example, a LinearLayout may call measure() on its child
455 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
456 * tall the child view wants to be given a width of 240 pixels.
457 * <li>EXACTLY: This is used by the parent to impose an exact size on the
458 * child. The child must use this size, and guarantee that all of its
459 * descendants will fit within this size.
460 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
461 * child. The child must guarantee that it and all of its descendants will fit
462 * within this size.
463 * </ul>
464 * </p>
465 *
466 * <p>
467 * To initiate a layout, call {@link #requestLayout}. This method is typically
468 * called by a view on itself when it believes that is can no longer fit within
469 * its current bounds.
470 * </p>
471 *
472 * <a name="Drawing"></a>
473 * <h3>Drawing</h3>
474 * <p>
475 * Drawing is handled by walking the tree and recording the drawing commands of
476 * any View that needs to update. After this, the drawing commands of the
477 * entire tree are issued to screen, clipped to the newly damaged area.
478 * </p>
479 *
480 * <p>
481 * The tree is largely recorded and drawn in order, with parents drawn before
482 * (i.e., behind) their children, with siblings drawn in the order they appear
483 * in the tree. If you set a background drawable for a View, then the View will
484 * draw it before calling back to its <code>onDraw()</code> method. The child
485 * drawing order can be overridden with
486 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
487 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
488 * </p>
489 *
490 * <p>
491 * To force a view to draw, call {@link #invalidate()}.
492 * </p>
493 *
494 * <a name="EventHandlingThreading"></a>
495 * <h3>Event Handling and Threading</h3>
496 * <p>
497 * The basic cycle of a view is as follows:
498 * <ol>
499 * <li>An event comes in and is dispatched to the appropriate view. The view
500 * handles the event and notifies any listeners.</li>
501 * <li>If in the course of processing the event, the view's bounds may need
502 * to be changed, the view will call {@link #requestLayout()}.</li>
503 * <li>Similarly, if in the course of processing the event the view's appearance
504 * may need to be changed, the view will call {@link #invalidate()}.</li>
505 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
506 * the framework will take care of measuring, laying out, and drawing the tree
507 * as appropriate.</li>
508 * </ol>
509 * </p>
510 *
511 * <p><em>Note: The entire view tree is single threaded. You must always be on
512 * the UI thread when calling any method on any view.</em>
513 * If you are doing work on other threads and want to update the state of a view
514 * from that thread, you should use a {@link Handler}.
515 * </p>
516 *
517 * <a name="FocusHandling"></a>
518 * <h3>Focus Handling</h3>
519 * <p>
520 * The framework will handle routine focus movement in response to user input.
521 * This includes changing the focus as views are removed or hidden, or as new
522 * views become available. Views indicate their willingness to take focus
523 * through the {@link #isFocusable} method. To change whether a view can take
524 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
525 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
526 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
527 * </p>
528 * <p>
529 * Focus movement is based on an algorithm which finds the nearest neighbor in a
530 * given direction. In rare cases, the default algorithm may not match the
531 * intended behavior of the developer. In these situations, you can provide
532 * explicit overrides by using these XML attributes in the layout file:
533 * <pre>
534 * nextFocusDown
535 * nextFocusLeft
536 * nextFocusRight
537 * nextFocusUp
538 * </pre>
539 * </p>
540 *
541 *
542 * <p>
543 * To get a particular view to take focus, call {@link #requestFocus()}.
544 * </p>
545 *
546 * <a name="TouchMode"></a>
547 * <h3>Touch Mode</h3>
548 * <p>
549 * When a user is navigating a user interface via directional keys such as a D-pad, it is
550 * necessary to give focus to actionable items such as buttons so the user can see
551 * what will take input.  If the device has touch capabilities, however, and the user
552 * begins interacting with the interface by touching it, it is no longer necessary to
553 * always highlight, or give focus to, a particular view.  This motivates a mode
554 * for interaction named 'touch mode'.
555 * </p>
556 * <p>
557 * For a touch capable device, once the user touches the screen, the device
558 * will enter touch mode.  From this point onward, only views for which
559 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
560 * Other views that are touchable, like buttons, will not take focus when touched; they will
561 * only fire the on click listeners.
562 * </p>
563 * <p>
564 * Any time a user hits a directional key, such as a D-pad direction, the view device will
565 * exit touch mode, and find a view to take focus, so that the user may resume interacting
566 * with the user interface without touching the screen again.
567 * </p>
568 * <p>
569 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
570 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
571 * </p>
572 *
573 * <a name="Scrolling"></a>
574 * <h3>Scrolling</h3>
575 * <p>
576 * The framework provides basic support for views that wish to internally
577 * scroll their content. This includes keeping track of the X and Y scroll
578 * offset as well as mechanisms for drawing scrollbars. See
579 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
580 * {@link #awakenScrollBars()} for more details.
581 * </p>
582 *
583 * <a name="Tags"></a>
584 * <h3>Tags</h3>
585 * <p>
586 * Unlike IDs, tags are not used to identify views. Tags are essentially an
587 * extra piece of information that can be associated with a view. They are most
588 * often used as a convenience to store data related to views in the views
589 * themselves rather than by putting them in a separate structure.
590 * </p>
591 * <p>
592 * Tags may be specified with character sequence values in layout XML as either
593 * a single tag using the {@link android.R.styleable#View_tag android:tag}
594 * attribute or multiple tags using the {@code <tag>} child element:
595 * <pre>
596 *     &lt;View ...
597 *           android:tag="@string/mytag_value" /&gt;
598 *     &lt;View ...&gt;
599 *         &lt;tag android:id="@+id/mytag"
600 *              android:value="@string/mytag_value" /&gt;
601 *     &lt;/View>
602 * </pre>
603 * </p>
604 * <p>
605 * Tags may also be specified with arbitrary objects from code using
606 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
607 * </p>
608 *
609 * <a name="Themes"></a>
610 * <h3>Themes</h3>
611 * <p>
612 * By default, Views are created using the theme of the Context object supplied
613 * to their constructor; however, a different theme may be specified by using
614 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
615 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
616 * code.
617 * </p>
618 * <p>
619 * When the {@link android.R.styleable#View_theme android:theme} attribute is
620 * used in XML, the specified theme is applied on top of the inflation
621 * context's theme (see {@link LayoutInflater}) and used for the view itself as
622 * well as any child elements.
623 * </p>
624 * <p>
625 * In the following example, both views will be created using the Material dark
626 * color scheme; however, because an overlay theme is used which only defines a
627 * subset of attributes, the value of
628 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
629 * the inflation context's theme (e.g. the Activity theme) will be preserved.
630 * <pre>
631 *     &lt;LinearLayout
632 *             ...
633 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
634 *         &lt;View ...&gt;
635 *     &lt;/LinearLayout&gt;
636 * </pre>
637 * </p>
638 *
639 * <a name="Properties"></a>
640 * <h3>Properties</h3>
641 * <p>
642 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
643 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
644 * available both in the {@link Property} form as well as in similarly-named setter/getter
645 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
646 * be used to set persistent state associated with these rendering-related properties on the view.
647 * The properties and methods can also be used in conjunction with
648 * {@link android.animation.Animator Animator}-based animations, described more in the
649 * <a href="#Animation">Animation</a> section.
650 * </p>
651 *
652 * <a name="Animation"></a>
653 * <h3>Animation</h3>
654 * <p>
655 * Starting with Android 3.0, the preferred way of animating views is to use the
656 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
657 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
658 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
659 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
660 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
661 * makes animating these View properties particularly easy and efficient.
662 * </p>
663 * <p>
664 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
665 * You can attach an {@link Animation} object to a view using
666 * {@link #setAnimation(Animation)} or
667 * {@link #startAnimation(Animation)}. The animation can alter the scale,
668 * rotation, translation and alpha of a view over time. If the animation is
669 * attached to a view that has children, the animation will affect the entire
670 * subtree rooted by that node. When an animation is started, the framework will
671 * take care of redrawing the appropriate views until the animation completes.
672 * </p>
673 *
674 * <a name="Security"></a>
675 * <h3>Security</h3>
676 * <p>
677 * Sometimes it is essential that an application be able to verify that an action
678 * is being performed with the full knowledge and consent of the user, such as
679 * granting a permission request, making a purchase or clicking on an advertisement.
680 * Unfortunately, a malicious application could try to spoof the user into
681 * performing these actions, unaware, by concealing the intended purpose of the view.
682 * As a remedy, the framework offers a touch filtering mechanism that can be used to
683 * improve the security of views that provide access to sensitive functionality.
684 * </p><p>
685 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
686 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
687 * will discard touches that are received whenever the view's window is obscured by
688 * another visible window.  As a result, the view will not receive touches whenever a
689 * toast, dialog or other window appears above the view's window.
690 * </p><p>
691 * For more fine-grained control over security, consider overriding the
692 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
693 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
694 * </p>
695 *
696 * @attr ref android.R.styleable#View_alpha
697 * @attr ref android.R.styleable#View_background
698 * @attr ref android.R.styleable#View_clickable
699 * @attr ref android.R.styleable#View_contentDescription
700 * @attr ref android.R.styleable#View_drawingCacheQuality
701 * @attr ref android.R.styleable#View_duplicateParentState
702 * @attr ref android.R.styleable#View_id
703 * @attr ref android.R.styleable#View_requiresFadingEdge
704 * @attr ref android.R.styleable#View_fadeScrollbars
705 * @attr ref android.R.styleable#View_fadingEdgeLength
706 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
707 * @attr ref android.R.styleable#View_fitsSystemWindows
708 * @attr ref android.R.styleable#View_isScrollContainer
709 * @attr ref android.R.styleable#View_focusable
710 * @attr ref android.R.styleable#View_focusableInTouchMode
711 * @attr ref android.R.styleable#View_focusedByDefault
712 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
713 * @attr ref android.R.styleable#View_keepScreenOn
714 * @attr ref android.R.styleable#View_keyboardNavigationCluster
715 * @attr ref android.R.styleable#View_layerType
716 * @attr ref android.R.styleable#View_layoutDirection
717 * @attr ref android.R.styleable#View_longClickable
718 * @attr ref android.R.styleable#View_minHeight
719 * @attr ref android.R.styleable#View_minWidth
720 * @attr ref android.R.styleable#View_nextClusterForward
721 * @attr ref android.R.styleable#View_nextFocusDown
722 * @attr ref android.R.styleable#View_nextFocusLeft
723 * @attr ref android.R.styleable#View_nextFocusRight
724 * @attr ref android.R.styleable#View_nextFocusUp
725 * @attr ref android.R.styleable#View_onClick
726 * @attr ref android.R.styleable#View_padding
727 * @attr ref android.R.styleable#View_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     * Hint indicating that this view can be autofilled with an email address.
968     *
969     * <p>Can be used with either {@link #setAutofillHints(String[])} or
970     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
971     * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
972     *
973     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
974     */
975    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
976
977    /**
978     * Hint indicating that this view can be autofilled with a user's real name.
979     *
980     * <p>Can be used with either {@link #setAutofillHints(String[])} or
981     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
982     * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
983     *
984     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
985     */
986    public static final String AUTOFILL_HINT_NAME = "name";
987
988    /**
989     * Hint indicating that this view can be autofilled with a username.
990     *
991     * <p>Can be used with either {@link #setAutofillHints(String[])} or
992     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
993     * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
994     *
995     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
996     */
997    public static final String AUTOFILL_HINT_USERNAME = "username";
998
999    /**
1000     * Hint indicating that this view can be autofilled with a password.
1001     *
1002     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1003     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1004     * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1005     *
1006     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1007     */
1008    public static final String AUTOFILL_HINT_PASSWORD = "password";
1009
1010    /**
1011     * Hint indicating that this view can be autofilled with a phone number.
1012     *
1013     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1014     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1015     * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1016     *
1017     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1018     */
1019    public static final String AUTOFILL_HINT_PHONE = "phone";
1020
1021    /**
1022     * Hint indicating that this view can be autofilled with a postal address.
1023     *
1024     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1025     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1026     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1027     *
1028     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1029     */
1030    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1031
1032    /**
1033     * Hint indicating that this view can be autofilled with a postal code.
1034     *
1035     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1036     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1037     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1038     *
1039     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1040     */
1041    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1042
1043    /**
1044     * Hint indicating that this view can be autofilled with a credit card number.
1045     *
1046     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1047     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1048     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1049     *
1050     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1051     */
1052    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1053
1054    /**
1055     * Hint indicating that this view can be autofilled with a credit card security code.
1056     *
1057     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1058     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1059     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1060     *
1061     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1062     */
1063    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1064
1065    /**
1066     * Hint indicating that this view can be autofilled with a credit card expiration date.
1067     *
1068     * <p>It should be used when the credit card expiration date is represented by just one view;
1069     * if it is represented by more than one (for example, one view for the month and another view
1070     * for the year), then each of these views should use the hint specific for the unit
1071     * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1072     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1073     * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1074     *
1075     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1076     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1077     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1078     *
1079     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1080     */
1081    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1082            "creditCardExpirationDate";
1083
1084    /**
1085     * Hint indicating that this view can be autofilled with a credit card expiration month.
1086     *
1087     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1088     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1089     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1090     *
1091     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1092     */
1093    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1094            "creditCardExpirationMonth";
1095
1096    /**
1097     * Hint indicating that this view can be autofilled with a credit card expiration year.
1098     *
1099     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1100     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1101     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1102     *
1103     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1104     */
1105    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1106            "creditCardExpirationYear";
1107
1108    /**
1109     * Hint indicating that this view can be autofilled with a credit card expiration day.
1110     *
1111     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1112     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1113     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1114     *
1115     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1116     */
1117    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1118
1119    /**
1120     * Hints for the autofill services that describes the content of the view.
1121     */
1122    private @Nullable String[] mAutofillHints;
1123
1124    /**
1125     * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1126     */
1127    private AutofillId mAutofillId;
1128
1129    /** @hide */
1130    @IntDef({
1131            AUTOFILL_TYPE_NONE,
1132            AUTOFILL_TYPE_TEXT,
1133            AUTOFILL_TYPE_TOGGLE,
1134            AUTOFILL_TYPE_LIST,
1135            AUTOFILL_TYPE_DATE
1136    })
1137    @Retention(RetentionPolicy.SOURCE)
1138    public @interface AutofillType {}
1139
1140    /**
1141     * Autofill type for views that cannot be autofilled.
1142     *
1143     * <p>Typically used when the view is read-only; for example, a text label.
1144     *
1145     * @see #getAutofillType()
1146     */
1147    public static final int AUTOFILL_TYPE_NONE = 0;
1148
1149    /**
1150     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1151     *
1152     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1153     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1154     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1155     *
1156     * @see #getAutofillType()
1157     */
1158    public static final int AUTOFILL_TYPE_TEXT = 1;
1159
1160    /**
1161     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1162     *
1163     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1164     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1165     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1166     *
1167     * @see #getAutofillType()
1168     */
1169    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1170
1171    /**
1172     * Autofill type for a selection list field, which is filled by an {@code int}
1173     * representing the element index inside the list (starting at {@code 0}).
1174     *
1175     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1176     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1177     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1178     *
1179     * <p>The available options in the selection list are typically provided by
1180     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1181     *
1182     * @see #getAutofillType()
1183     */
1184    public static final int AUTOFILL_TYPE_LIST = 3;
1185
1186
1187    /**
1188     * Autofill type for a field that contains a date, which is represented by a long representing
1189     * the number of milliseconds since the standard base time known as "the epoch", namely
1190     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1191     *
1192     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1193     * {@link AutofillValue#forDate(long)}, and the values passed to
1194     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1195     *
1196     * @see #getAutofillType()
1197     */
1198    public static final int AUTOFILL_TYPE_DATE = 4;
1199
1200    /** @hide */
1201    @IntDef({
1202            IMPORTANT_FOR_AUTOFILL_AUTO,
1203            IMPORTANT_FOR_AUTOFILL_YES,
1204            IMPORTANT_FOR_AUTOFILL_NO,
1205            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1206            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1207    })
1208    @Retention(RetentionPolicy.SOURCE)
1209    public @interface AutofillImportance {}
1210
1211    /**
1212     * Automatically determine whether a view is important for autofill.
1213     *
1214     * @see #isImportantForAutofill()
1215     * @see #setImportantForAutofill(int)
1216     */
1217    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1218
1219    /**
1220     * The view is important for autofill, and its children (if any) will be traversed.
1221     *
1222     * @see #isImportantForAutofill()
1223     * @see #setImportantForAutofill(int)
1224     */
1225    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1226
1227    /**
1228     * The view is not important for autofill, but its children (if any) will be traversed.
1229     *
1230     * @see #isImportantForAutofill()
1231     * @see #setImportantForAutofill(int)
1232     */
1233    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1234
1235    /**
1236     * The view is important for autofill, but its children (if any) will not be traversed.
1237     *
1238     * @see #isImportantForAutofill()
1239     * @see #setImportantForAutofill(int)
1240     */
1241    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1242
1243    /**
1244     * The view is not important for autofill, and its children (if any) will not be traversed.
1245     *
1246     * @see #isImportantForAutofill()
1247     * @see #setImportantForAutofill(int)
1248     */
1249    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1250
1251    /** @hide */
1252    @IntDef(
1253            flag = true,
1254            value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS})
1255    @Retention(RetentionPolicy.SOURCE)
1256    public @interface AutofillFlags {}
1257
1258    /**
1259     * Flag requesting you to add views that are marked as not important for autofill
1260     * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1261     */
1262    public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1263
1264    /**
1265     * This view is enabled. Interpretation varies by subclass.
1266     * Use with ENABLED_MASK when calling setFlags.
1267     * {@hide}
1268     */
1269    static final int ENABLED = 0x00000000;
1270
1271    /**
1272     * This view is disabled. Interpretation varies by subclass.
1273     * Use with ENABLED_MASK when calling setFlags.
1274     * {@hide}
1275     */
1276    static final int DISABLED = 0x00000020;
1277
1278   /**
1279    * Mask for use with setFlags indicating bits used for indicating whether
1280    * this view is enabled
1281    * {@hide}
1282    */
1283    static final int ENABLED_MASK = 0x00000020;
1284
1285    /**
1286     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1287     * called and further optimizations will be performed. It is okay to have
1288     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1289     * {@hide}
1290     */
1291    static final int WILL_NOT_DRAW = 0x00000080;
1292
1293    /**
1294     * Mask for use with setFlags indicating bits used for indicating whether
1295     * this view is will draw
1296     * {@hide}
1297     */
1298    static final int DRAW_MASK = 0x00000080;
1299
1300    /**
1301     * <p>This view doesn't show scrollbars.</p>
1302     * {@hide}
1303     */
1304    static final int SCROLLBARS_NONE = 0x00000000;
1305
1306    /**
1307     * <p>This view shows horizontal scrollbars.</p>
1308     * {@hide}
1309     */
1310    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1311
1312    /**
1313     * <p>This view shows vertical scrollbars.</p>
1314     * {@hide}
1315     */
1316    static final int SCROLLBARS_VERTICAL = 0x00000200;
1317
1318    /**
1319     * <p>Mask for use with setFlags indicating bits used for indicating which
1320     * scrollbars are enabled.</p>
1321     * {@hide}
1322     */
1323    static final int SCROLLBARS_MASK = 0x00000300;
1324
1325    /**
1326     * Indicates that the view should filter touches when its window is obscured.
1327     * Refer to the class comments for more information about this security feature.
1328     * {@hide}
1329     */
1330    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1331
1332    /**
1333     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1334     * that they are optional and should be skipped if the window has
1335     * requested system UI flags that ignore those insets for layout.
1336     */
1337    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1338
1339    /**
1340     * <p>This view doesn't show fading edges.</p>
1341     * {@hide}
1342     */
1343    static final int FADING_EDGE_NONE = 0x00000000;
1344
1345    /**
1346     * <p>This view shows horizontal fading edges.</p>
1347     * {@hide}
1348     */
1349    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1350
1351    /**
1352     * <p>This view shows vertical fading edges.</p>
1353     * {@hide}
1354     */
1355    static final int FADING_EDGE_VERTICAL = 0x00002000;
1356
1357    /**
1358     * <p>Mask for use with setFlags indicating bits used for indicating which
1359     * fading edges are enabled.</p>
1360     * {@hide}
1361     */
1362    static final int FADING_EDGE_MASK = 0x00003000;
1363
1364    /**
1365     * <p>Indicates this view can be clicked. When clickable, a View reacts
1366     * to clicks by notifying the OnClickListener.<p>
1367     * {@hide}
1368     */
1369    static final int CLICKABLE = 0x00004000;
1370
1371    /**
1372     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1373     * {@hide}
1374     */
1375    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1376
1377    /**
1378     * <p>Indicates that no icicle should be saved for this view.<p>
1379     * {@hide}
1380     */
1381    static final int SAVE_DISABLED = 0x000010000;
1382
1383    /**
1384     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1385     * property.</p>
1386     * {@hide}
1387     */
1388    static final int SAVE_DISABLED_MASK = 0x000010000;
1389
1390    /**
1391     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1392     * {@hide}
1393     */
1394    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1395
1396    /**
1397     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1398     * {@hide}
1399     */
1400    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1401
1402    /** @hide */
1403    @Retention(RetentionPolicy.SOURCE)
1404    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1405    public @interface DrawingCacheQuality {}
1406
1407    /**
1408     * <p>Enables low quality mode for the drawing cache.</p>
1409     */
1410    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1411
1412    /**
1413     * <p>Enables high quality mode for the drawing cache.</p>
1414     */
1415    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1416
1417    /**
1418     * <p>Enables automatic quality mode for the drawing cache.</p>
1419     */
1420    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1421
1422    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1423            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1424    };
1425
1426    /**
1427     * <p>Mask for use with setFlags indicating bits used for the cache
1428     * quality property.</p>
1429     * {@hide}
1430     */
1431    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1432
1433    /**
1434     * <p>
1435     * Indicates this view can be long clicked. When long clickable, a View
1436     * reacts to long clicks by notifying the OnLongClickListener or showing a
1437     * context menu.
1438     * </p>
1439     * {@hide}
1440     */
1441    static final int LONG_CLICKABLE = 0x00200000;
1442
1443    /**
1444     * <p>Indicates that this view gets its drawable states from its direct parent
1445     * and ignores its original internal states.</p>
1446     *
1447     * @hide
1448     */
1449    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1450
1451    /**
1452     * <p>
1453     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1454     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1455     * OnContextClickListener.
1456     * </p>
1457     * {@hide}
1458     */
1459    static final int CONTEXT_CLICKABLE = 0x00800000;
1460
1461
1462    /** @hide */
1463    @IntDef({
1464        SCROLLBARS_INSIDE_OVERLAY,
1465        SCROLLBARS_INSIDE_INSET,
1466        SCROLLBARS_OUTSIDE_OVERLAY,
1467        SCROLLBARS_OUTSIDE_INSET
1468    })
1469    @Retention(RetentionPolicy.SOURCE)
1470    public @interface ScrollBarStyle {}
1471
1472    /**
1473     * The scrollbar style to display the scrollbars inside the content area,
1474     * without increasing the padding. The scrollbars will be overlaid with
1475     * translucency on the view's content.
1476     */
1477    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1478
1479    /**
1480     * The scrollbar style to display the scrollbars inside the padded area,
1481     * increasing the padding of the view. The scrollbars will not overlap the
1482     * content area of the view.
1483     */
1484    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1485
1486    /**
1487     * The scrollbar style to display the scrollbars at the edge of the view,
1488     * without increasing the padding. The scrollbars will be overlaid with
1489     * translucency.
1490     */
1491    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1492
1493    /**
1494     * The scrollbar style to display the scrollbars at the edge of the view,
1495     * increasing the padding of the view. The scrollbars will only overlap the
1496     * background, if any.
1497     */
1498    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1499
1500    /**
1501     * Mask to check if the scrollbar style is overlay or inset.
1502     * {@hide}
1503     */
1504    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1505
1506    /**
1507     * Mask to check if the scrollbar style is inside or outside.
1508     * {@hide}
1509     */
1510    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1511
1512    /**
1513     * Mask for scrollbar style.
1514     * {@hide}
1515     */
1516    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1517
1518    /**
1519     * View flag indicating that the screen should remain on while the
1520     * window containing this view is visible to the user.  This effectively
1521     * takes care of automatically setting the WindowManager's
1522     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1523     */
1524    public static final int KEEP_SCREEN_ON = 0x04000000;
1525
1526    /**
1527     * View flag indicating whether this view should have sound effects enabled
1528     * for events such as clicking and touching.
1529     */
1530    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1531
1532    /**
1533     * View flag indicating whether this view should have haptic feedback
1534     * enabled for events such as long presses.
1535     */
1536    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1537
1538    /**
1539     * <p>Indicates that the view hierarchy should stop saving state when
1540     * it reaches this view.  If state saving is initiated immediately at
1541     * the view, it will be allowed.
1542     * {@hide}
1543     */
1544    static final int PARENT_SAVE_DISABLED = 0x20000000;
1545
1546    /**
1547     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1548     * {@hide}
1549     */
1550    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1551
1552    private static Paint sDebugPaint;
1553
1554    /**
1555     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1556     * {@hide}
1557     */
1558    static final int TOOLTIP = 0x40000000;
1559
1560    /** @hide */
1561    @IntDef(flag = true,
1562            value = {
1563                FOCUSABLES_ALL,
1564                FOCUSABLES_TOUCH_MODE
1565            })
1566    @Retention(RetentionPolicy.SOURCE)
1567    public @interface FocusableMode {}
1568
1569    /**
1570     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1571     * should add all focusable Views regardless if they are focusable in touch mode.
1572     */
1573    public static final int FOCUSABLES_ALL = 0x00000000;
1574
1575    /**
1576     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1577     * should add only Views focusable in touch mode.
1578     */
1579    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1580
1581    /** @hide */
1582    @IntDef({
1583            FOCUS_BACKWARD,
1584            FOCUS_FORWARD,
1585            FOCUS_LEFT,
1586            FOCUS_UP,
1587            FOCUS_RIGHT,
1588            FOCUS_DOWN
1589    })
1590    @Retention(RetentionPolicy.SOURCE)
1591    public @interface FocusDirection {}
1592
1593    /** @hide */
1594    @IntDef({
1595            FOCUS_LEFT,
1596            FOCUS_UP,
1597            FOCUS_RIGHT,
1598            FOCUS_DOWN
1599    })
1600    @Retention(RetentionPolicy.SOURCE)
1601    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1602
1603    /**
1604     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1605     * item.
1606     */
1607    public static final int FOCUS_BACKWARD = 0x00000001;
1608
1609    /**
1610     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1611     * item.
1612     */
1613    public static final int FOCUS_FORWARD = 0x00000002;
1614
1615    /**
1616     * Use with {@link #focusSearch(int)}. Move focus to the left.
1617     */
1618    public static final int FOCUS_LEFT = 0x00000011;
1619
1620    /**
1621     * Use with {@link #focusSearch(int)}. Move focus up.
1622     */
1623    public static final int FOCUS_UP = 0x00000021;
1624
1625    /**
1626     * Use with {@link #focusSearch(int)}. Move focus to the right.
1627     */
1628    public static final int FOCUS_RIGHT = 0x00000042;
1629
1630    /**
1631     * Use with {@link #focusSearch(int)}. Move focus down.
1632     */
1633    public static final int FOCUS_DOWN = 0x00000082;
1634
1635    /**
1636     * Bits of {@link #getMeasuredWidthAndState()} and
1637     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1638     */
1639    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1640
1641    /**
1642     * Bits of {@link #getMeasuredWidthAndState()} and
1643     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1644     */
1645    public static final int MEASURED_STATE_MASK = 0xff000000;
1646
1647    /**
1648     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1649     * for functions that combine both width and height into a single int,
1650     * such as {@link #getMeasuredState()} and the childState argument of
1651     * {@link #resolveSizeAndState(int, int, int)}.
1652     */
1653    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1654
1655    /**
1656     * Bit of {@link #getMeasuredWidthAndState()} and
1657     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1658     * is smaller that the space the view would like to have.
1659     */
1660    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1661
1662    /**
1663     * Base View state sets
1664     */
1665    // Singles
1666    /**
1667     * Indicates the view has no states set. States are used with
1668     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1669     * view depending on its state.
1670     *
1671     * @see android.graphics.drawable.Drawable
1672     * @see #getDrawableState()
1673     */
1674    protected static final int[] EMPTY_STATE_SET;
1675    /**
1676     * Indicates the view is enabled. States are used with
1677     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1678     * view depending on its state.
1679     *
1680     * @see android.graphics.drawable.Drawable
1681     * @see #getDrawableState()
1682     */
1683    protected static final int[] ENABLED_STATE_SET;
1684    /**
1685     * Indicates the view is focused. States are used with
1686     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1687     * view depending on its state.
1688     *
1689     * @see android.graphics.drawable.Drawable
1690     * @see #getDrawableState()
1691     */
1692    protected static final int[] FOCUSED_STATE_SET;
1693    /**
1694     * Indicates the view is selected. States are used with
1695     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1696     * view depending on its state.
1697     *
1698     * @see android.graphics.drawable.Drawable
1699     * @see #getDrawableState()
1700     */
1701    protected static final int[] SELECTED_STATE_SET;
1702    /**
1703     * Indicates the view is pressed. States are used with
1704     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1705     * view depending on its state.
1706     *
1707     * @see android.graphics.drawable.Drawable
1708     * @see #getDrawableState()
1709     */
1710    protected static final int[] PRESSED_STATE_SET;
1711    /**
1712     * Indicates the view's window has focus. States are used with
1713     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1714     * view depending on its state.
1715     *
1716     * @see android.graphics.drawable.Drawable
1717     * @see #getDrawableState()
1718     */
1719    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1720    // Doubles
1721    /**
1722     * Indicates the view is enabled and has the focus.
1723     *
1724     * @see #ENABLED_STATE_SET
1725     * @see #FOCUSED_STATE_SET
1726     */
1727    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1728    /**
1729     * Indicates the view is enabled and selected.
1730     *
1731     * @see #ENABLED_STATE_SET
1732     * @see #SELECTED_STATE_SET
1733     */
1734    protected static final int[] ENABLED_SELECTED_STATE_SET;
1735    /**
1736     * Indicates the view is enabled and that its window has focus.
1737     *
1738     * @see #ENABLED_STATE_SET
1739     * @see #WINDOW_FOCUSED_STATE_SET
1740     */
1741    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1742    /**
1743     * Indicates the view is focused and selected.
1744     *
1745     * @see #FOCUSED_STATE_SET
1746     * @see #SELECTED_STATE_SET
1747     */
1748    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1749    /**
1750     * Indicates the view has the focus and that its window has the focus.
1751     *
1752     * @see #FOCUSED_STATE_SET
1753     * @see #WINDOW_FOCUSED_STATE_SET
1754     */
1755    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1756    /**
1757     * Indicates the view is selected and that its window has the focus.
1758     *
1759     * @see #SELECTED_STATE_SET
1760     * @see #WINDOW_FOCUSED_STATE_SET
1761     */
1762    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1763    // Triples
1764    /**
1765     * Indicates the view is enabled, focused and selected.
1766     *
1767     * @see #ENABLED_STATE_SET
1768     * @see #FOCUSED_STATE_SET
1769     * @see #SELECTED_STATE_SET
1770     */
1771    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1772    /**
1773     * Indicates the view is enabled, focused and its window has the focus.
1774     *
1775     * @see #ENABLED_STATE_SET
1776     * @see #FOCUSED_STATE_SET
1777     * @see #WINDOW_FOCUSED_STATE_SET
1778     */
1779    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1780    /**
1781     * Indicates the view is enabled, selected and its window has the focus.
1782     *
1783     * @see #ENABLED_STATE_SET
1784     * @see #SELECTED_STATE_SET
1785     * @see #WINDOW_FOCUSED_STATE_SET
1786     */
1787    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1788    /**
1789     * Indicates the view is focused, selected and its window has the focus.
1790     *
1791     * @see #FOCUSED_STATE_SET
1792     * @see #SELECTED_STATE_SET
1793     * @see #WINDOW_FOCUSED_STATE_SET
1794     */
1795    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1796    /**
1797     * Indicates the view is enabled, focused, selected and its window
1798     * has the focus.
1799     *
1800     * @see #ENABLED_STATE_SET
1801     * @see #FOCUSED_STATE_SET
1802     * @see #SELECTED_STATE_SET
1803     * @see #WINDOW_FOCUSED_STATE_SET
1804     */
1805    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1806    /**
1807     * Indicates the view is pressed and its window has the focus.
1808     *
1809     * @see #PRESSED_STATE_SET
1810     * @see #WINDOW_FOCUSED_STATE_SET
1811     */
1812    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1813    /**
1814     * Indicates the view is pressed and selected.
1815     *
1816     * @see #PRESSED_STATE_SET
1817     * @see #SELECTED_STATE_SET
1818     */
1819    protected static final int[] PRESSED_SELECTED_STATE_SET;
1820    /**
1821     * Indicates the view is pressed, selected and its window has the focus.
1822     *
1823     * @see #PRESSED_STATE_SET
1824     * @see #SELECTED_STATE_SET
1825     * @see #WINDOW_FOCUSED_STATE_SET
1826     */
1827    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1828    /**
1829     * Indicates the view is pressed and focused.
1830     *
1831     * @see #PRESSED_STATE_SET
1832     * @see #FOCUSED_STATE_SET
1833     */
1834    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1835    /**
1836     * Indicates the view is pressed, focused and its window has the focus.
1837     *
1838     * @see #PRESSED_STATE_SET
1839     * @see #FOCUSED_STATE_SET
1840     * @see #WINDOW_FOCUSED_STATE_SET
1841     */
1842    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1843    /**
1844     * Indicates the view is pressed, focused and selected.
1845     *
1846     * @see #PRESSED_STATE_SET
1847     * @see #SELECTED_STATE_SET
1848     * @see #FOCUSED_STATE_SET
1849     */
1850    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1851    /**
1852     * Indicates the view is pressed, focused, selected and its window has the focus.
1853     *
1854     * @see #PRESSED_STATE_SET
1855     * @see #FOCUSED_STATE_SET
1856     * @see #SELECTED_STATE_SET
1857     * @see #WINDOW_FOCUSED_STATE_SET
1858     */
1859    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1860    /**
1861     * Indicates the view is pressed and enabled.
1862     *
1863     * @see #PRESSED_STATE_SET
1864     * @see #ENABLED_STATE_SET
1865     */
1866    protected static final int[] PRESSED_ENABLED_STATE_SET;
1867    /**
1868     * Indicates the view is pressed, enabled and its window has the focus.
1869     *
1870     * @see #PRESSED_STATE_SET
1871     * @see #ENABLED_STATE_SET
1872     * @see #WINDOW_FOCUSED_STATE_SET
1873     */
1874    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1875    /**
1876     * Indicates the view is pressed, enabled and selected.
1877     *
1878     * @see #PRESSED_STATE_SET
1879     * @see #ENABLED_STATE_SET
1880     * @see #SELECTED_STATE_SET
1881     */
1882    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1883    /**
1884     * Indicates the view is pressed, enabled, selected and its window has the
1885     * focus.
1886     *
1887     * @see #PRESSED_STATE_SET
1888     * @see #ENABLED_STATE_SET
1889     * @see #SELECTED_STATE_SET
1890     * @see #WINDOW_FOCUSED_STATE_SET
1891     */
1892    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1893    /**
1894     * Indicates the view is pressed, enabled and focused.
1895     *
1896     * @see #PRESSED_STATE_SET
1897     * @see #ENABLED_STATE_SET
1898     * @see #FOCUSED_STATE_SET
1899     */
1900    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1901    /**
1902     * Indicates the view is pressed, enabled, focused and its window has the
1903     * focus.
1904     *
1905     * @see #PRESSED_STATE_SET
1906     * @see #ENABLED_STATE_SET
1907     * @see #FOCUSED_STATE_SET
1908     * @see #WINDOW_FOCUSED_STATE_SET
1909     */
1910    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1911    /**
1912     * Indicates the view is pressed, enabled, focused and selected.
1913     *
1914     * @see #PRESSED_STATE_SET
1915     * @see #ENABLED_STATE_SET
1916     * @see #SELECTED_STATE_SET
1917     * @see #FOCUSED_STATE_SET
1918     */
1919    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1920    /**
1921     * Indicates the view is pressed, enabled, focused, selected and its window
1922     * has the focus.
1923     *
1924     * @see #PRESSED_STATE_SET
1925     * @see #ENABLED_STATE_SET
1926     * @see #SELECTED_STATE_SET
1927     * @see #FOCUSED_STATE_SET
1928     * @see #WINDOW_FOCUSED_STATE_SET
1929     */
1930    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1931
1932    static {
1933        EMPTY_STATE_SET = StateSet.get(0);
1934
1935        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1936
1937        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1938        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1939                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1940
1941        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1942        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1943                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1944        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1945                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1946        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1947                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1948                        | StateSet.VIEW_STATE_FOCUSED);
1949
1950        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1951        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1952                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1953        ENABLED_SELECTED_STATE_SET = StateSet.get(
1954                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1955        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1956                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1957                        | StateSet.VIEW_STATE_ENABLED);
1958        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1959                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1960        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1961                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1962                        | StateSet.VIEW_STATE_ENABLED);
1963        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1964                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1965                        | StateSet.VIEW_STATE_ENABLED);
1966        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1967                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1968                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1969
1970        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1971        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1972                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1973        PRESSED_SELECTED_STATE_SET = StateSet.get(
1974                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1975        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1976                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1977                        | StateSet.VIEW_STATE_PRESSED);
1978        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1979                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1980        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1981                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1982                        | StateSet.VIEW_STATE_PRESSED);
1983        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1984                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1985                        | StateSet.VIEW_STATE_PRESSED);
1986        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1987                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1988                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1989        PRESSED_ENABLED_STATE_SET = StateSet.get(
1990                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1991        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1992                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1993                        | StateSet.VIEW_STATE_PRESSED);
1994        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1995                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1996                        | StateSet.VIEW_STATE_PRESSED);
1997        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1998                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1999                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2000        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2001                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2002                        | StateSet.VIEW_STATE_PRESSED);
2003        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2004                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2005                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2006        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2007                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2008                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2009        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2010                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2011                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2012                        | StateSet.VIEW_STATE_PRESSED);
2013    }
2014
2015    /**
2016     * Accessibility event types that are dispatched for text population.
2017     */
2018    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2019            AccessibilityEvent.TYPE_VIEW_CLICKED
2020            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2021            | AccessibilityEvent.TYPE_VIEW_SELECTED
2022            | AccessibilityEvent.TYPE_VIEW_FOCUSED
2023            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2024            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2025            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2026            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2027            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2028            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2029            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2030
2031    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2032
2033    static final int DEBUG_CORNERS_SIZE_DIP = 8;
2034
2035    /**
2036     * Temporary Rect currently for use in setBackground().  This will probably
2037     * be extended in the future to hold our own class with more than just
2038     * a Rect. :)
2039     */
2040    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2041
2042    /**
2043     * Map used to store views' tags.
2044     */
2045    private SparseArray<Object> mKeyedTags;
2046
2047    /**
2048     * The animation currently associated with this view.
2049     * @hide
2050     */
2051    protected Animation mCurrentAnimation = null;
2052
2053    /**
2054     * Width as measured during measure pass.
2055     * {@hide}
2056     */
2057    @ViewDebug.ExportedProperty(category = "measurement")
2058    int mMeasuredWidth;
2059
2060    /**
2061     * Height as measured during measure pass.
2062     * {@hide}
2063     */
2064    @ViewDebug.ExportedProperty(category = "measurement")
2065    int mMeasuredHeight;
2066
2067    /**
2068     * Flag to indicate that this view was marked INVALIDATED, or had its display list
2069     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2070     * its display list. This flag, used only when hw accelerated, allows us to clear the
2071     * flag while retaining this information until it's needed (at getDisplayList() time and
2072     * in drawChild(), when we decide to draw a view's children's display lists into our own).
2073     *
2074     * {@hide}
2075     */
2076    boolean mRecreateDisplayList = false;
2077
2078    /**
2079     * The view's identifier.
2080     * {@hide}
2081     *
2082     * @see #setId(int)
2083     * @see #getId()
2084     */
2085    @IdRes
2086    @ViewDebug.ExportedProperty(resolveId = true)
2087    int mID = NO_ID;
2088
2089    /** The ID of this view for accessibility and autofill purposes.
2090     * <ul>
2091     *     <li>== {@link #NO_ID}: ID has not been assigned yet
2092     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
2093     *                                                  unique in the process. This might change
2094     *                                                  over activity lifecycle events.
2095     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
2096     *                                                  unique in the activity. This stays the same
2097     *                                                  over activity lifecycle events.
2098     */
2099    private int mAccessibilityViewId = NO_ID;
2100
2101    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2102
2103    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2104
2105    /**
2106     * The view's tag.
2107     * {@hide}
2108     *
2109     * @see #setTag(Object)
2110     * @see #getTag()
2111     */
2112    protected Object mTag = null;
2113
2114    // for mPrivateFlags:
2115    /** {@hide} */
2116    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2117    /** {@hide} */
2118    static final int PFLAG_FOCUSED                     = 0x00000002;
2119    /** {@hide} */
2120    static final int PFLAG_SELECTED                    = 0x00000004;
2121    /** {@hide} */
2122    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2123    /** {@hide} */
2124    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2125    /** {@hide} */
2126    static final int PFLAG_DRAWN                       = 0x00000020;
2127    /**
2128     * When this flag is set, this view is running an animation on behalf of its
2129     * children and should therefore not cancel invalidate requests, even if they
2130     * lie outside of this view's bounds.
2131     *
2132     * {@hide}
2133     */
2134    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2135    /** {@hide} */
2136    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2137    /** {@hide} */
2138    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2139    /** {@hide} */
2140    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2141    /** {@hide} */
2142    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2143    /** {@hide} */
2144    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2145    /** {@hide} */
2146    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2147
2148    private static final int PFLAG_PRESSED             = 0x00004000;
2149
2150    /** {@hide} */
2151    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2152    /**
2153     * Flag used to indicate that this view should be drawn once more (and only once
2154     * more) after its animation has completed.
2155     * {@hide}
2156     */
2157    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2158
2159    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2160
2161    /**
2162     * Indicates that the View returned true when onSetAlpha() was called and that
2163     * the alpha must be restored.
2164     * {@hide}
2165     */
2166    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2167
2168    /**
2169     * Set by {@link #setScrollContainer(boolean)}.
2170     */
2171    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2172
2173    /**
2174     * Set by {@link #setScrollContainer(boolean)}.
2175     */
2176    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2177
2178    /**
2179     * View flag indicating whether this view was invalidated (fully or partially.)
2180     *
2181     * @hide
2182     */
2183    static final int PFLAG_DIRTY                       = 0x00200000;
2184
2185    /**
2186     * View flag indicating whether this view was invalidated by an opaque
2187     * invalidate request.
2188     *
2189     * @hide
2190     */
2191    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2192
2193    /**
2194     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2195     *
2196     * @hide
2197     */
2198    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2199
2200    /**
2201     * Indicates whether the background is opaque.
2202     *
2203     * @hide
2204     */
2205    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2206
2207    /**
2208     * Indicates whether the scrollbars are opaque.
2209     *
2210     * @hide
2211     */
2212    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2213
2214    /**
2215     * Indicates whether the view is opaque.
2216     *
2217     * @hide
2218     */
2219    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2220
2221    /**
2222     * Indicates a prepressed state;
2223     * the short time between ACTION_DOWN and recognizing
2224     * a 'real' press. Prepressed is used to recognize quick taps
2225     * even when they are shorter than ViewConfiguration.getTapTimeout().
2226     *
2227     * @hide
2228     */
2229    private static final int PFLAG_PREPRESSED          = 0x02000000;
2230
2231    /**
2232     * Indicates whether the view is temporarily detached.
2233     *
2234     * @hide
2235     */
2236    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2237
2238    /**
2239     * Indicates that we should awaken scroll bars once attached
2240     *
2241     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2242     * during window attachment and it is no longer needed. Feel free to repurpose it.
2243     *
2244     * @hide
2245     */
2246    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2247
2248    /**
2249     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2250     * @hide
2251     */
2252    private static final int PFLAG_HOVERED             = 0x10000000;
2253
2254    /**
2255     * no longer needed, should be reused
2256     */
2257    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2258
2259    /** {@hide} */
2260    static final int PFLAG_ACTIVATED                   = 0x40000000;
2261
2262    /**
2263     * Indicates that this view was specifically invalidated, not just dirtied because some
2264     * child view was invalidated. The flag is used to determine when we need to recreate
2265     * a view's display list (as opposed to just returning a reference to its existing
2266     * display list).
2267     *
2268     * @hide
2269     */
2270    static final int PFLAG_INVALIDATED                 = 0x80000000;
2271
2272    /**
2273     * Masks for mPrivateFlags2, as generated by dumpFlags():
2274     *
2275     * |-------|-------|-------|-------|
2276     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2277     *                                1  PFLAG2_DRAG_HOVERED
2278     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2279     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2280     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2281     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2282     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2283     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2284     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2285     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2286     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2287     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2288     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2289     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2290     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2291     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2292     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2293     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2294     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2295     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2296     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2297     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2298     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2299     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2300     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2301     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2302     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2303     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2304     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2305     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2306     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2307     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2308     *    1                              PFLAG2_PADDING_RESOLVED
2309     *   1                               PFLAG2_DRAWABLE_RESOLVED
2310     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2311     * |-------|-------|-------|-------|
2312     */
2313
2314    /**
2315     * Indicates that this view has reported that it can accept the current drag's content.
2316     * Cleared when the drag operation concludes.
2317     * @hide
2318     */
2319    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2320
2321    /**
2322     * Indicates that this view is currently directly under the drag location in a
2323     * drag-and-drop operation involving content that it can accept.  Cleared when
2324     * the drag exits the view, or when the drag operation concludes.
2325     * @hide
2326     */
2327    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2328
2329    /** @hide */
2330    @IntDef({
2331        LAYOUT_DIRECTION_LTR,
2332        LAYOUT_DIRECTION_RTL,
2333        LAYOUT_DIRECTION_INHERIT,
2334        LAYOUT_DIRECTION_LOCALE
2335    })
2336    @Retention(RetentionPolicy.SOURCE)
2337    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2338    public @interface LayoutDir {}
2339
2340    /** @hide */
2341    @IntDef({
2342        LAYOUT_DIRECTION_LTR,
2343        LAYOUT_DIRECTION_RTL
2344    })
2345    @Retention(RetentionPolicy.SOURCE)
2346    public @interface ResolvedLayoutDir {}
2347
2348    /**
2349     * A flag to indicate that the layout direction of this view has not been defined yet.
2350     * @hide
2351     */
2352    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2353
2354    /**
2355     * Horizontal layout direction of this view is from Left to Right.
2356     * Use with {@link #setLayoutDirection}.
2357     */
2358    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2359
2360    /**
2361     * Horizontal layout direction of this view is from Right to Left.
2362     * Use with {@link #setLayoutDirection}.
2363     */
2364    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2365
2366    /**
2367     * Horizontal layout direction of this view is inherited from its parent.
2368     * Use with {@link #setLayoutDirection}.
2369     */
2370    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2371
2372    /**
2373     * Horizontal layout direction of this view is from deduced from the default language
2374     * script for the locale. Use with {@link #setLayoutDirection}.
2375     */
2376    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2377
2378    /**
2379     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2380     * @hide
2381     */
2382    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2383
2384    /**
2385     * Mask for use with private flags indicating bits used for horizontal layout direction.
2386     * @hide
2387     */
2388    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2389
2390    /**
2391     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2392     * right-to-left direction.
2393     * @hide
2394     */
2395    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2396
2397    /**
2398     * Indicates whether the view horizontal layout direction has been resolved.
2399     * @hide
2400     */
2401    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2402
2403    /**
2404     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2405     * @hide
2406     */
2407    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2408            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2409
2410    /*
2411     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2412     * flag value.
2413     * @hide
2414     */
2415    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2416            LAYOUT_DIRECTION_LTR,
2417            LAYOUT_DIRECTION_RTL,
2418            LAYOUT_DIRECTION_INHERIT,
2419            LAYOUT_DIRECTION_LOCALE
2420    };
2421
2422    /**
2423     * Default horizontal layout direction.
2424     */
2425    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2426
2427    /**
2428     * Default horizontal layout direction.
2429     * @hide
2430     */
2431    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2432
2433    /**
2434     * Text direction is inherited through {@link ViewGroup}
2435     */
2436    public static final int TEXT_DIRECTION_INHERIT = 0;
2437
2438    /**
2439     * Text direction is using "first strong algorithm". The first strong directional character
2440     * determines the paragraph direction. If there is no strong directional character, the
2441     * paragraph direction is the view's resolved layout direction.
2442     */
2443    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2444
2445    /**
2446     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2447     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2448     * If there are neither, the paragraph direction is the view's resolved layout direction.
2449     */
2450    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2451
2452    /**
2453     * Text direction is forced to LTR.
2454     */
2455    public static final int TEXT_DIRECTION_LTR = 3;
2456
2457    /**
2458     * Text direction is forced to RTL.
2459     */
2460    public static final int TEXT_DIRECTION_RTL = 4;
2461
2462    /**
2463     * Text direction is coming from the system Locale.
2464     */
2465    public static final int TEXT_DIRECTION_LOCALE = 5;
2466
2467    /**
2468     * Text direction is using "first strong algorithm". The first strong directional character
2469     * determines the paragraph direction. If there is no strong directional character, the
2470     * paragraph direction is LTR.
2471     */
2472    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2473
2474    /**
2475     * Text direction is using "first strong algorithm". The first strong directional character
2476     * determines the paragraph direction. If there is no strong directional character, the
2477     * paragraph direction is RTL.
2478     */
2479    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2480
2481    /**
2482     * Default text direction is inherited
2483     */
2484    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2485
2486    /**
2487     * Default resolved text direction
2488     * @hide
2489     */
2490    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2491
2492    /**
2493     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2494     * @hide
2495     */
2496    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2497
2498    /**
2499     * Mask for use with private flags indicating bits used for text direction.
2500     * @hide
2501     */
2502    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2503            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2504
2505    /**
2506     * Array of text direction flags for mapping attribute "textDirection" to correct
2507     * flag value.
2508     * @hide
2509     */
2510    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2511            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2512            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2513            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2514            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2515            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2516            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2517            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2518            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2519    };
2520
2521    /**
2522     * Indicates whether the view text direction has been resolved.
2523     * @hide
2524     */
2525    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2526            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2527
2528    /**
2529     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2530     * @hide
2531     */
2532    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2533
2534    /**
2535     * Mask for use with private flags indicating bits used for resolved text direction.
2536     * @hide
2537     */
2538    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2539            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2540
2541    /**
2542     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2543     * @hide
2544     */
2545    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2546            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2547
2548    /** @hide */
2549    @IntDef({
2550        TEXT_ALIGNMENT_INHERIT,
2551        TEXT_ALIGNMENT_GRAVITY,
2552        TEXT_ALIGNMENT_CENTER,
2553        TEXT_ALIGNMENT_TEXT_START,
2554        TEXT_ALIGNMENT_TEXT_END,
2555        TEXT_ALIGNMENT_VIEW_START,
2556        TEXT_ALIGNMENT_VIEW_END
2557    })
2558    @Retention(RetentionPolicy.SOURCE)
2559    public @interface TextAlignment {}
2560
2561    /**
2562     * Default text alignment. The text alignment of this View is inherited from its parent.
2563     * Use with {@link #setTextAlignment(int)}
2564     */
2565    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2566
2567    /**
2568     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2569     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2570     *
2571     * Use with {@link #setTextAlignment(int)}
2572     */
2573    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2574
2575    /**
2576     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2577     *
2578     * Use with {@link #setTextAlignment(int)}
2579     */
2580    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2581
2582    /**
2583     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2584     *
2585     * Use with {@link #setTextAlignment(int)}
2586     */
2587    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2588
2589    /**
2590     * Center the paragraph, e.g. ALIGN_CENTER.
2591     *
2592     * Use with {@link #setTextAlignment(int)}
2593     */
2594    public static final int TEXT_ALIGNMENT_CENTER = 4;
2595
2596    /**
2597     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2598     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2599     *
2600     * Use with {@link #setTextAlignment(int)}
2601     */
2602    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2603
2604    /**
2605     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2606     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2607     *
2608     * Use with {@link #setTextAlignment(int)}
2609     */
2610    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2611
2612    /**
2613     * Default text alignment is inherited
2614     */
2615    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2616
2617    /**
2618     * Default resolved text alignment
2619     * @hide
2620     */
2621    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2622
2623    /**
2624      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2625      * @hide
2626      */
2627    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2628
2629    /**
2630      * Mask for use with private flags indicating bits used for text alignment.
2631      * @hide
2632      */
2633    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2634
2635    /**
2636     * Array of text direction flags for mapping attribute "textAlignment" to correct
2637     * flag value.
2638     * @hide
2639     */
2640    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2641            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2642            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2643            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2644            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2645            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2646            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2647            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2648    };
2649
2650    /**
2651     * Indicates whether the view text alignment has been resolved.
2652     * @hide
2653     */
2654    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2655
2656    /**
2657     * Bit shift to get the resolved text alignment.
2658     * @hide
2659     */
2660    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2661
2662    /**
2663     * Mask for use with private flags indicating bits used for text alignment.
2664     * @hide
2665     */
2666    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2667            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2668
2669    /**
2670     * Indicates whether if the view text alignment has been resolved to gravity
2671     */
2672    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2673            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2674
2675    // Accessiblity constants for mPrivateFlags2
2676
2677    /**
2678     * Shift for the bits in {@link #mPrivateFlags2} related to the
2679     * "importantForAccessibility" attribute.
2680     */
2681    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2682
2683    /**
2684     * Automatically determine whether a view is important for accessibility.
2685     */
2686    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2687
2688    /**
2689     * The view is important for accessibility.
2690     */
2691    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2692
2693    /**
2694     * The view is not important for accessibility.
2695     */
2696    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2697
2698    /**
2699     * The view is not important for accessibility, nor are any of its
2700     * descendant views.
2701     */
2702    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2703
2704    /**
2705     * The default whether the view is important for accessibility.
2706     */
2707    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2708
2709    /**
2710     * Mask for obtaining the bits which specify how to determine
2711     * whether a view is important for accessibility.
2712     */
2713    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2714        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2715        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2716        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2717
2718    /**
2719     * Shift for the bits in {@link #mPrivateFlags2} related to the
2720     * "accessibilityLiveRegion" attribute.
2721     */
2722    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2723
2724    /**
2725     * Live region mode specifying that accessibility services should not
2726     * automatically announce changes to this view. This is the default live
2727     * region mode for most views.
2728     * <p>
2729     * Use with {@link #setAccessibilityLiveRegion(int)}.
2730     */
2731    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2732
2733    /**
2734     * Live region mode specifying that accessibility services should announce
2735     * changes to this view.
2736     * <p>
2737     * Use with {@link #setAccessibilityLiveRegion(int)}.
2738     */
2739    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2740
2741    /**
2742     * Live region mode specifying that accessibility services should interrupt
2743     * ongoing speech to immediately announce changes to this view.
2744     * <p>
2745     * Use with {@link #setAccessibilityLiveRegion(int)}.
2746     */
2747    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2748
2749    /**
2750     * The default whether the view is important for accessibility.
2751     */
2752    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2753
2754    /**
2755     * Mask for obtaining the bits which specify a view's accessibility live
2756     * region mode.
2757     */
2758    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2759            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2760            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2761
2762    /**
2763     * Flag indicating whether a view has accessibility focus.
2764     */
2765    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2766
2767    /**
2768     * Flag whether the accessibility state of the subtree rooted at this view changed.
2769     */
2770    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2771
2772    /**
2773     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2774     * is used to check whether later changes to the view's transform should invalidate the
2775     * view to force the quickReject test to run again.
2776     */
2777    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2778
2779    /**
2780     * Flag indicating that start/end padding has been resolved into left/right padding
2781     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2782     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2783     * during measurement. In some special cases this is required such as when an adapter-based
2784     * view measures prospective children without attaching them to a window.
2785     */
2786    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2787
2788    /**
2789     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2790     */
2791    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2792
2793    /**
2794     * Indicates that the view is tracking some sort of transient state
2795     * that the app should not need to be aware of, but that the framework
2796     * should take special care to preserve.
2797     */
2798    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2799
2800    /**
2801     * Group of bits indicating that RTL properties resolution is done.
2802     */
2803    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2804            PFLAG2_TEXT_DIRECTION_RESOLVED |
2805            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2806            PFLAG2_PADDING_RESOLVED |
2807            PFLAG2_DRAWABLE_RESOLVED;
2808
2809    // There are a couple of flags left in mPrivateFlags2
2810
2811    /* End of masks for mPrivateFlags2 */
2812
2813    /**
2814     * Masks for mPrivateFlags3, as generated by dumpFlags():
2815     *
2816     * |-------|-------|-------|-------|
2817     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2818     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2819     *                               1   PFLAG3_IS_LAID_OUT
2820     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2821     *                             1     PFLAG3_CALLED_SUPER
2822     *                            1      PFLAG3_APPLYING_INSETS
2823     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2824     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2825     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2826     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2827     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2828     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2829     *                     1             PFLAG3_SCROLL_INDICATOR_START
2830     *                    1              PFLAG3_SCROLL_INDICATOR_END
2831     *                   1               PFLAG3_ASSIST_BLOCKED
2832     *                  1                PFLAG3_CLUSTER
2833     *                 1                 PFLAG3_IS_AUTOFILLED
2834     *                1                  PFLAG3_FINGER_DOWN
2835     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2836     *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2837     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2838     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2839     *        1                          PFLAG3_TEMPORARY_DETACH
2840     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2841     *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2842     * |-------|-------|-------|-------|
2843     */
2844
2845    /**
2846     * Flag indicating that view has a transform animation set on it. This is used to track whether
2847     * an animation is cleared between successive frames, in order to tell the associated
2848     * DisplayList to clear its animation matrix.
2849     */
2850    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2851
2852    /**
2853     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2854     * animation is cleared between successive frames, in order to tell the associated
2855     * DisplayList to restore its alpha value.
2856     */
2857    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2858
2859    /**
2860     * Flag indicating that the view has been through at least one layout since it
2861     * was last attached to a window.
2862     */
2863    static final int PFLAG3_IS_LAID_OUT = 0x4;
2864
2865    /**
2866     * Flag indicating that a call to measure() was skipped and should be done
2867     * instead when layout() is invoked.
2868     */
2869    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2870
2871    /**
2872     * Flag indicating that an overridden method correctly called down to
2873     * the superclass implementation as required by the API spec.
2874     */
2875    static final int PFLAG3_CALLED_SUPER = 0x10;
2876
2877    /**
2878     * Flag indicating that we're in the process of applying window insets.
2879     */
2880    static final int PFLAG3_APPLYING_INSETS = 0x20;
2881
2882    /**
2883     * Flag indicating that we're in the process of fitting system windows using the old method.
2884     */
2885    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2886
2887    /**
2888     * Flag indicating that nested scrolling is enabled for this view.
2889     * The view will optionally cooperate with views up its parent chain to allow for
2890     * integrated nested scrolling along the same axis.
2891     */
2892    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2893
2894    /**
2895     * Flag indicating that the bottom scroll indicator should be displayed
2896     * when this view can scroll up.
2897     */
2898    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2899
2900    /**
2901     * Flag indicating that the bottom scroll indicator should be displayed
2902     * when this view can scroll down.
2903     */
2904    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2905
2906    /**
2907     * Flag indicating that the left scroll indicator should be displayed
2908     * when this view can scroll left.
2909     */
2910    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2911
2912    /**
2913     * Flag indicating that the right scroll indicator should be displayed
2914     * when this view can scroll right.
2915     */
2916    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2917
2918    /**
2919     * Flag indicating that the start scroll indicator should be displayed
2920     * when this view can scroll in the start direction.
2921     */
2922    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2923
2924    /**
2925     * Flag indicating that the end scroll indicator should be displayed
2926     * when this view can scroll in the end direction.
2927     */
2928    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2929
2930    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2931
2932    static final int SCROLL_INDICATORS_NONE = 0x0000;
2933
2934    /**
2935     * Mask for use with setFlags indicating bits used for indicating which
2936     * scroll indicators are enabled.
2937     */
2938    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2939            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2940            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2941            | PFLAG3_SCROLL_INDICATOR_END;
2942
2943    /**
2944     * Left-shift required to translate between public scroll indicator flags
2945     * and internal PFLAGS3 flags. When used as a right-shift, translates
2946     * PFLAGS3 flags to public flags.
2947     */
2948    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2949
2950    /** @hide */
2951    @Retention(RetentionPolicy.SOURCE)
2952    @IntDef(flag = true,
2953            value = {
2954                    SCROLL_INDICATOR_TOP,
2955                    SCROLL_INDICATOR_BOTTOM,
2956                    SCROLL_INDICATOR_LEFT,
2957                    SCROLL_INDICATOR_RIGHT,
2958                    SCROLL_INDICATOR_START,
2959                    SCROLL_INDICATOR_END,
2960            })
2961    public @interface ScrollIndicators {}
2962
2963    /**
2964     * Scroll indicator direction for the top edge of the view.
2965     *
2966     * @see #setScrollIndicators(int)
2967     * @see #setScrollIndicators(int, int)
2968     * @see #getScrollIndicators()
2969     */
2970    public static final int SCROLL_INDICATOR_TOP =
2971            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2972
2973    /**
2974     * Scroll indicator direction for the bottom edge of the view.
2975     *
2976     * @see #setScrollIndicators(int)
2977     * @see #setScrollIndicators(int, int)
2978     * @see #getScrollIndicators()
2979     */
2980    public static final int SCROLL_INDICATOR_BOTTOM =
2981            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2982
2983    /**
2984     * Scroll indicator direction for the left edge of the view.
2985     *
2986     * @see #setScrollIndicators(int)
2987     * @see #setScrollIndicators(int, int)
2988     * @see #getScrollIndicators()
2989     */
2990    public static final int SCROLL_INDICATOR_LEFT =
2991            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2992
2993    /**
2994     * Scroll indicator direction for the right edge of the view.
2995     *
2996     * @see #setScrollIndicators(int)
2997     * @see #setScrollIndicators(int, int)
2998     * @see #getScrollIndicators()
2999     */
3000    public static final int SCROLL_INDICATOR_RIGHT =
3001            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3002
3003    /**
3004     * Scroll indicator direction for the starting edge of the view.
3005     * <p>
3006     * Resolved according to the view's layout direction, see
3007     * {@link #getLayoutDirection()} for more information.
3008     *
3009     * @see #setScrollIndicators(int)
3010     * @see #setScrollIndicators(int, int)
3011     * @see #getScrollIndicators()
3012     */
3013    public static final int SCROLL_INDICATOR_START =
3014            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3015
3016    /**
3017     * Scroll indicator direction for the ending edge of the view.
3018     * <p>
3019     * Resolved according to the view's layout direction, see
3020     * {@link #getLayoutDirection()} for more information.
3021     *
3022     * @see #setScrollIndicators(int)
3023     * @see #setScrollIndicators(int, int)
3024     * @see #getScrollIndicators()
3025     */
3026    public static final int SCROLL_INDICATOR_END =
3027            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3028
3029    /**
3030     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3031     * into this view.<p>
3032     */
3033    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3034
3035    /**
3036     * Flag indicating that the view is a root of a keyboard navigation cluster.
3037     *
3038     * @see #isKeyboardNavigationCluster()
3039     * @see #setKeyboardNavigationCluster(boolean)
3040     */
3041    private static final int PFLAG3_CLUSTER = 0x8000;
3042
3043    /**
3044     * Flag indicating that the view is autofilled
3045     *
3046     * @see #isAutofilled()
3047     * @see #setAutofilled(boolean)
3048     */
3049    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3050
3051    /**
3052     * Indicates that the user is currently touching the screen.
3053     * Currently used for the tooltip positioning only.
3054     */
3055    private static final int PFLAG3_FINGER_DOWN = 0x20000;
3056
3057    /**
3058     * Flag indicating that this view is the default-focus view.
3059     *
3060     * @see #isFocusedByDefault()
3061     * @see #setFocusedByDefault(boolean)
3062     */
3063    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3064
3065    /**
3066     * Shift for the bits in {@link #mPrivateFlags3} related to the
3067     * "importantForAutofill" attribute.
3068     */
3069    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3070
3071    /**
3072     * Mask for obtaining the bits which specify how to determine
3073     * whether a view is important for autofill.
3074     */
3075    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3076            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3077            | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3078            | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3079            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3080
3081    /**
3082     * Whether this view has rendered elements that overlap (see {@link
3083     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3084     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3085     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3086     * determined by whatever {@link #hasOverlappingRendering()} returns.
3087     */
3088    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3089
3090    /**
3091     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3092     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3093     */
3094    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3095
3096    /**
3097     * Flag indicating that the view is temporarily detached from the parent view.
3098     *
3099     * @see #onStartTemporaryDetach()
3100     * @see #onFinishTemporaryDetach()
3101     */
3102    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3103
3104    /**
3105     * Flag indicating that the view does not wish to be revealed within its parent
3106     * hierarchy when it gains focus. Expressed in the negative since the historical
3107     * default behavior is to reveal on focus; this flag suppresses that behavior.
3108     *
3109     * @see #setRevealOnFocusHint(boolean)
3110     * @see #getRevealOnFocusHint()
3111     */
3112    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3113
3114    /**
3115     * Flag indicating that when layout is completed we should notify
3116     * that the view was entered for autofill purposes. To minimize
3117     * showing autofill for views not visible to the user we evaluate
3118     * user visibility which cannot be done until the view is laid out.
3119     */
3120    static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3121
3122    /* End of masks for mPrivateFlags3 */
3123
3124    /**
3125     * Always allow a user to over-scroll this view, provided it is a
3126     * view that can scroll.
3127     *
3128     * @see #getOverScrollMode()
3129     * @see #setOverScrollMode(int)
3130     */
3131    public static final int OVER_SCROLL_ALWAYS = 0;
3132
3133    /**
3134     * Allow a user to over-scroll this view only if the content is large
3135     * enough to meaningfully scroll, provided it is a view that can scroll.
3136     *
3137     * @see #getOverScrollMode()
3138     * @see #setOverScrollMode(int)
3139     */
3140    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3141
3142    /**
3143     * Never allow a user to over-scroll this view.
3144     *
3145     * @see #getOverScrollMode()
3146     * @see #setOverScrollMode(int)
3147     */
3148    public static final int OVER_SCROLL_NEVER = 2;
3149
3150    /**
3151     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3152     * requested the system UI (status bar) to be visible (the default).
3153     *
3154     * @see #setSystemUiVisibility(int)
3155     */
3156    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3157
3158    /**
3159     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3160     * system UI to enter an unobtrusive "low profile" mode.
3161     *
3162     * <p>This is for use in games, book readers, video players, or any other
3163     * "immersive" application where the usual system chrome is deemed too distracting.
3164     *
3165     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3166     *
3167     * @see #setSystemUiVisibility(int)
3168     */
3169    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3170
3171    /**
3172     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3173     * system navigation be temporarily hidden.
3174     *
3175     * <p>This is an even less obtrusive state than that called for by
3176     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3177     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3178     * those to disappear. This is useful (in conjunction with the
3179     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3180     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3181     * window flags) for displaying content using every last pixel on the display.
3182     *
3183     * <p>There is a limitation: because navigation controls are so important, the least user
3184     * interaction will cause them to reappear immediately.  When this happens, both
3185     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3186     * so that both elements reappear at the same time.
3187     *
3188     * @see #setSystemUiVisibility(int)
3189     */
3190    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3191
3192    /**
3193     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3194     * into the normal fullscreen mode so that its content can take over the screen
3195     * while still allowing the user to interact with the application.
3196     *
3197     * <p>This has the same visual effect as
3198     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3199     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3200     * meaning that non-critical screen decorations (such as the status bar) will be
3201     * hidden while the user is in the View's window, focusing the experience on
3202     * that content.  Unlike the window flag, if you are using ActionBar in
3203     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3204     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3205     * hide the action bar.
3206     *
3207     * <p>This approach to going fullscreen is best used over the window flag when
3208     * it is a transient state -- that is, the application does this at certain
3209     * points in its user interaction where it wants to allow the user to focus
3210     * on content, but not as a continuous state.  For situations where the application
3211     * would like to simply stay full screen the entire time (such as a game that
3212     * wants to take over the screen), the
3213     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3214     * is usually a better approach.  The state set here will be removed by the system
3215     * in various situations (such as the user moving to another application) like
3216     * the other system UI states.
3217     *
3218     * <p>When using this flag, the application should provide some easy facility
3219     * for the user to go out of it.  A common example would be in an e-book
3220     * reader, where tapping on the screen brings back whatever screen and UI
3221     * decorations that had been hidden while the user was immersed in reading
3222     * the book.
3223     *
3224     * @see #setSystemUiVisibility(int)
3225     */
3226    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3227
3228    /**
3229     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3230     * flags, we would like a stable view of the content insets given to
3231     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3232     * will always represent the worst case that the application can expect
3233     * as a continuous state.  In the stock Android UI this is the space for
3234     * the system bar, nav bar, and status bar, but not more transient elements
3235     * such as an input method.
3236     *
3237     * The stable layout your UI sees is based on the system UI modes you can
3238     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3239     * then you will get a stable layout for changes of the
3240     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3241     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3242     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3243     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3244     * with a stable layout.  (Note that you should avoid using
3245     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3246     *
3247     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3248     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3249     * then a hidden status bar will be considered a "stable" state for purposes
3250     * here.  This allows your UI to continually hide the status bar, while still
3251     * using the system UI flags to hide the action bar while still retaining
3252     * a stable layout.  Note that changing the window fullscreen flag will never
3253     * provide a stable layout for a clean transition.
3254     *
3255     * <p>If you are using ActionBar in
3256     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3257     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3258     * insets it adds to those given to the application.
3259     */
3260    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3261
3262    /**
3263     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3264     * to be laid out as if it has requested
3265     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3266     * allows it to avoid artifacts when switching in and out of that mode, at
3267     * the expense that some of its user interface may be covered by screen
3268     * decorations when they are shown.  You can perform layout of your inner
3269     * UI elements to account for the navigation system UI through the
3270     * {@link #fitSystemWindows(Rect)} method.
3271     */
3272    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3273
3274    /**
3275     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3276     * to be laid out as if it has requested
3277     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3278     * allows it to avoid artifacts when switching in and out of that mode, at
3279     * the expense that some of its user interface may be covered by screen
3280     * decorations when they are shown.  You can perform layout of your inner
3281     * UI elements to account for non-fullscreen system UI through the
3282     * {@link #fitSystemWindows(Rect)} method.
3283     */
3284    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3285
3286    /**
3287     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3288     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3289     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3290     * user interaction.
3291     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3292     * has an effect when used in combination with that flag.</p>
3293     */
3294    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3295
3296    /**
3297     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3298     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3299     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3300     * experience while also hiding the system bars.  If this flag is not set,
3301     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3302     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3303     * if the user swipes from the top of the screen.
3304     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3305     * system gestures, such as swiping from the top of the screen.  These transient system bars
3306     * will overlay app’s content, may have some degree of transparency, and will automatically
3307     * hide after a short timeout.
3308     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3309     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3310     * with one or both of those flags.</p>
3311     */
3312    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3313
3314    /**
3315     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3316     * is compatible with light status bar backgrounds.
3317     *
3318     * <p>For this to take effect, the window must request
3319     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3320     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3321     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3322     *         FLAG_TRANSLUCENT_STATUS}.
3323     *
3324     * @see android.R.attr#windowLightStatusBar
3325     */
3326    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3327
3328    /**
3329     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3330     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3331     */
3332    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3333
3334    /**
3335     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3336     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3337     */
3338    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3339
3340    /**
3341     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3342     * that is compatible with light navigation bar backgrounds.
3343     *
3344     * <p>For this to take effect, the window must request
3345     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3346     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3347     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3348     *         FLAG_TRANSLUCENT_NAVIGATION}.
3349     */
3350    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3351
3352    /**
3353     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3354     */
3355    @Deprecated
3356    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3357
3358    /**
3359     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3360     */
3361    @Deprecated
3362    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3363
3364    /**
3365     * @hide
3366     *
3367     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3368     * out of the public fields to keep the undefined bits out of the developer's way.
3369     *
3370     * Flag to make the status bar not expandable.  Unless you also
3371     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3372     */
3373    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3374
3375    /**
3376     * @hide
3377     *
3378     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3379     * out of the public fields to keep the undefined bits out of the developer's way.
3380     *
3381     * Flag to hide notification icons and scrolling ticker text.
3382     */
3383    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
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 incoming notification alerts.  This will not block
3392     * icons, but it will block sound, vibrating and other visual or aural notifications.
3393     */
3394    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
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 hide only the scrolling ticker.  Note that
3403     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3404     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3405     */
3406    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3407
3408    /**
3409     * @hide
3410     *
3411     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3412     * out of the public fields to keep the undefined bits out of the developer's way.
3413     *
3414     * Flag to hide the center system info area.
3415     */
3416    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3417
3418    /**
3419     * @hide
3420     *
3421     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3422     * out of the public fields to keep the undefined bits out of the developer's way.
3423     *
3424     * Flag to hide only the home button.  Don't use this
3425     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3426     */
3427    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3428
3429    /**
3430     * @hide
3431     *
3432     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3433     * out of the public fields to keep the undefined bits out of the developer's way.
3434     *
3435     * Flag to hide only the back button. Don't use this
3436     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3437     */
3438    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3439
3440    /**
3441     * @hide
3442     *
3443     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3444     * out of the public fields to keep the undefined bits out of the developer's way.
3445     *
3446     * Flag to hide only the clock.  You might use this if your activity has
3447     * its own clock making the status bar's clock redundant.
3448     */
3449    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3450
3451    /**
3452     * @hide
3453     *
3454     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3455     * out of the public fields to keep the undefined bits out of the developer's way.
3456     *
3457     * Flag to hide only the recent apps button. Don't use this
3458     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3459     */
3460    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3461
3462    /**
3463     * @hide
3464     *
3465     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3466     * out of the public fields to keep the undefined bits out of the developer's way.
3467     *
3468     * Flag to disable the global search gesture. Don't use this
3469     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3470     */
3471    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3472
3473    /**
3474     * @hide
3475     *
3476     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3477     * out of the public fields to keep the undefined bits out of the developer's way.
3478     *
3479     * Flag to specify that the status bar is displayed in transient mode.
3480     */
3481    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3482
3483    /**
3484     * @hide
3485     *
3486     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3487     * out of the public fields to keep the undefined bits out of the developer's way.
3488     *
3489     * Flag to specify that the navigation bar is displayed in transient mode.
3490     */
3491    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3492
3493    /**
3494     * @hide
3495     *
3496     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3497     * out of the public fields to keep the undefined bits out of the developer's way.
3498     *
3499     * Flag to specify that the hidden status bar would like to be shown.
3500     */
3501    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3502
3503    /**
3504     * @hide
3505     *
3506     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3507     * out of the public fields to keep the undefined bits out of the developer's way.
3508     *
3509     * Flag to specify that the hidden navigation bar would like to be shown.
3510     */
3511    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3512
3513    /**
3514     * @hide
3515     *
3516     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3517     * out of the public fields to keep the undefined bits out of the developer's way.
3518     *
3519     * Flag to specify that the status bar is displayed in translucent mode.
3520     */
3521    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3522
3523    /**
3524     * @hide
3525     *
3526     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3527     * out of the public fields to keep the undefined bits out of the developer's way.
3528     *
3529     * Flag to specify that the navigation bar is displayed in translucent mode.
3530     */
3531    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3532
3533    /**
3534     * @hide
3535     *
3536     * Makes navigation bar transparent (but not the status bar).
3537     */
3538    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3539
3540    /**
3541     * @hide
3542     *
3543     * Makes status bar transparent (but not the navigation bar).
3544     */
3545    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3546
3547    /**
3548     * @hide
3549     *
3550     * Makes both status bar and navigation bar transparent.
3551     */
3552    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3553            | STATUS_BAR_TRANSPARENT;
3554
3555    /**
3556     * @hide
3557     */
3558    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3559
3560    /**
3561     * These are the system UI flags that can be cleared by events outside
3562     * of an application.  Currently this is just the ability to tap on the
3563     * screen while hiding the navigation bar to have it return.
3564     * @hide
3565     */
3566    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3567            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3568            | SYSTEM_UI_FLAG_FULLSCREEN;
3569
3570    /**
3571     * Flags that can impact the layout in relation to system UI.
3572     */
3573    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3574            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3575            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3576
3577    /** @hide */
3578    @IntDef(flag = true,
3579            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3580    @Retention(RetentionPolicy.SOURCE)
3581    public @interface FindViewFlags {}
3582
3583    /**
3584     * Find views that render the specified text.
3585     *
3586     * @see #findViewsWithText(ArrayList, CharSequence, int)
3587     */
3588    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3589
3590    /**
3591     * Find find views that contain the specified content description.
3592     *
3593     * @see #findViewsWithText(ArrayList, CharSequence, int)
3594     */
3595    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3596
3597    /**
3598     * Find views that contain {@link AccessibilityNodeProvider}. Such
3599     * a View is a root of virtual view hierarchy and may contain the searched
3600     * text. If this flag is set Views with providers are automatically
3601     * added and it is a responsibility of the client to call the APIs of
3602     * the provider to determine whether the virtual tree rooted at this View
3603     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3604     * representing the virtual views with this text.
3605     *
3606     * @see #findViewsWithText(ArrayList, CharSequence, int)
3607     *
3608     * @hide
3609     */
3610    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3611
3612    /**
3613     * The undefined cursor position.
3614     *
3615     * @hide
3616     */
3617    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3618
3619    /**
3620     * Indicates that the screen has changed state and is now off.
3621     *
3622     * @see #onScreenStateChanged(int)
3623     */
3624    public static final int SCREEN_STATE_OFF = 0x0;
3625
3626    /**
3627     * Indicates that the screen has changed state and is now on.
3628     *
3629     * @see #onScreenStateChanged(int)
3630     */
3631    public static final int SCREEN_STATE_ON = 0x1;
3632
3633    /**
3634     * Indicates no axis of view scrolling.
3635     */
3636    public static final int SCROLL_AXIS_NONE = 0;
3637
3638    /**
3639     * Indicates scrolling along the horizontal axis.
3640     */
3641    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3642
3643    /**
3644     * Indicates scrolling along the vertical axis.
3645     */
3646    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3647
3648    /**
3649     * Controls the over-scroll mode for this view.
3650     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3651     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3652     * and {@link #OVER_SCROLL_NEVER}.
3653     */
3654    private int mOverScrollMode;
3655
3656    /**
3657     * The parent this view is attached to.
3658     * {@hide}
3659     *
3660     * @see #getParent()
3661     */
3662    protected ViewParent mParent;
3663
3664    /**
3665     * {@hide}
3666     */
3667    AttachInfo mAttachInfo;
3668
3669    /**
3670     * {@hide}
3671     */
3672    @ViewDebug.ExportedProperty(flagMapping = {
3673        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3674                name = "FORCE_LAYOUT"),
3675        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3676                name = "LAYOUT_REQUIRED"),
3677        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3678            name = "DRAWING_CACHE_INVALID", outputIf = false),
3679        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3680        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3681        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3682        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3683    }, formatToHexString = true)
3684
3685    /* @hide */
3686    public int mPrivateFlags;
3687    int mPrivateFlags2;
3688    int mPrivateFlags3;
3689
3690    /**
3691     * This view's request for the visibility of the status bar.
3692     * @hide
3693     */
3694    @ViewDebug.ExportedProperty(flagMapping = {
3695        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3696                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3697                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3698        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3699                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3700                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3701        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3702                                equals = SYSTEM_UI_FLAG_VISIBLE,
3703                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3704    }, formatToHexString = true)
3705    int mSystemUiVisibility;
3706
3707    /**
3708     * Reference count for transient state.
3709     * @see #setHasTransientState(boolean)
3710     */
3711    int mTransientStateCount = 0;
3712
3713    /**
3714     * Count of how many windows this view has been attached to.
3715     */
3716    int mWindowAttachCount;
3717
3718    /**
3719     * The layout parameters associated with this view and used by the parent
3720     * {@link android.view.ViewGroup} to determine how this view should be
3721     * laid out.
3722     * {@hide}
3723     */
3724    protected ViewGroup.LayoutParams mLayoutParams;
3725
3726    /**
3727     * The view flags hold various views states.
3728     * {@hide}
3729     */
3730    @ViewDebug.ExportedProperty(formatToHexString = true)
3731    int mViewFlags;
3732
3733    static class TransformationInfo {
3734        /**
3735         * The transform matrix for the View. This transform is calculated internally
3736         * based on the translation, rotation, and scale properties.
3737         *
3738         * Do *not* use this variable directly; instead call getMatrix(), which will
3739         * load the value from the View's RenderNode.
3740         */
3741        private final Matrix mMatrix = new Matrix();
3742
3743        /**
3744         * The inverse transform matrix for the View. This transform is calculated
3745         * internally based on the translation, rotation, and scale properties.
3746         *
3747         * Do *not* use this variable directly; instead call getInverseMatrix(),
3748         * which will load the value from the View's RenderNode.
3749         */
3750        private Matrix mInverseMatrix;
3751
3752        /**
3753         * The opacity of the View. This is a value from 0 to 1, where 0 means
3754         * completely transparent and 1 means completely opaque.
3755         */
3756        @ViewDebug.ExportedProperty
3757        float mAlpha = 1f;
3758
3759        /**
3760         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3761         * property only used by transitions, which is composited with the other alpha
3762         * values to calculate the final visual alpha value.
3763         */
3764        float mTransitionAlpha = 1f;
3765    }
3766
3767    /** @hide */
3768    public TransformationInfo mTransformationInfo;
3769
3770    /**
3771     * Current clip bounds. to which all drawing of this view are constrained.
3772     */
3773    Rect mClipBounds = null;
3774
3775    private boolean mLastIsOpaque;
3776
3777    /**
3778     * The distance in pixels from the left edge of this view's parent
3779     * to the left edge of this view.
3780     * {@hide}
3781     */
3782    @ViewDebug.ExportedProperty(category = "layout")
3783    protected int mLeft;
3784    /**
3785     * The distance in pixels from the left edge of this view's parent
3786     * to the right edge of this view.
3787     * {@hide}
3788     */
3789    @ViewDebug.ExportedProperty(category = "layout")
3790    protected int mRight;
3791    /**
3792     * The distance in pixels from the top edge of this view's parent
3793     * to the top edge of this view.
3794     * {@hide}
3795     */
3796    @ViewDebug.ExportedProperty(category = "layout")
3797    protected int mTop;
3798    /**
3799     * The distance in pixels from the top edge of this view's parent
3800     * to the bottom edge of this view.
3801     * {@hide}
3802     */
3803    @ViewDebug.ExportedProperty(category = "layout")
3804    protected int mBottom;
3805
3806    /**
3807     * The offset, in pixels, by which the content of this view is scrolled
3808     * horizontally.
3809     * {@hide}
3810     */
3811    @ViewDebug.ExportedProperty(category = "scrolling")
3812    protected int mScrollX;
3813    /**
3814     * The offset, in pixels, by which the content of this view is scrolled
3815     * vertically.
3816     * {@hide}
3817     */
3818    @ViewDebug.ExportedProperty(category = "scrolling")
3819    protected int mScrollY;
3820
3821    /**
3822     * The left padding in pixels, that is the distance in pixels between the
3823     * left edge of this view and the left edge of its content.
3824     * {@hide}
3825     */
3826    @ViewDebug.ExportedProperty(category = "padding")
3827    protected int mPaddingLeft = 0;
3828    /**
3829     * The right padding in pixels, that is the distance in pixels between the
3830     * right edge of this view and the right edge of its content.
3831     * {@hide}
3832     */
3833    @ViewDebug.ExportedProperty(category = "padding")
3834    protected int mPaddingRight = 0;
3835    /**
3836     * The top padding in pixels, that is the distance in pixels between the
3837     * top edge of this view and the top edge of its content.
3838     * {@hide}
3839     */
3840    @ViewDebug.ExportedProperty(category = "padding")
3841    protected int mPaddingTop;
3842    /**
3843     * The bottom padding in pixels, that is the distance in pixels between the
3844     * bottom edge of this view and the bottom edge of its content.
3845     * {@hide}
3846     */
3847    @ViewDebug.ExportedProperty(category = "padding")
3848    protected int mPaddingBottom;
3849
3850    /**
3851     * The layout insets in pixels, that is the distance in pixels between the
3852     * visible edges of this view its bounds.
3853     */
3854    private Insets mLayoutInsets;
3855
3856    /**
3857     * Briefly describes the view and is primarily used for accessibility support.
3858     */
3859    private CharSequence mContentDescription;
3860
3861    /**
3862     * Specifies the id of a view for which this view serves as a label for
3863     * accessibility purposes.
3864     */
3865    private int mLabelForId = View.NO_ID;
3866
3867    /**
3868     * Predicate for matching labeled view id with its label for
3869     * accessibility purposes.
3870     */
3871    private MatchLabelForPredicate mMatchLabelForPredicate;
3872
3873    /**
3874     * Specifies a view before which this one is visited in accessibility traversal.
3875     */
3876    private int mAccessibilityTraversalBeforeId = NO_ID;
3877
3878    /**
3879     * Specifies a view after which this one is visited in accessibility traversal.
3880     */
3881    private int mAccessibilityTraversalAfterId = NO_ID;
3882
3883    /**
3884     * Predicate for matching a view by its id.
3885     */
3886    private MatchIdPredicate mMatchIdPredicate;
3887
3888    /**
3889     * Cache the paddingRight set by the user to append to the scrollbar's size.
3890     *
3891     * @hide
3892     */
3893    @ViewDebug.ExportedProperty(category = "padding")
3894    protected int mUserPaddingRight;
3895
3896    /**
3897     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3898     *
3899     * @hide
3900     */
3901    @ViewDebug.ExportedProperty(category = "padding")
3902    protected int mUserPaddingBottom;
3903
3904    /**
3905     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3906     *
3907     * @hide
3908     */
3909    @ViewDebug.ExportedProperty(category = "padding")
3910    protected int mUserPaddingLeft;
3911
3912    /**
3913     * Cache the paddingStart set by the user to append to the scrollbar's size.
3914     *
3915     */
3916    @ViewDebug.ExportedProperty(category = "padding")
3917    int mUserPaddingStart;
3918
3919    /**
3920     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3921     *
3922     */
3923    @ViewDebug.ExportedProperty(category = "padding")
3924    int mUserPaddingEnd;
3925
3926    /**
3927     * Cache initial left padding.
3928     *
3929     * @hide
3930     */
3931    int mUserPaddingLeftInitial;
3932
3933    /**
3934     * Cache initial right padding.
3935     *
3936     * @hide
3937     */
3938    int mUserPaddingRightInitial;
3939
3940    /**
3941     * Default undefined padding
3942     */
3943    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3944
3945    /**
3946     * Cache if a left padding has been defined
3947     */
3948    private boolean mLeftPaddingDefined = false;
3949
3950    /**
3951     * Cache if a right padding has been defined
3952     */
3953    private boolean mRightPaddingDefined = false;
3954
3955    /**
3956     * @hide
3957     */
3958    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3959    /**
3960     * @hide
3961     */
3962    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3963
3964    private LongSparseLongArray mMeasureCache;
3965
3966    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3967    private Drawable mBackground;
3968    private TintInfo mBackgroundTint;
3969
3970    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3971    private ForegroundInfo mForegroundInfo;
3972
3973    private Drawable mScrollIndicatorDrawable;
3974
3975    /**
3976     * RenderNode used for backgrounds.
3977     * <p>
3978     * When non-null and valid, this is expected to contain an up-to-date copy
3979     * of the background drawable. It is cleared on temporary detach, and reset
3980     * on cleanup.
3981     */
3982    private RenderNode mBackgroundRenderNode;
3983
3984    private int mBackgroundResource;
3985    private boolean mBackgroundSizeChanged;
3986
3987    /** The default focus highlight.
3988     * @see #mDefaultFocusHighlightEnabled
3989     * @see Drawable#hasFocusStateSpecified()
3990     */
3991    private Drawable mDefaultFocusHighlight;
3992    private Drawable mDefaultFocusHighlightCache;
3993    private boolean mDefaultFocusHighlightSizeChanged;
3994    /**
3995     * True if the default focus highlight is needed on the target device.
3996     */
3997    private static boolean sUseDefaultFocusHighlight;
3998
3999    private String mTransitionName;
4000
4001    static class TintInfo {
4002        ColorStateList mTintList;
4003        PorterDuff.Mode mTintMode;
4004        boolean mHasTintMode;
4005        boolean mHasTintList;
4006    }
4007
4008    private static class ForegroundInfo {
4009        private Drawable mDrawable;
4010        private TintInfo mTintInfo;
4011        private int mGravity = Gravity.FILL;
4012        private boolean mInsidePadding = true;
4013        private boolean mBoundsChanged = true;
4014        private final Rect mSelfBounds = new Rect();
4015        private final Rect mOverlayBounds = new Rect();
4016    }
4017
4018    static class ListenerInfo {
4019        /**
4020         * Listener used to dispatch focus change events.
4021         * This field should be made private, so it is hidden from the SDK.
4022         * {@hide}
4023         */
4024        protected OnFocusChangeListener mOnFocusChangeListener;
4025
4026        /**
4027         * Listeners for layout change events.
4028         */
4029        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4030
4031        protected OnScrollChangeListener mOnScrollChangeListener;
4032
4033        /**
4034         * Listeners for attach events.
4035         */
4036        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4037
4038        /**
4039         * Listener used to dispatch click events.
4040         * This field should be made private, so it is hidden from the SDK.
4041         * {@hide}
4042         */
4043        public OnClickListener mOnClickListener;
4044
4045        /**
4046         * Listener used to dispatch long click events.
4047         * This field should be made private, so it is hidden from the SDK.
4048         * {@hide}
4049         */
4050        protected OnLongClickListener mOnLongClickListener;
4051
4052        /**
4053         * Listener used to dispatch context click events. This field should be made private, so it
4054         * is hidden from the SDK.
4055         * {@hide}
4056         */
4057        protected OnContextClickListener mOnContextClickListener;
4058
4059        /**
4060         * Listener used to build the context menu.
4061         * This field should be made private, so it is hidden from the SDK.
4062         * {@hide}
4063         */
4064        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4065
4066        private OnKeyListener mOnKeyListener;
4067
4068        private OnTouchListener mOnTouchListener;
4069
4070        private OnHoverListener mOnHoverListener;
4071
4072        private OnGenericMotionListener mOnGenericMotionListener;
4073
4074        private OnDragListener mOnDragListener;
4075
4076        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4077
4078        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4079
4080        OnCapturedPointerListener mOnCapturedPointerListener;
4081    }
4082
4083    ListenerInfo mListenerInfo;
4084
4085    private static class TooltipInfo {
4086        /**
4087         * Text to be displayed in a tooltip popup.
4088         */
4089        @Nullable
4090        CharSequence mTooltipText;
4091
4092        /**
4093         * View-relative position of the tooltip anchor point.
4094         */
4095        int mAnchorX;
4096        int mAnchorY;
4097
4098        /**
4099         * The tooltip popup.
4100         */
4101        @Nullable
4102        TooltipPopup mTooltipPopup;
4103
4104        /**
4105         * Set to true if the tooltip was shown as a result of a long click.
4106         */
4107        boolean mTooltipFromLongClick;
4108
4109        /**
4110         * Keep these Runnables so that they can be used to reschedule.
4111         */
4112        Runnable mShowTooltipRunnable;
4113        Runnable mHideTooltipRunnable;
4114    }
4115
4116    TooltipInfo mTooltipInfo;
4117
4118    // Temporary values used to hold (x,y) coordinates when delegating from the
4119    // two-arg performLongClick() method to the legacy no-arg version.
4120    private float mLongClickX = Float.NaN;
4121    private float mLongClickY = Float.NaN;
4122
4123    /**
4124     * The application environment this view lives in.
4125     * This field should be made private, so it is hidden from the SDK.
4126     * {@hide}
4127     */
4128    @ViewDebug.ExportedProperty(deepExport = true)
4129    protected Context mContext;
4130
4131    private final Resources mResources;
4132
4133    private ScrollabilityCache mScrollCache;
4134
4135    private int[] mDrawableState = null;
4136
4137    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4138
4139    /**
4140     * Animator that automatically runs based on state changes.
4141     */
4142    private StateListAnimator mStateListAnimator;
4143
4144    /**
4145     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4146     * the user may specify which view to go to next.
4147     */
4148    private int mNextFocusLeftId = View.NO_ID;
4149
4150    /**
4151     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4152     * the user may specify which view to go to next.
4153     */
4154    private int mNextFocusRightId = View.NO_ID;
4155
4156    /**
4157     * When this view has focus and the next focus is {@link #FOCUS_UP},
4158     * the user may specify which view to go to next.
4159     */
4160    private int mNextFocusUpId = View.NO_ID;
4161
4162    /**
4163     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4164     * the user may specify which view to go to next.
4165     */
4166    private int mNextFocusDownId = View.NO_ID;
4167
4168    /**
4169     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4170     * the user may specify which view to go to next.
4171     */
4172    int mNextFocusForwardId = View.NO_ID;
4173
4174    /**
4175     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4176     *
4177     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4178     */
4179    int mNextClusterForwardId = View.NO_ID;
4180
4181    /**
4182     * Whether this View should use a default focus highlight when it gets focused but doesn't
4183     * have {@link android.R.attr#state_focused} defined in its background.
4184     */
4185    boolean mDefaultFocusHighlightEnabled = true;
4186
4187    private CheckForLongPress mPendingCheckForLongPress;
4188    private CheckForTap mPendingCheckForTap = null;
4189    private PerformClick mPerformClick;
4190    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4191
4192    private UnsetPressedState mUnsetPressedState;
4193
4194    /**
4195     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4196     * up event while a long press is invoked as soon as the long press duration is reached, so
4197     * a long press could be performed before the tap is checked, in which case the tap's action
4198     * should not be invoked.
4199     */
4200    private boolean mHasPerformedLongPress;
4201
4202    /**
4203     * Whether a context click button is currently pressed down. This is true when the stylus is
4204     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4205     * pressed. This is false once the button is released or if the stylus has been lifted.
4206     */
4207    private boolean mInContextButtonPress;
4208
4209    /**
4210     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4211     * true after a stylus button press has occured, when the next up event should not be recognized
4212     * as a tap.
4213     */
4214    private boolean mIgnoreNextUpEvent;
4215
4216    /**
4217     * The minimum height of the view. We'll try our best to have the height
4218     * of this view to at least this amount.
4219     */
4220    @ViewDebug.ExportedProperty(category = "measurement")
4221    private int mMinHeight;
4222
4223    /**
4224     * The minimum width of the view. We'll try our best to have the width
4225     * of this view to at least this amount.
4226     */
4227    @ViewDebug.ExportedProperty(category = "measurement")
4228    private int mMinWidth;
4229
4230    /**
4231     * The delegate to handle touch events that are physically in this view
4232     * but should be handled by another view.
4233     */
4234    private TouchDelegate mTouchDelegate = null;
4235
4236    /**
4237     * Solid color to use as a background when creating the drawing cache. Enables
4238     * the cache to use 16 bit bitmaps instead of 32 bit.
4239     */
4240    private int mDrawingCacheBackgroundColor = 0;
4241
4242    /**
4243     * Special tree observer used when mAttachInfo is null.
4244     */
4245    private ViewTreeObserver mFloatingTreeObserver;
4246
4247    /**
4248     * Cache the touch slop from the context that created the view.
4249     */
4250    private int mTouchSlop;
4251
4252    /**
4253     * Object that handles automatic animation of view properties.
4254     */
4255    private ViewPropertyAnimator mAnimator = null;
4256
4257    /**
4258     * List of registered FrameMetricsObservers.
4259     */
4260    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4261
4262    /**
4263     * Flag indicating that a drag can cross window boundaries.  When
4264     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4265     * with this flag set, all visible applications with targetSdkVersion >=
4266     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4267     * in the drag operation and receive the dragged content.
4268     *
4269     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4270     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4271     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4272     */
4273    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4274
4275    /**
4276     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4277     * request read access to the content URI(s) contained in the {@link ClipData} object.
4278     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4279     */
4280    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4281
4282    /**
4283     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4284     * request write access to the content URI(s) contained in the {@link ClipData} object.
4285     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4286     */
4287    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4288
4289    /**
4290     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4291     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4292     * reboots until explicitly revoked with
4293     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4294     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4295     */
4296    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4297            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4298
4299    /**
4300     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4301     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4302     * match against the original granted URI.
4303     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4304     */
4305    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4306            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4307
4308    /**
4309     * Flag indicating that the drag shadow will be opaque.  When
4310     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4311     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4312     */
4313    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4314
4315    /**
4316     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4317     */
4318    private float mVerticalScrollFactor;
4319
4320    /**
4321     * Position of the vertical scroll bar.
4322     */
4323    private int mVerticalScrollbarPosition;
4324
4325    /**
4326     * Position the scroll bar at the default position as determined by the system.
4327     */
4328    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4329
4330    /**
4331     * Position the scroll bar along the left edge.
4332     */
4333    public static final int SCROLLBAR_POSITION_LEFT = 1;
4334
4335    /**
4336     * Position the scroll bar along the right edge.
4337     */
4338    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4339
4340    /**
4341     * Indicates that the view does not have a layer.
4342     *
4343     * @see #getLayerType()
4344     * @see #setLayerType(int, android.graphics.Paint)
4345     * @see #LAYER_TYPE_SOFTWARE
4346     * @see #LAYER_TYPE_HARDWARE
4347     */
4348    public static final int LAYER_TYPE_NONE = 0;
4349
4350    /**
4351     * <p>Indicates that the view has a software layer. A software layer is backed
4352     * by a bitmap and causes the view to be rendered using Android's software
4353     * rendering pipeline, even if hardware acceleration is enabled.</p>
4354     *
4355     * <p>Software layers have various usages:</p>
4356     * <p>When the application is not using hardware acceleration, a software layer
4357     * is useful to apply a specific color filter and/or blending mode and/or
4358     * translucency to a view and all its children.</p>
4359     * <p>When the application is using hardware acceleration, a software layer
4360     * is useful to render drawing primitives not supported by the hardware
4361     * accelerated pipeline. It can also be used to cache a complex view tree
4362     * into a texture and reduce the complexity of drawing operations. For instance,
4363     * when animating a complex view tree with a translation, a software layer can
4364     * be used to render the view tree only once.</p>
4365     * <p>Software layers should be avoided when the affected view tree updates
4366     * often. Every update will require to re-render the software layer, which can
4367     * potentially be slow (particularly when hardware acceleration is turned on
4368     * since the layer will have to be uploaded into a hardware texture after every
4369     * update.)</p>
4370     *
4371     * @see #getLayerType()
4372     * @see #setLayerType(int, android.graphics.Paint)
4373     * @see #LAYER_TYPE_NONE
4374     * @see #LAYER_TYPE_HARDWARE
4375     */
4376    public static final int LAYER_TYPE_SOFTWARE = 1;
4377
4378    /**
4379     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4380     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4381     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4382     * rendering pipeline, but only if hardware acceleration is turned on for the
4383     * view hierarchy. When hardware acceleration is turned off, hardware layers
4384     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4385     *
4386     * <p>A hardware layer is useful to apply a specific color filter and/or
4387     * blending mode and/or translucency to a view and all its children.</p>
4388     * <p>A hardware layer can be used to cache a complex view tree into a
4389     * texture and reduce the complexity of drawing operations. For instance,
4390     * when animating a complex view tree with a translation, a hardware layer can
4391     * be used to render the view tree only once.</p>
4392     * <p>A hardware layer can also be used to increase the rendering quality when
4393     * rotation transformations are applied on a view. It can also be used to
4394     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4395     *
4396     * @see #getLayerType()
4397     * @see #setLayerType(int, android.graphics.Paint)
4398     * @see #LAYER_TYPE_NONE
4399     * @see #LAYER_TYPE_SOFTWARE
4400     */
4401    public static final int LAYER_TYPE_HARDWARE = 2;
4402
4403    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4404            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4405            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4406            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4407    })
4408    int mLayerType = LAYER_TYPE_NONE;
4409    Paint mLayerPaint;
4410
4411    /**
4412     * Set to true when drawing cache is enabled and cannot be created.
4413     *
4414     * @hide
4415     */
4416    public boolean mCachingFailed;
4417    private Bitmap mDrawingCache;
4418    private Bitmap mUnscaledDrawingCache;
4419
4420    /**
4421     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4422     * <p>
4423     * When non-null and valid, this is expected to contain an up-to-date copy
4424     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4425     * cleanup.
4426     */
4427    final RenderNode mRenderNode;
4428
4429    /**
4430     * Set to true when the view is sending hover accessibility events because it
4431     * is the innermost hovered view.
4432     */
4433    private boolean mSendingHoverAccessibilityEvents;
4434
4435    /**
4436     * Delegate for injecting accessibility functionality.
4437     */
4438    AccessibilityDelegate mAccessibilityDelegate;
4439
4440    /**
4441     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4442     * and add/remove objects to/from the overlay directly through the Overlay methods.
4443     */
4444    ViewOverlay mOverlay;
4445
4446    /**
4447     * The currently active parent view for receiving delegated nested scrolling events.
4448     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4449     * by {@link #stopNestedScroll()} at the same point where we clear
4450     * requestDisallowInterceptTouchEvent.
4451     */
4452    private ViewParent mNestedScrollingParent;
4453
4454    /**
4455     * Consistency verifier for debugging purposes.
4456     * @hide
4457     */
4458    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4459            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4460                    new InputEventConsistencyVerifier(this, 0) : null;
4461
4462    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4463
4464    private int[] mTempNestedScrollConsumed;
4465
4466    /**
4467     * An overlay is going to draw this View instead of being drawn as part of this
4468     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4469     * when this view is invalidated.
4470     */
4471    GhostView mGhostView;
4472
4473    /**
4474     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4475     * @hide
4476     */
4477    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4478    public String[] mAttributes;
4479
4480    /**
4481     * Maps a Resource id to its name.
4482     */
4483    private static SparseArray<String> mAttributeMap;
4484
4485    /**
4486     * Queue of pending runnables. Used to postpone calls to post() until this
4487     * view is attached and has a handler.
4488     */
4489    private HandlerActionQueue mRunQueue;
4490
4491    /**
4492     * The pointer icon when the mouse hovers on this view. The default is null.
4493     */
4494    private PointerIcon mPointerIcon;
4495
4496    /**
4497     * @hide
4498     */
4499    String mStartActivityRequestWho;
4500
4501    @Nullable
4502    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4503
4504    /** Used to delay visibility updates sent to the autofill manager */
4505    private Handler mVisibilityChangeForAutofillHandler;
4506
4507    /**
4508     * Simple constructor to use when creating a view from code.
4509     *
4510     * @param context The Context the view is running in, through which it can
4511     *        access the current theme, resources, etc.
4512     */
4513    public View(Context context) {
4514        mContext = context;
4515        mResources = context != null ? context.getResources() : null;
4516        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4517        // Set some flags defaults
4518        mPrivateFlags2 =
4519                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4520                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4521                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4522                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4523                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4524                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4525        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4526        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4527        mUserPaddingStart = UNDEFINED_PADDING;
4528        mUserPaddingEnd = UNDEFINED_PADDING;
4529        mRenderNode = RenderNode.create(getClass().getName(), this);
4530
4531        if (!sCompatibilityDone && context != null) {
4532            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4533
4534            // Older apps may need this compatibility hack for measurement.
4535            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4536
4537            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4538            // of whether a layout was requested on that View.
4539            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4540
4541            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4542            Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4543
4544            // In M and newer, our widgets can pass a "hint" value in the size
4545            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4546            // know what the expected parent size is going to be, so e.g. list items can size
4547            // themselves at 1/3 the size of their container. It breaks older apps though,
4548            // specifically apps that use some popular open source libraries.
4549            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4550
4551            // Old versions of the platform would give different results from
4552            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4553            // modes, so we always need to run an additional EXACTLY pass.
4554            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4555
4556            // Prior to N, layout params could change without requiring a
4557            // subsequent call to setLayoutParams() and they would usually
4558            // work. Partial layout breaks this assumption.
4559            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4560
4561            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4562            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4563            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4564
4565            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4566            // in apps so we target check it to avoid breaking existing apps.
4567            sPreserveMarginParamsInLayoutParamConversion =
4568                    targetSdkVersion >= Build.VERSION_CODES.N;
4569
4570            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4571
4572            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4573
4574            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4575
4576            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4577                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4578
4579            sCompatibilityDone = true;
4580        }
4581    }
4582
4583    /**
4584     * Constructor that is called when inflating a view from XML. This is called
4585     * when a view is being constructed from an XML file, supplying attributes
4586     * that were specified in the XML file. This version uses a default style of
4587     * 0, so the only attribute values applied are those in the Context's Theme
4588     * and the given AttributeSet.
4589     *
4590     * <p>
4591     * The method onFinishInflate() will be called after all children have been
4592     * added.
4593     *
4594     * @param context The Context the view is running in, through which it can
4595     *        access the current theme, resources, etc.
4596     * @param attrs The attributes of the XML tag that is inflating the view.
4597     * @see #View(Context, AttributeSet, int)
4598     */
4599    public View(Context context, @Nullable AttributeSet attrs) {
4600        this(context, attrs, 0);
4601    }
4602
4603    /**
4604     * Perform inflation from XML and apply a class-specific base style from a
4605     * theme attribute. This constructor of View allows subclasses to use their
4606     * own base style when they are inflating. For example, a Button class's
4607     * constructor would call this version of the super class constructor and
4608     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4609     * allows the theme's button style to modify all of the base view attributes
4610     * (in particular its background) as well as the Button class's attributes.
4611     *
4612     * @param context The Context the view is running in, through which it can
4613     *        access the current theme, resources, etc.
4614     * @param attrs The attributes of the XML tag that is inflating the view.
4615     * @param defStyleAttr An attribute in the current theme that contains a
4616     *        reference to a style resource that supplies default values for
4617     *        the view. Can be 0 to not look for defaults.
4618     * @see #View(Context, AttributeSet)
4619     */
4620    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4621        this(context, attrs, defStyleAttr, 0);
4622    }
4623
4624    /**
4625     * Perform inflation from XML and apply a class-specific base style from a
4626     * theme attribute or style resource. This constructor of View allows
4627     * subclasses to use their own base style when they are inflating.
4628     * <p>
4629     * When determining the final value of a particular attribute, there are
4630     * four inputs that come into play:
4631     * <ol>
4632     * <li>Any attribute values in the given AttributeSet.
4633     * <li>The style resource specified in the AttributeSet (named "style").
4634     * <li>The default style specified by <var>defStyleAttr</var>.
4635     * <li>The default style specified by <var>defStyleRes</var>.
4636     * <li>The base values in this theme.
4637     * </ol>
4638     * <p>
4639     * Each of these inputs is considered in-order, with the first listed taking
4640     * precedence over the following ones. In other words, if in the
4641     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4642     * , then the button's text will <em>always</em> be black, regardless of
4643     * what is specified in any of the styles.
4644     *
4645     * @param context The Context the view is running in, through which it can
4646     *        access the current theme, resources, etc.
4647     * @param attrs The attributes of the XML tag that is inflating the view.
4648     * @param defStyleAttr An attribute in the current theme that contains a
4649     *        reference to a style resource that supplies default values for
4650     *        the view. Can be 0 to not look for defaults.
4651     * @param defStyleRes A resource identifier of a style resource that
4652     *        supplies default values for the view, used only if
4653     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4654     *        to not look for defaults.
4655     * @see #View(Context, AttributeSet, int)
4656     */
4657    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4658        this(context);
4659
4660        final TypedArray a = context.obtainStyledAttributes(
4661                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4662
4663        if (mDebugViewAttributes) {
4664            saveAttributeData(attrs, a);
4665        }
4666
4667        Drawable background = null;
4668
4669        int leftPadding = -1;
4670        int topPadding = -1;
4671        int rightPadding = -1;
4672        int bottomPadding = -1;
4673        int startPadding = UNDEFINED_PADDING;
4674        int endPadding = UNDEFINED_PADDING;
4675
4676        int padding = -1;
4677        int paddingHorizontal = -1;
4678        int paddingVertical = -1;
4679
4680        int viewFlagValues = 0;
4681        int viewFlagMasks = 0;
4682
4683        boolean setScrollContainer = false;
4684
4685        int x = 0;
4686        int y = 0;
4687
4688        float tx = 0;
4689        float ty = 0;
4690        float tz = 0;
4691        float elevation = 0;
4692        float rotation = 0;
4693        float rotationX = 0;
4694        float rotationY = 0;
4695        float sx = 1f;
4696        float sy = 1f;
4697        boolean transformSet = false;
4698
4699        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4700        int overScrollMode = mOverScrollMode;
4701        boolean initializeScrollbars = false;
4702        boolean initializeScrollIndicators = false;
4703
4704        boolean startPaddingDefined = false;
4705        boolean endPaddingDefined = false;
4706        boolean leftPaddingDefined = false;
4707        boolean rightPaddingDefined = false;
4708
4709        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4710
4711        // Set default values.
4712        viewFlagValues |= FOCUSABLE_AUTO;
4713        viewFlagMasks |= FOCUSABLE_AUTO;
4714
4715        final int N = a.getIndexCount();
4716        for (int i = 0; i < N; i++) {
4717            int attr = a.getIndex(i);
4718            switch (attr) {
4719                case com.android.internal.R.styleable.View_background:
4720                    background = a.getDrawable(attr);
4721                    break;
4722                case com.android.internal.R.styleable.View_padding:
4723                    padding = a.getDimensionPixelSize(attr, -1);
4724                    mUserPaddingLeftInitial = padding;
4725                    mUserPaddingRightInitial = padding;
4726                    leftPaddingDefined = true;
4727                    rightPaddingDefined = true;
4728                    break;
4729                case com.android.internal.R.styleable.View_paddingHorizontal:
4730                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4731                    mUserPaddingLeftInitial = paddingHorizontal;
4732                    mUserPaddingRightInitial = paddingHorizontal;
4733                    leftPaddingDefined = true;
4734                    rightPaddingDefined = true;
4735                    break;
4736                case com.android.internal.R.styleable.View_paddingVertical:
4737                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4738                    break;
4739                 case com.android.internal.R.styleable.View_paddingLeft:
4740                    leftPadding = a.getDimensionPixelSize(attr, -1);
4741                    mUserPaddingLeftInitial = leftPadding;
4742                    leftPaddingDefined = true;
4743                    break;
4744                case com.android.internal.R.styleable.View_paddingTop:
4745                    topPadding = a.getDimensionPixelSize(attr, -1);
4746                    break;
4747                case com.android.internal.R.styleable.View_paddingRight:
4748                    rightPadding = a.getDimensionPixelSize(attr, -1);
4749                    mUserPaddingRightInitial = rightPadding;
4750                    rightPaddingDefined = true;
4751                    break;
4752                case com.android.internal.R.styleable.View_paddingBottom:
4753                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4754                    break;
4755                case com.android.internal.R.styleable.View_paddingStart:
4756                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4757                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4758                    break;
4759                case com.android.internal.R.styleable.View_paddingEnd:
4760                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4761                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4762                    break;
4763                case com.android.internal.R.styleable.View_scrollX:
4764                    x = a.getDimensionPixelOffset(attr, 0);
4765                    break;
4766                case com.android.internal.R.styleable.View_scrollY:
4767                    y = a.getDimensionPixelOffset(attr, 0);
4768                    break;
4769                case com.android.internal.R.styleable.View_alpha:
4770                    setAlpha(a.getFloat(attr, 1f));
4771                    break;
4772                case com.android.internal.R.styleable.View_transformPivotX:
4773                    setPivotX(a.getDimension(attr, 0));
4774                    break;
4775                case com.android.internal.R.styleable.View_transformPivotY:
4776                    setPivotY(a.getDimension(attr, 0));
4777                    break;
4778                case com.android.internal.R.styleable.View_translationX:
4779                    tx = a.getDimension(attr, 0);
4780                    transformSet = true;
4781                    break;
4782                case com.android.internal.R.styleable.View_translationY:
4783                    ty = a.getDimension(attr, 0);
4784                    transformSet = true;
4785                    break;
4786                case com.android.internal.R.styleable.View_translationZ:
4787                    tz = a.getDimension(attr, 0);
4788                    transformSet = true;
4789                    break;
4790                case com.android.internal.R.styleable.View_elevation:
4791                    elevation = a.getDimension(attr, 0);
4792                    transformSet = true;
4793                    break;
4794                case com.android.internal.R.styleable.View_rotation:
4795                    rotation = a.getFloat(attr, 0);
4796                    transformSet = true;
4797                    break;
4798                case com.android.internal.R.styleable.View_rotationX:
4799                    rotationX = a.getFloat(attr, 0);
4800                    transformSet = true;
4801                    break;
4802                case com.android.internal.R.styleable.View_rotationY:
4803                    rotationY = a.getFloat(attr, 0);
4804                    transformSet = true;
4805                    break;
4806                case com.android.internal.R.styleable.View_scaleX:
4807                    sx = a.getFloat(attr, 1f);
4808                    transformSet = true;
4809                    break;
4810                case com.android.internal.R.styleable.View_scaleY:
4811                    sy = a.getFloat(attr, 1f);
4812                    transformSet = true;
4813                    break;
4814                case com.android.internal.R.styleable.View_id:
4815                    mID = a.getResourceId(attr, NO_ID);
4816                    break;
4817                case com.android.internal.R.styleable.View_tag:
4818                    mTag = a.getText(attr);
4819                    break;
4820                case com.android.internal.R.styleable.View_fitsSystemWindows:
4821                    if (a.getBoolean(attr, false)) {
4822                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4823                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4824                    }
4825                    break;
4826                case com.android.internal.R.styleable.View_focusable:
4827                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4828                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4829                        viewFlagMasks |= FOCUSABLE_MASK;
4830                    }
4831                    break;
4832                case com.android.internal.R.styleable.View_focusableInTouchMode:
4833                    if (a.getBoolean(attr, false)) {
4834                        // unset auto focus since focusableInTouchMode implies explicit focusable
4835                        viewFlagValues &= ~FOCUSABLE_AUTO;
4836                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4837                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4838                    }
4839                    break;
4840                case com.android.internal.R.styleable.View_clickable:
4841                    if (a.getBoolean(attr, false)) {
4842                        viewFlagValues |= CLICKABLE;
4843                        viewFlagMasks |= CLICKABLE;
4844                    }
4845                    break;
4846                case com.android.internal.R.styleable.View_longClickable:
4847                    if (a.getBoolean(attr, false)) {
4848                        viewFlagValues |= LONG_CLICKABLE;
4849                        viewFlagMasks |= LONG_CLICKABLE;
4850                    }
4851                    break;
4852                case com.android.internal.R.styleable.View_contextClickable:
4853                    if (a.getBoolean(attr, false)) {
4854                        viewFlagValues |= CONTEXT_CLICKABLE;
4855                        viewFlagMasks |= CONTEXT_CLICKABLE;
4856                    }
4857                    break;
4858                case com.android.internal.R.styleable.View_saveEnabled:
4859                    if (!a.getBoolean(attr, true)) {
4860                        viewFlagValues |= SAVE_DISABLED;
4861                        viewFlagMasks |= SAVE_DISABLED_MASK;
4862                    }
4863                    break;
4864                case com.android.internal.R.styleable.View_duplicateParentState:
4865                    if (a.getBoolean(attr, false)) {
4866                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4867                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4868                    }
4869                    break;
4870                case com.android.internal.R.styleable.View_visibility:
4871                    final int visibility = a.getInt(attr, 0);
4872                    if (visibility != 0) {
4873                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4874                        viewFlagMasks |= VISIBILITY_MASK;
4875                    }
4876                    break;
4877                case com.android.internal.R.styleable.View_layoutDirection:
4878                    // Clear any layout direction flags (included resolved bits) already set
4879                    mPrivateFlags2 &=
4880                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4881                    // Set the layout direction flags depending on the value of the attribute
4882                    final int layoutDirection = a.getInt(attr, -1);
4883                    final int value = (layoutDirection != -1) ?
4884                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4885                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4886                    break;
4887                case com.android.internal.R.styleable.View_drawingCacheQuality:
4888                    final int cacheQuality = a.getInt(attr, 0);
4889                    if (cacheQuality != 0) {
4890                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4891                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4892                    }
4893                    break;
4894                case com.android.internal.R.styleable.View_contentDescription:
4895                    setContentDescription(a.getString(attr));
4896                    break;
4897                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4898                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4899                    break;
4900                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4901                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4902                    break;
4903                case com.android.internal.R.styleable.View_labelFor:
4904                    setLabelFor(a.getResourceId(attr, NO_ID));
4905                    break;
4906                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4907                    if (!a.getBoolean(attr, true)) {
4908                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4909                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4910                    }
4911                    break;
4912                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4913                    if (!a.getBoolean(attr, true)) {
4914                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4915                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4916                    }
4917                    break;
4918                case R.styleable.View_scrollbars:
4919                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4920                    if (scrollbars != SCROLLBARS_NONE) {
4921                        viewFlagValues |= scrollbars;
4922                        viewFlagMasks |= SCROLLBARS_MASK;
4923                        initializeScrollbars = true;
4924                    }
4925                    break;
4926                //noinspection deprecation
4927                case R.styleable.View_fadingEdge:
4928                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4929                        // Ignore the attribute starting with ICS
4930                        break;
4931                    }
4932                    // With builds < ICS, fall through and apply fading edges
4933                case R.styleable.View_requiresFadingEdge:
4934                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4935                    if (fadingEdge != FADING_EDGE_NONE) {
4936                        viewFlagValues |= fadingEdge;
4937                        viewFlagMasks |= FADING_EDGE_MASK;
4938                        initializeFadingEdgeInternal(a);
4939                    }
4940                    break;
4941                case R.styleable.View_scrollbarStyle:
4942                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4943                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4944                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4945                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4946                    }
4947                    break;
4948                case R.styleable.View_isScrollContainer:
4949                    setScrollContainer = true;
4950                    if (a.getBoolean(attr, false)) {
4951                        setScrollContainer(true);
4952                    }
4953                    break;
4954                case com.android.internal.R.styleable.View_keepScreenOn:
4955                    if (a.getBoolean(attr, false)) {
4956                        viewFlagValues |= KEEP_SCREEN_ON;
4957                        viewFlagMasks |= KEEP_SCREEN_ON;
4958                    }
4959                    break;
4960                case R.styleable.View_filterTouchesWhenObscured:
4961                    if (a.getBoolean(attr, false)) {
4962                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4963                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4964                    }
4965                    break;
4966                case R.styleable.View_nextFocusLeft:
4967                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4968                    break;
4969                case R.styleable.View_nextFocusRight:
4970                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4971                    break;
4972                case R.styleable.View_nextFocusUp:
4973                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4974                    break;
4975                case R.styleable.View_nextFocusDown:
4976                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4977                    break;
4978                case R.styleable.View_nextFocusForward:
4979                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4980                    break;
4981                case R.styleable.View_nextClusterForward:
4982                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4983                    break;
4984                case R.styleable.View_minWidth:
4985                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4986                    break;
4987                case R.styleable.View_minHeight:
4988                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4989                    break;
4990                case R.styleable.View_onClick:
4991                    if (context.isRestricted()) {
4992                        throw new IllegalStateException("The android:onClick attribute cannot "
4993                                + "be used within a restricted context");
4994                    }
4995
4996                    final String handlerName = a.getString(attr);
4997                    if (handlerName != null) {
4998                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4999                    }
5000                    break;
5001                case R.styleable.View_overScrollMode:
5002                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5003                    break;
5004                case R.styleable.View_verticalScrollbarPosition:
5005                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5006                    break;
5007                case R.styleable.View_layerType:
5008                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5009                    break;
5010                case R.styleable.View_textDirection:
5011                    // Clear any text direction flag already set
5012                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5013                    // Set the text direction flags depending on the value of the attribute
5014                    final int textDirection = a.getInt(attr, -1);
5015                    if (textDirection != -1) {
5016                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5017                    }
5018                    break;
5019                case R.styleable.View_textAlignment:
5020                    // Clear any text alignment flag already set
5021                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5022                    // Set the text alignment flag depending on the value of the attribute
5023                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5024                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5025                    break;
5026                case R.styleable.View_importantForAccessibility:
5027                    setImportantForAccessibility(a.getInt(attr,
5028                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5029                    break;
5030                case R.styleable.View_accessibilityLiveRegion:
5031                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5032                    break;
5033                case R.styleable.View_transitionName:
5034                    setTransitionName(a.getString(attr));
5035                    break;
5036                case R.styleable.View_nestedScrollingEnabled:
5037                    setNestedScrollingEnabled(a.getBoolean(attr, false));
5038                    break;
5039                case R.styleable.View_stateListAnimator:
5040                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5041                            a.getResourceId(attr, 0)));
5042                    break;
5043                case R.styleable.View_backgroundTint:
5044                    // This will get applied later during setBackground().
5045                    if (mBackgroundTint == null) {
5046                        mBackgroundTint = new TintInfo();
5047                    }
5048                    mBackgroundTint.mTintList = a.getColorStateList(
5049                            R.styleable.View_backgroundTint);
5050                    mBackgroundTint.mHasTintList = true;
5051                    break;
5052                case R.styleable.View_backgroundTintMode:
5053                    // This will get applied later during setBackground().
5054                    if (mBackgroundTint == null) {
5055                        mBackgroundTint = new TintInfo();
5056                    }
5057                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5058                            R.styleable.View_backgroundTintMode, -1), null);
5059                    mBackgroundTint.mHasTintMode = true;
5060                    break;
5061                case R.styleable.View_outlineProvider:
5062                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5063                            PROVIDER_BACKGROUND));
5064                    break;
5065                case R.styleable.View_foreground:
5066                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5067                        setForeground(a.getDrawable(attr));
5068                    }
5069                    break;
5070                case R.styleable.View_foregroundGravity:
5071                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5072                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5073                    }
5074                    break;
5075                case R.styleable.View_foregroundTintMode:
5076                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5077                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5078                    }
5079                    break;
5080                case R.styleable.View_foregroundTint:
5081                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5082                        setForegroundTintList(a.getColorStateList(attr));
5083                    }
5084                    break;
5085                case R.styleable.View_foregroundInsidePadding:
5086                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5087                        if (mForegroundInfo == null) {
5088                            mForegroundInfo = new ForegroundInfo();
5089                        }
5090                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5091                                mForegroundInfo.mInsidePadding);
5092                    }
5093                    break;
5094                case R.styleable.View_scrollIndicators:
5095                    final int scrollIndicators =
5096                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5097                                    & SCROLL_INDICATORS_PFLAG3_MASK;
5098                    if (scrollIndicators != 0) {
5099                        mPrivateFlags3 |= scrollIndicators;
5100                        initializeScrollIndicators = true;
5101                    }
5102                    break;
5103                case R.styleable.View_pointerIcon:
5104                    final int resourceId = a.getResourceId(attr, 0);
5105                    if (resourceId != 0) {
5106                        setPointerIcon(PointerIcon.load(
5107                                context.getResources(), resourceId));
5108                    } else {
5109                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5110                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5111                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5112                        }
5113                    }
5114                    break;
5115                case R.styleable.View_forceHasOverlappingRendering:
5116                    if (a.peekValue(attr) != null) {
5117                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5118                    }
5119                    break;
5120                case R.styleable.View_tooltipText:
5121                    setTooltipText(a.getText(attr));
5122                    break;
5123                case R.styleable.View_keyboardNavigationCluster:
5124                    if (a.peekValue(attr) != null) {
5125                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5126                    }
5127                    break;
5128                case R.styleable.View_focusedByDefault:
5129                    if (a.peekValue(attr) != null) {
5130                        setFocusedByDefault(a.getBoolean(attr, true));
5131                    }
5132                    break;
5133                case R.styleable.View_autofillHints:
5134                    if (a.peekValue(attr) != null) {
5135                        CharSequence[] rawHints = null;
5136                        String rawString = null;
5137
5138                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5139                            int resId = a.getResourceId(attr, 0);
5140
5141                            try {
5142                                rawHints = a.getTextArray(attr);
5143                            } catch (Resources.NotFoundException e) {
5144                                rawString = getResources().getString(resId);
5145                            }
5146                        } else {
5147                            rawString = a.getString(attr);
5148                        }
5149
5150                        if (rawHints == null) {
5151                            if (rawString == null) {
5152                                throw new IllegalArgumentException(
5153                                        "Could not resolve autofillHints");
5154                            } else {
5155                                rawHints = rawString.split(",");
5156                            }
5157                        }
5158
5159                        String[] hints = new String[rawHints.length];
5160
5161                        int numHints = rawHints.length;
5162                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5163                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5164                        }
5165                        setAutofillHints(hints);
5166                    }
5167                    break;
5168                case R.styleable.View_importantForAutofill:
5169                    if (a.peekValue(attr) != null) {
5170                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5171                    }
5172                    break;
5173                case R.styleable.View_defaultFocusHighlightEnabled:
5174                    if (a.peekValue(attr) != null) {
5175                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5176                    }
5177                    break;
5178            }
5179        }
5180
5181        setOverScrollMode(overScrollMode);
5182
5183        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5184        // the resolved layout direction). Those cached values will be used later during padding
5185        // resolution.
5186        mUserPaddingStart = startPadding;
5187        mUserPaddingEnd = endPadding;
5188
5189        if (background != null) {
5190            setBackground(background);
5191        }
5192
5193        // setBackground above will record that padding is currently provided by the background.
5194        // If we have padding specified via xml, record that here instead and use it.
5195        mLeftPaddingDefined = leftPaddingDefined;
5196        mRightPaddingDefined = rightPaddingDefined;
5197
5198        if (padding >= 0) {
5199            leftPadding = padding;
5200            topPadding = padding;
5201            rightPadding = padding;
5202            bottomPadding = padding;
5203            mUserPaddingLeftInitial = padding;
5204            mUserPaddingRightInitial = padding;
5205        } else {
5206            if (paddingHorizontal >= 0) {
5207                leftPadding = paddingHorizontal;
5208                rightPadding = paddingHorizontal;
5209                mUserPaddingLeftInitial = paddingHorizontal;
5210                mUserPaddingRightInitial = paddingHorizontal;
5211            }
5212            if (paddingVertical >= 0) {
5213                topPadding = paddingVertical;
5214                bottomPadding = paddingVertical;
5215            }
5216        }
5217
5218        if (isRtlCompatibilityMode()) {
5219            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5220            // left / right padding are used if defined (meaning here nothing to do). If they are not
5221            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5222            // start / end and resolve them as left / right (layout direction is not taken into account).
5223            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5224            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5225            // defined.
5226            if (!mLeftPaddingDefined && startPaddingDefined) {
5227                leftPadding = startPadding;
5228            }
5229            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5230            if (!mRightPaddingDefined && endPaddingDefined) {
5231                rightPadding = endPadding;
5232            }
5233            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5234        } else {
5235            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5236            // values defined. Otherwise, left /right values are used.
5237            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5238            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5239            // defined.
5240            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5241
5242            if (mLeftPaddingDefined && !hasRelativePadding) {
5243                mUserPaddingLeftInitial = leftPadding;
5244            }
5245            if (mRightPaddingDefined && !hasRelativePadding) {
5246                mUserPaddingRightInitial = rightPadding;
5247            }
5248        }
5249
5250        internalSetPadding(
5251                mUserPaddingLeftInitial,
5252                topPadding >= 0 ? topPadding : mPaddingTop,
5253                mUserPaddingRightInitial,
5254                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5255
5256        if (viewFlagMasks != 0) {
5257            setFlags(viewFlagValues, viewFlagMasks);
5258        }
5259
5260        if (initializeScrollbars) {
5261            initializeScrollbarsInternal(a);
5262        }
5263
5264        if (initializeScrollIndicators) {
5265            initializeScrollIndicatorsInternal();
5266        }
5267
5268        a.recycle();
5269
5270        // Needs to be called after mViewFlags is set
5271        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5272            recomputePadding();
5273        }
5274
5275        if (x != 0 || y != 0) {
5276            scrollTo(x, y);
5277        }
5278
5279        if (transformSet) {
5280            setTranslationX(tx);
5281            setTranslationY(ty);
5282            setTranslationZ(tz);
5283            setElevation(elevation);
5284            setRotation(rotation);
5285            setRotationX(rotationX);
5286            setRotationY(rotationY);
5287            setScaleX(sx);
5288            setScaleY(sy);
5289        }
5290
5291        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5292            setScrollContainer(true);
5293        }
5294
5295        computeOpaqueFlags();
5296    }
5297
5298    /**
5299     * An implementation of OnClickListener that attempts to lazily load a
5300     * named click handling method from a parent or ancestor context.
5301     */
5302    private static class DeclaredOnClickListener implements OnClickListener {
5303        private final View mHostView;
5304        private final String mMethodName;
5305
5306        private Method mResolvedMethod;
5307        private Context mResolvedContext;
5308
5309        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5310            mHostView = hostView;
5311            mMethodName = methodName;
5312        }
5313
5314        @Override
5315        public void onClick(@NonNull View v) {
5316            if (mResolvedMethod == null) {
5317                resolveMethod(mHostView.getContext(), mMethodName);
5318            }
5319
5320            try {
5321                mResolvedMethod.invoke(mResolvedContext, v);
5322            } catch (IllegalAccessException e) {
5323                throw new IllegalStateException(
5324                        "Could not execute non-public method for android:onClick", e);
5325            } catch (InvocationTargetException e) {
5326                throw new IllegalStateException(
5327                        "Could not execute method for android:onClick", e);
5328            }
5329        }
5330
5331        @NonNull
5332        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5333            while (context != null) {
5334                try {
5335                    if (!context.isRestricted()) {
5336                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5337                        if (method != null) {
5338                            mResolvedMethod = method;
5339                            mResolvedContext = context;
5340                            return;
5341                        }
5342                    }
5343                } catch (NoSuchMethodException e) {
5344                    // Failed to find method, keep searching up the hierarchy.
5345                }
5346
5347                if (context instanceof ContextWrapper) {
5348                    context = ((ContextWrapper) context).getBaseContext();
5349                } else {
5350                    // Can't search up the hierarchy, null out and fail.
5351                    context = null;
5352                }
5353            }
5354
5355            final int id = mHostView.getId();
5356            final String idText = id == NO_ID ? "" : " with id '"
5357                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5358            throw new IllegalStateException("Could not find method " + mMethodName
5359                    + "(View) in a parent or ancestor Context for android:onClick "
5360                    + "attribute defined on view " + mHostView.getClass() + idText);
5361        }
5362    }
5363
5364    /**
5365     * Non-public constructor for use in testing
5366     */
5367    View() {
5368        mResources = null;
5369        mRenderNode = RenderNode.create(getClass().getName(), this);
5370    }
5371
5372    final boolean debugDraw() {
5373        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5374    }
5375
5376    private static SparseArray<String> getAttributeMap() {
5377        if (mAttributeMap == null) {
5378            mAttributeMap = new SparseArray<>();
5379        }
5380        return mAttributeMap;
5381    }
5382
5383    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5384        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5385        final int indexCount = t.getIndexCount();
5386        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5387
5388        int i = 0;
5389
5390        // Store raw XML attributes.
5391        for (int j = 0; j < attrsCount; ++j) {
5392            attributes[i] = attrs.getAttributeName(j);
5393            attributes[i + 1] = attrs.getAttributeValue(j);
5394            i += 2;
5395        }
5396
5397        // Store resolved styleable attributes.
5398        final Resources res = t.getResources();
5399        final SparseArray<String> attributeMap = getAttributeMap();
5400        for (int j = 0; j < indexCount; ++j) {
5401            final int index = t.getIndex(j);
5402            if (!t.hasValueOrEmpty(index)) {
5403                // Value is undefined. Skip it.
5404                continue;
5405            }
5406
5407            final int resourceId = t.getResourceId(index, 0);
5408            if (resourceId == 0) {
5409                // Value is not a reference. Skip it.
5410                continue;
5411            }
5412
5413            String resourceName = attributeMap.get(resourceId);
5414            if (resourceName == null) {
5415                try {
5416                    resourceName = res.getResourceName(resourceId);
5417                } catch (Resources.NotFoundException e) {
5418                    resourceName = "0x" + Integer.toHexString(resourceId);
5419                }
5420                attributeMap.put(resourceId, resourceName);
5421            }
5422
5423            attributes[i] = resourceName;
5424            attributes[i + 1] = t.getString(index);
5425            i += 2;
5426        }
5427
5428        // Trim to fit contents.
5429        final String[] trimmed = new String[i];
5430        System.arraycopy(attributes, 0, trimmed, 0, i);
5431        mAttributes = trimmed;
5432    }
5433
5434    public String toString() {
5435        StringBuilder out = new StringBuilder(128);
5436        out.append(getClass().getName());
5437        out.append('{');
5438        out.append(Integer.toHexString(System.identityHashCode(this)));
5439        out.append(' ');
5440        switch (mViewFlags&VISIBILITY_MASK) {
5441            case VISIBLE: out.append('V'); break;
5442            case INVISIBLE: out.append('I'); break;
5443            case GONE: out.append('G'); break;
5444            default: out.append('.'); break;
5445        }
5446        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5447        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5448        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5449        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5450        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5451        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5452        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5453        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5454        out.append(' ');
5455        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5456        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5457        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5458        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5459            out.append('p');
5460        } else {
5461            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5462        }
5463        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5464        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5465        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5466        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5467        out.append(' ');
5468        out.append(mLeft);
5469        out.append(',');
5470        out.append(mTop);
5471        out.append('-');
5472        out.append(mRight);
5473        out.append(',');
5474        out.append(mBottom);
5475        final int id = getId();
5476        if (id != NO_ID) {
5477            out.append(" #");
5478            out.append(Integer.toHexString(id));
5479            final Resources r = mResources;
5480            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5481                try {
5482                    String pkgname;
5483                    switch (id&0xff000000) {
5484                        case 0x7f000000:
5485                            pkgname="app";
5486                            break;
5487                        case 0x01000000:
5488                            pkgname="android";
5489                            break;
5490                        default:
5491                            pkgname = r.getResourcePackageName(id);
5492                            break;
5493                    }
5494                    String typename = r.getResourceTypeName(id);
5495                    String entryname = r.getResourceEntryName(id);
5496                    out.append(" ");
5497                    out.append(pkgname);
5498                    out.append(":");
5499                    out.append(typename);
5500                    out.append("/");
5501                    out.append(entryname);
5502                } catch (Resources.NotFoundException e) {
5503                }
5504            }
5505        }
5506        out.append("}");
5507        return out.toString();
5508    }
5509
5510    /**
5511     * <p>
5512     * Initializes the fading edges from a given set of styled attributes. This
5513     * method should be called by subclasses that need fading edges and when an
5514     * instance of these subclasses is created programmatically rather than
5515     * being inflated from XML. This method is automatically called when the XML
5516     * is inflated.
5517     * </p>
5518     *
5519     * @param a the styled attributes set to initialize the fading edges from
5520     *
5521     * @removed
5522     */
5523    protected void initializeFadingEdge(TypedArray a) {
5524        // This method probably shouldn't have been included in the SDK to begin with.
5525        // It relies on 'a' having been initialized using an attribute filter array that is
5526        // not publicly available to the SDK. The old method has been renamed
5527        // to initializeFadingEdgeInternal and hidden for framework use only;
5528        // this one initializes using defaults to make it safe to call for apps.
5529
5530        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5531
5532        initializeFadingEdgeInternal(arr);
5533
5534        arr.recycle();
5535    }
5536
5537    /**
5538     * <p>
5539     * Initializes the fading edges from a given set of styled attributes. This
5540     * method should be called by subclasses that need fading edges and when an
5541     * instance of these subclasses is created programmatically rather than
5542     * being inflated from XML. This method is automatically called when the XML
5543     * is inflated.
5544     * </p>
5545     *
5546     * @param a the styled attributes set to initialize the fading edges from
5547     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5548     */
5549    protected void initializeFadingEdgeInternal(TypedArray a) {
5550        initScrollCache();
5551
5552        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5553                R.styleable.View_fadingEdgeLength,
5554                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5555    }
5556
5557    /**
5558     * Returns the size of the vertical faded edges used to indicate that more
5559     * content in this view is visible.
5560     *
5561     * @return The size in pixels of the vertical faded edge or 0 if vertical
5562     *         faded edges are not enabled for this view.
5563     * @attr ref android.R.styleable#View_fadingEdgeLength
5564     */
5565    public int getVerticalFadingEdgeLength() {
5566        if (isVerticalFadingEdgeEnabled()) {
5567            ScrollabilityCache cache = mScrollCache;
5568            if (cache != null) {
5569                return cache.fadingEdgeLength;
5570            }
5571        }
5572        return 0;
5573    }
5574
5575    /**
5576     * Set the size of the faded edge used to indicate that more content in this
5577     * view is available.  Will not change whether the fading edge is enabled; use
5578     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5579     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5580     * for the vertical or horizontal fading edges.
5581     *
5582     * @param length The size in pixels of the faded edge used to indicate that more
5583     *        content in this view is visible.
5584     */
5585    public void setFadingEdgeLength(int length) {
5586        initScrollCache();
5587        mScrollCache.fadingEdgeLength = length;
5588    }
5589
5590    /**
5591     * Returns the size of the horizontal faded edges used to indicate that more
5592     * content in this view is visible.
5593     *
5594     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5595     *         faded edges are not enabled for this view.
5596     * @attr ref android.R.styleable#View_fadingEdgeLength
5597     */
5598    public int getHorizontalFadingEdgeLength() {
5599        if (isHorizontalFadingEdgeEnabled()) {
5600            ScrollabilityCache cache = mScrollCache;
5601            if (cache != null) {
5602                return cache.fadingEdgeLength;
5603            }
5604        }
5605        return 0;
5606    }
5607
5608    /**
5609     * Returns the width of the vertical scrollbar.
5610     *
5611     * @return The width in pixels of the vertical scrollbar or 0 if there
5612     *         is no vertical scrollbar.
5613     */
5614    public int getVerticalScrollbarWidth() {
5615        ScrollabilityCache cache = mScrollCache;
5616        if (cache != null) {
5617            ScrollBarDrawable scrollBar = cache.scrollBar;
5618            if (scrollBar != null) {
5619                int size = scrollBar.getSize(true);
5620                if (size <= 0) {
5621                    size = cache.scrollBarSize;
5622                }
5623                return size;
5624            }
5625            return 0;
5626        }
5627        return 0;
5628    }
5629
5630    /**
5631     * Returns the height of the horizontal scrollbar.
5632     *
5633     * @return The height in pixels of the horizontal scrollbar or 0 if
5634     *         there is no horizontal scrollbar.
5635     */
5636    protected int getHorizontalScrollbarHeight() {
5637        ScrollabilityCache cache = mScrollCache;
5638        if (cache != null) {
5639            ScrollBarDrawable scrollBar = cache.scrollBar;
5640            if (scrollBar != null) {
5641                int size = scrollBar.getSize(false);
5642                if (size <= 0) {
5643                    size = cache.scrollBarSize;
5644                }
5645                return size;
5646            }
5647            return 0;
5648        }
5649        return 0;
5650    }
5651
5652    /**
5653     * <p>
5654     * Initializes the scrollbars from a given set of styled attributes. This
5655     * method should be called by subclasses that need scrollbars and when an
5656     * instance of these subclasses is created programmatically rather than
5657     * being inflated from XML. This method is automatically called when the XML
5658     * is inflated.
5659     * </p>
5660     *
5661     * @param a the styled attributes set to initialize the scrollbars from
5662     *
5663     * @removed
5664     */
5665    protected void initializeScrollbars(TypedArray a) {
5666        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5667        // using the View filter array which is not available to the SDK. As such, internal
5668        // framework usage now uses initializeScrollbarsInternal and we grab a default
5669        // TypedArray with the right filter instead here.
5670        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5671
5672        initializeScrollbarsInternal(arr);
5673
5674        // We ignored the method parameter. Recycle the one we actually did use.
5675        arr.recycle();
5676    }
5677
5678    /**
5679     * <p>
5680     * Initializes the scrollbars from a given set of styled attributes. This
5681     * method should be called by subclasses that need scrollbars and when an
5682     * instance of these subclasses is created programmatically rather than
5683     * being inflated from XML. This method is automatically called when the XML
5684     * is inflated.
5685     * </p>
5686     *
5687     * @param a the styled attributes set to initialize the scrollbars from
5688     * @hide
5689     */
5690    protected void initializeScrollbarsInternal(TypedArray a) {
5691        initScrollCache();
5692
5693        final ScrollabilityCache scrollabilityCache = mScrollCache;
5694
5695        if (scrollabilityCache.scrollBar == null) {
5696            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5697            scrollabilityCache.scrollBar.setState(getDrawableState());
5698            scrollabilityCache.scrollBar.setCallback(this);
5699        }
5700
5701        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5702
5703        if (!fadeScrollbars) {
5704            scrollabilityCache.state = ScrollabilityCache.ON;
5705        }
5706        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5707
5708
5709        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5710                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5711                        .getScrollBarFadeDuration());
5712        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5713                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5714                ViewConfiguration.getScrollDefaultDelay());
5715
5716
5717        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5718                com.android.internal.R.styleable.View_scrollbarSize,
5719                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5720
5721        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5722        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5723
5724        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5725        if (thumb != null) {
5726            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5727        }
5728
5729        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5730                false);
5731        if (alwaysDraw) {
5732            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5733        }
5734
5735        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5736        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5737
5738        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5739        if (thumb != null) {
5740            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5741        }
5742
5743        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5744                false);
5745        if (alwaysDraw) {
5746            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5747        }
5748
5749        // Apply layout direction to the new Drawables if needed
5750        final int layoutDirection = getLayoutDirection();
5751        if (track != null) {
5752            track.setLayoutDirection(layoutDirection);
5753        }
5754        if (thumb != null) {
5755            thumb.setLayoutDirection(layoutDirection);
5756        }
5757
5758        // Re-apply user/background padding so that scrollbar(s) get added
5759        resolvePadding();
5760    }
5761
5762    private void initializeScrollIndicatorsInternal() {
5763        // Some day maybe we'll break this into top/left/start/etc. and let the
5764        // client control it. Until then, you can have any scroll indicator you
5765        // want as long as it's a 1dp foreground-colored rectangle.
5766        if (mScrollIndicatorDrawable == null) {
5767            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5768        }
5769    }
5770
5771    /**
5772     * <p>
5773     * Initalizes the scrollability cache if necessary.
5774     * </p>
5775     */
5776    private void initScrollCache() {
5777        if (mScrollCache == null) {
5778            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5779        }
5780    }
5781
5782    private ScrollabilityCache getScrollCache() {
5783        initScrollCache();
5784        return mScrollCache;
5785    }
5786
5787    /**
5788     * Set the position of the vertical scroll bar. Should be one of
5789     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5790     * {@link #SCROLLBAR_POSITION_RIGHT}.
5791     *
5792     * @param position Where the vertical scroll bar should be positioned.
5793     */
5794    public void setVerticalScrollbarPosition(int position) {
5795        if (mVerticalScrollbarPosition != position) {
5796            mVerticalScrollbarPosition = position;
5797            computeOpaqueFlags();
5798            resolvePadding();
5799        }
5800    }
5801
5802    /**
5803     * @return The position where the vertical scroll bar will show, if applicable.
5804     * @see #setVerticalScrollbarPosition(int)
5805     */
5806    public int getVerticalScrollbarPosition() {
5807        return mVerticalScrollbarPosition;
5808    }
5809
5810    boolean isOnScrollbar(float x, float y) {
5811        if (mScrollCache == null) {
5812            return false;
5813        }
5814        x += getScrollX();
5815        y += getScrollY();
5816        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5817            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5818            getVerticalScrollBarBounds(null, touchBounds);
5819            if (touchBounds.contains((int) x, (int) y)) {
5820                return true;
5821            }
5822        }
5823        if (isHorizontalScrollBarEnabled()) {
5824            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5825            getHorizontalScrollBarBounds(null, touchBounds);
5826            if (touchBounds.contains((int) x, (int) y)) {
5827                return true;
5828            }
5829        }
5830        return false;
5831    }
5832
5833    boolean isOnScrollbarThumb(float x, float y) {
5834        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5835    }
5836
5837    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5838        if (mScrollCache == null) {
5839            return false;
5840        }
5841        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5842            x += getScrollX();
5843            y += getScrollY();
5844            final Rect bounds = mScrollCache.mScrollBarBounds;
5845            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5846            getVerticalScrollBarBounds(bounds, touchBounds);
5847            final int range = computeVerticalScrollRange();
5848            final int offset = computeVerticalScrollOffset();
5849            final int extent = computeVerticalScrollExtent();
5850            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5851                    extent, range);
5852            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5853                    extent, range, offset);
5854            final int thumbTop = bounds.top + thumbOffset;
5855            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5856            if (x >= touchBounds.left && x <= touchBounds.right
5857                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5858                return true;
5859            }
5860        }
5861        return false;
5862    }
5863
5864    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5865        if (mScrollCache == null) {
5866            return false;
5867        }
5868        if (isHorizontalScrollBarEnabled()) {
5869            x += getScrollX();
5870            y += getScrollY();
5871            final Rect bounds = mScrollCache.mScrollBarBounds;
5872            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5873            getHorizontalScrollBarBounds(bounds, touchBounds);
5874            final int range = computeHorizontalScrollRange();
5875            final int offset = computeHorizontalScrollOffset();
5876            final int extent = computeHorizontalScrollExtent();
5877            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5878                    extent, range);
5879            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5880                    extent, range, offset);
5881            final int thumbLeft = bounds.left + thumbOffset;
5882            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5883            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5884                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5885                return true;
5886            }
5887        }
5888        return false;
5889    }
5890
5891    boolean isDraggingScrollBar() {
5892        return mScrollCache != null
5893                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5894    }
5895
5896    /**
5897     * Sets the state of all scroll indicators.
5898     * <p>
5899     * See {@link #setScrollIndicators(int, int)} for usage information.
5900     *
5901     * @param indicators a bitmask of indicators that should be enabled, or
5902     *                   {@code 0} to disable all indicators
5903     * @see #setScrollIndicators(int, int)
5904     * @see #getScrollIndicators()
5905     * @attr ref android.R.styleable#View_scrollIndicators
5906     */
5907    public void setScrollIndicators(@ScrollIndicators int indicators) {
5908        setScrollIndicators(indicators,
5909                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5910    }
5911
5912    /**
5913     * Sets the state of the scroll indicators specified by the mask. To change
5914     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5915     * <p>
5916     * When a scroll indicator is enabled, it will be displayed if the view
5917     * can scroll in the direction of the indicator.
5918     * <p>
5919     * Multiple indicator types may be enabled or disabled by passing the
5920     * logical OR of the desired types. If multiple types are specified, they
5921     * will all be set to the same enabled state.
5922     * <p>
5923     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5924     *
5925     * @param indicators the indicator direction, or the logical OR of multiple
5926     *             indicator directions. One or more of:
5927     *             <ul>
5928     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5929     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5930     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5931     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5932     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5933     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5934     *             </ul>
5935     * @see #setScrollIndicators(int)
5936     * @see #getScrollIndicators()
5937     * @attr ref android.R.styleable#View_scrollIndicators
5938     */
5939    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5940        // Shift and sanitize mask.
5941        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5942        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5943
5944        // Shift and mask indicators.
5945        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5946        indicators &= mask;
5947
5948        // Merge with non-masked flags.
5949        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5950
5951        if (mPrivateFlags3 != updatedFlags) {
5952            mPrivateFlags3 = updatedFlags;
5953
5954            if (indicators != 0) {
5955                initializeScrollIndicatorsInternal();
5956            }
5957            invalidate();
5958        }
5959    }
5960
5961    /**
5962     * Returns a bitmask representing the enabled scroll indicators.
5963     * <p>
5964     * For example, if the top and left scroll indicators are enabled and all
5965     * other indicators are disabled, the return value will be
5966     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5967     * <p>
5968     * To check whether the bottom scroll indicator is enabled, use the value
5969     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5970     *
5971     * @return a bitmask representing the enabled scroll indicators
5972     */
5973    @ScrollIndicators
5974    public int getScrollIndicators() {
5975        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5976                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5977    }
5978
5979    ListenerInfo getListenerInfo() {
5980        if (mListenerInfo != null) {
5981            return mListenerInfo;
5982        }
5983        mListenerInfo = new ListenerInfo();
5984        return mListenerInfo;
5985    }
5986
5987    /**
5988     * Register a callback to be invoked when the scroll X or Y positions of
5989     * this view change.
5990     * <p>
5991     * <b>Note:</b> Some views handle scrolling independently from View and may
5992     * have their own separate listeners for scroll-type events. For example,
5993     * {@link android.widget.ListView ListView} allows clients to register an
5994     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5995     * to listen for changes in list scroll position.
5996     *
5997     * @param l The listener to notify when the scroll X or Y position changes.
5998     * @see android.view.View#getScrollX()
5999     * @see android.view.View#getScrollY()
6000     */
6001    public void setOnScrollChangeListener(OnScrollChangeListener l) {
6002        getListenerInfo().mOnScrollChangeListener = l;
6003    }
6004
6005    /**
6006     * Register a callback to be invoked when focus of this view changed.
6007     *
6008     * @param l The callback that will run.
6009     */
6010    public void setOnFocusChangeListener(OnFocusChangeListener l) {
6011        getListenerInfo().mOnFocusChangeListener = l;
6012    }
6013
6014    /**
6015     * Add a listener that will be called when the bounds of the view change due to
6016     * layout processing.
6017     *
6018     * @param listener The listener that will be called when layout bounds change.
6019     */
6020    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6021        ListenerInfo li = getListenerInfo();
6022        if (li.mOnLayoutChangeListeners == null) {
6023            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6024        }
6025        if (!li.mOnLayoutChangeListeners.contains(listener)) {
6026            li.mOnLayoutChangeListeners.add(listener);
6027        }
6028    }
6029
6030    /**
6031     * Remove a listener for layout changes.
6032     *
6033     * @param listener The listener for layout bounds change.
6034     */
6035    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6036        ListenerInfo li = mListenerInfo;
6037        if (li == null || li.mOnLayoutChangeListeners == null) {
6038            return;
6039        }
6040        li.mOnLayoutChangeListeners.remove(listener);
6041    }
6042
6043    /**
6044     * Add a listener for attach state changes.
6045     *
6046     * This listener will be called whenever this view is attached or detached
6047     * from a window. Remove the listener using
6048     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6049     *
6050     * @param listener Listener to attach
6051     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6052     */
6053    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6054        ListenerInfo li = getListenerInfo();
6055        if (li.mOnAttachStateChangeListeners == null) {
6056            li.mOnAttachStateChangeListeners
6057                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6058        }
6059        li.mOnAttachStateChangeListeners.add(listener);
6060    }
6061
6062    /**
6063     * Remove a listener for attach state changes. The listener will receive no further
6064     * notification of window attach/detach events.
6065     *
6066     * @param listener Listener to remove
6067     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6068     */
6069    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6070        ListenerInfo li = mListenerInfo;
6071        if (li == null || li.mOnAttachStateChangeListeners == null) {
6072            return;
6073        }
6074        li.mOnAttachStateChangeListeners.remove(listener);
6075    }
6076
6077    /**
6078     * Returns the focus-change callback registered for this view.
6079     *
6080     * @return The callback, or null if one is not registered.
6081     */
6082    public OnFocusChangeListener getOnFocusChangeListener() {
6083        ListenerInfo li = mListenerInfo;
6084        return li != null ? li.mOnFocusChangeListener : null;
6085    }
6086
6087    /**
6088     * Register a callback to be invoked when this view is clicked. If this view is not
6089     * clickable, it becomes clickable.
6090     *
6091     * @param l The callback that will run
6092     *
6093     * @see #setClickable(boolean)
6094     */
6095    public void setOnClickListener(@Nullable OnClickListener l) {
6096        if (!isClickable()) {
6097            setClickable(true);
6098        }
6099        getListenerInfo().mOnClickListener = l;
6100    }
6101
6102    /**
6103     * Return whether this view has an attached OnClickListener.  Returns
6104     * true if there is a listener, false if there is none.
6105     */
6106    public boolean hasOnClickListeners() {
6107        ListenerInfo li = mListenerInfo;
6108        return (li != null && li.mOnClickListener != null);
6109    }
6110
6111    /**
6112     * Register a callback to be invoked when this view is clicked and held. If this view is not
6113     * long clickable, it becomes long clickable.
6114     *
6115     * @param l The callback that will run
6116     *
6117     * @see #setLongClickable(boolean)
6118     */
6119    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6120        if (!isLongClickable()) {
6121            setLongClickable(true);
6122        }
6123        getListenerInfo().mOnLongClickListener = l;
6124    }
6125
6126    /**
6127     * Register a callback to be invoked when this view is context clicked. If the view is not
6128     * context clickable, it becomes context clickable.
6129     *
6130     * @param l The callback that will run
6131     * @see #setContextClickable(boolean)
6132     */
6133    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6134        if (!isContextClickable()) {
6135            setContextClickable(true);
6136        }
6137        getListenerInfo().mOnContextClickListener = l;
6138    }
6139
6140    /**
6141     * Register a callback to be invoked when the context menu for this view is
6142     * being built. If this view is not long clickable, it becomes long clickable.
6143     *
6144     * @param l The callback that will run
6145     *
6146     */
6147    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6148        if (!isLongClickable()) {
6149            setLongClickable(true);
6150        }
6151        getListenerInfo().mOnCreateContextMenuListener = l;
6152    }
6153
6154    /**
6155     * Set an observer to collect stats for each frame rendered for this view.
6156     *
6157     * @hide
6158     */
6159    public void addFrameMetricsListener(Window window,
6160            Window.OnFrameMetricsAvailableListener listener,
6161            Handler handler) {
6162        if (mAttachInfo != null) {
6163            if (mAttachInfo.mThreadedRenderer != null) {
6164                if (mFrameMetricsObservers == null) {
6165                    mFrameMetricsObservers = new ArrayList<>();
6166                }
6167
6168                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6169                        handler.getLooper(), listener);
6170                mFrameMetricsObservers.add(fmo);
6171                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6172            } else {
6173                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6174            }
6175        } else {
6176            if (mFrameMetricsObservers == null) {
6177                mFrameMetricsObservers = new ArrayList<>();
6178            }
6179
6180            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6181                    handler.getLooper(), listener);
6182            mFrameMetricsObservers.add(fmo);
6183        }
6184    }
6185
6186    /**
6187     * Remove observer configured to collect frame stats for this view.
6188     *
6189     * @hide
6190     */
6191    public void removeFrameMetricsListener(
6192            Window.OnFrameMetricsAvailableListener listener) {
6193        ThreadedRenderer renderer = getThreadedRenderer();
6194        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6195        if (fmo == null) {
6196            throw new IllegalArgumentException(
6197                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6198        }
6199
6200        if (mFrameMetricsObservers != null) {
6201            mFrameMetricsObservers.remove(fmo);
6202            if (renderer != null) {
6203                renderer.removeFrameMetricsObserver(fmo);
6204            }
6205        }
6206    }
6207
6208    private void registerPendingFrameMetricsObservers() {
6209        if (mFrameMetricsObservers != null) {
6210            ThreadedRenderer renderer = getThreadedRenderer();
6211            if (renderer != null) {
6212                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6213                    renderer.addFrameMetricsObserver(fmo);
6214                }
6215            } else {
6216                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6217            }
6218        }
6219    }
6220
6221    private FrameMetricsObserver findFrameMetricsObserver(
6222            Window.OnFrameMetricsAvailableListener listener) {
6223        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6224            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6225            if (observer.mListener == listener) {
6226                return observer;
6227            }
6228        }
6229
6230        return null;
6231    }
6232
6233    /**
6234     * Call this view's OnClickListener, if it is defined.  Performs all normal
6235     * actions associated with clicking: reporting accessibility event, playing
6236     * a sound, etc.
6237     *
6238     * @return True there was an assigned OnClickListener that was called, false
6239     *         otherwise is returned.
6240     */
6241    public boolean performClick() {
6242        final boolean result;
6243        final ListenerInfo li = mListenerInfo;
6244        if (li != null && li.mOnClickListener != null) {
6245            playSoundEffect(SoundEffectConstants.CLICK);
6246            li.mOnClickListener.onClick(this);
6247            result = true;
6248        } else {
6249            result = false;
6250        }
6251
6252        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6253
6254        notifyEnterOrExitForAutoFillIfNeeded(true);
6255
6256        return result;
6257    }
6258
6259    /**
6260     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6261     * this only calls the listener, and does not do any associated clicking
6262     * actions like reporting an accessibility event.
6263     *
6264     * @return True there was an assigned OnClickListener that was called, false
6265     *         otherwise is returned.
6266     */
6267    public boolean callOnClick() {
6268        ListenerInfo li = mListenerInfo;
6269        if (li != null && li.mOnClickListener != null) {
6270            li.mOnClickListener.onClick(this);
6271            return true;
6272        }
6273        return false;
6274    }
6275
6276    /**
6277     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6278     * context menu if the OnLongClickListener did not consume the event.
6279     *
6280     * @return {@code true} if one of the above receivers consumed the event,
6281     *         {@code false} otherwise
6282     */
6283    public boolean performLongClick() {
6284        return performLongClickInternal(mLongClickX, mLongClickY);
6285    }
6286
6287    /**
6288     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6289     * context menu if the OnLongClickListener did not consume the event,
6290     * anchoring it to an (x,y) coordinate.
6291     *
6292     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6293     *          to disable anchoring
6294     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6295     *          to disable anchoring
6296     * @return {@code true} if one of the above receivers consumed the event,
6297     *         {@code false} otherwise
6298     */
6299    public boolean performLongClick(float x, float y) {
6300        mLongClickX = x;
6301        mLongClickY = y;
6302        final boolean handled = performLongClick();
6303        mLongClickX = Float.NaN;
6304        mLongClickY = Float.NaN;
6305        return handled;
6306    }
6307
6308    /**
6309     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6310     * context menu if the OnLongClickListener did not consume the event,
6311     * optionally anchoring it to an (x,y) coordinate.
6312     *
6313     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6314     *          to disable anchoring
6315     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6316     *          to disable anchoring
6317     * @return {@code true} if one of the above receivers consumed the event,
6318     *         {@code false} otherwise
6319     */
6320    private boolean performLongClickInternal(float x, float y) {
6321        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6322
6323        boolean handled = false;
6324        final ListenerInfo li = mListenerInfo;
6325        if (li != null && li.mOnLongClickListener != null) {
6326            handled = li.mOnLongClickListener.onLongClick(View.this);
6327        }
6328        if (!handled) {
6329            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6330            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6331        }
6332        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6333            if (!handled) {
6334                handled = showLongClickTooltip((int) x, (int) y);
6335            }
6336        }
6337        if (handled) {
6338            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6339        }
6340        return handled;
6341    }
6342
6343    /**
6344     * Call this view's OnContextClickListener, if it is defined.
6345     *
6346     * @param x the x coordinate of the context click
6347     * @param y the y coordinate of the context click
6348     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6349     *         otherwise.
6350     */
6351    public boolean performContextClick(float x, float y) {
6352        return performContextClick();
6353    }
6354
6355    /**
6356     * Call this view's OnContextClickListener, if it is defined.
6357     *
6358     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6359     *         otherwise.
6360     */
6361    public boolean performContextClick() {
6362        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6363
6364        boolean handled = false;
6365        ListenerInfo li = mListenerInfo;
6366        if (li != null && li.mOnContextClickListener != null) {
6367            handled = li.mOnContextClickListener.onContextClick(View.this);
6368        }
6369        if (handled) {
6370            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6371        }
6372        return handled;
6373    }
6374
6375    /**
6376     * Performs button-related actions during a touch down event.
6377     *
6378     * @param event The event.
6379     * @return True if the down was consumed.
6380     *
6381     * @hide
6382     */
6383    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6384        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6385            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6386            showContextMenu(event.getX(), event.getY());
6387            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6388            return true;
6389        }
6390        return false;
6391    }
6392
6393    /**
6394     * Shows the context menu for this view.
6395     *
6396     * @return {@code true} if the context menu was shown, {@code false}
6397     *         otherwise
6398     * @see #showContextMenu(float, float)
6399     */
6400    public boolean showContextMenu() {
6401        return getParent().showContextMenuForChild(this);
6402    }
6403
6404    /**
6405     * Shows the context menu for this view anchored to the specified
6406     * view-relative coordinate.
6407     *
6408     * @param x the X coordinate in pixels relative to the view to which the
6409     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6410     * @param y the Y coordinate in pixels relative to the view to which the
6411     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6412     * @return {@code true} if the context menu was shown, {@code false}
6413     *         otherwise
6414     */
6415    public boolean showContextMenu(float x, float y) {
6416        return getParent().showContextMenuForChild(this, x, y);
6417    }
6418
6419    /**
6420     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6421     *
6422     * @param callback Callback that will control the lifecycle of the action mode
6423     * @return The new action mode if it is started, null otherwise
6424     *
6425     * @see ActionMode
6426     * @see #startActionMode(android.view.ActionMode.Callback, int)
6427     */
6428    public ActionMode startActionMode(ActionMode.Callback callback) {
6429        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6430    }
6431
6432    /**
6433     * Start an action mode with the given type.
6434     *
6435     * @param callback Callback that will control the lifecycle of the action mode
6436     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6437     * @return The new action mode if it is started, null otherwise
6438     *
6439     * @see ActionMode
6440     */
6441    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6442        ViewParent parent = getParent();
6443        if (parent == null) return null;
6444        try {
6445            return parent.startActionModeForChild(this, callback, type);
6446        } catch (AbstractMethodError ame) {
6447            // Older implementations of custom views might not implement this.
6448            return parent.startActionModeForChild(this, callback);
6449        }
6450    }
6451
6452    /**
6453     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6454     * Context, creating a unique View identifier to retrieve the result.
6455     *
6456     * @param intent The Intent to be started.
6457     * @param requestCode The request code to use.
6458     * @hide
6459     */
6460    public void startActivityForResult(Intent intent, int requestCode) {
6461        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6462        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6463    }
6464
6465    /**
6466     * If this View corresponds to the calling who, dispatches the activity result.
6467     * @param who The identifier for the targeted View to receive the result.
6468     * @param requestCode The integer request code originally supplied to
6469     *                    startActivityForResult(), allowing you to identify who this
6470     *                    result came from.
6471     * @param resultCode The integer result code returned by the child activity
6472     *                   through its setResult().
6473     * @param data An Intent, which can return result data to the caller
6474     *               (various data can be attached to Intent "extras").
6475     * @return {@code true} if the activity result was dispatched.
6476     * @hide
6477     */
6478    public boolean dispatchActivityResult(
6479            String who, int requestCode, int resultCode, Intent data) {
6480        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6481            onActivityResult(requestCode, resultCode, data);
6482            mStartActivityRequestWho = null;
6483            return true;
6484        }
6485        return false;
6486    }
6487
6488    /**
6489     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6490     *
6491     * @param requestCode The integer request code originally supplied to
6492     *                    startActivityForResult(), allowing you to identify who this
6493     *                    result came from.
6494     * @param resultCode The integer result code returned by the child activity
6495     *                   through its setResult().
6496     * @param data An Intent, which can return result data to the caller
6497     *               (various data can be attached to Intent "extras").
6498     * @hide
6499     */
6500    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6501        // Do nothing.
6502    }
6503
6504    /**
6505     * Register a callback to be invoked when a hardware key is pressed in this view.
6506     * Key presses in software input methods will generally not trigger the methods of
6507     * this listener.
6508     * @param l the key listener to attach to this view
6509     */
6510    public void setOnKeyListener(OnKeyListener l) {
6511        getListenerInfo().mOnKeyListener = l;
6512    }
6513
6514    /**
6515     * Register a callback to be invoked when a touch event is sent to this view.
6516     * @param l the touch listener to attach to this view
6517     */
6518    public void setOnTouchListener(OnTouchListener l) {
6519        getListenerInfo().mOnTouchListener = l;
6520    }
6521
6522    /**
6523     * Register a callback to be invoked when a generic motion event is sent to this view.
6524     * @param l the generic motion listener to attach to this view
6525     */
6526    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6527        getListenerInfo().mOnGenericMotionListener = l;
6528    }
6529
6530    /**
6531     * Register a callback to be invoked when a hover event is sent to this view.
6532     * @param l the hover listener to attach to this view
6533     */
6534    public void setOnHoverListener(OnHoverListener l) {
6535        getListenerInfo().mOnHoverListener = l;
6536    }
6537
6538    /**
6539     * Register a drag event listener callback object for this View. The parameter is
6540     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6541     * View, the system calls the
6542     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6543     * @param l An implementation of {@link android.view.View.OnDragListener}.
6544     */
6545    public void setOnDragListener(OnDragListener l) {
6546        getListenerInfo().mOnDragListener = l;
6547    }
6548
6549    /**
6550     * Give this view focus. This will cause
6551     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6552     *
6553     * Note: this does not check whether this {@link View} should get focus, it just
6554     * gives it focus no matter what.  It should only be called internally by framework
6555     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6556     *
6557     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6558     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6559     *        focus moved when requestFocus() is called. It may not always
6560     *        apply, in which case use the default View.FOCUS_DOWN.
6561     * @param previouslyFocusedRect The rectangle of the view that had focus
6562     *        prior in this View's coordinate system.
6563     */
6564    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6565        if (DBG) {
6566            System.out.println(this + " requestFocus()");
6567        }
6568
6569        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6570            mPrivateFlags |= PFLAG_FOCUSED;
6571
6572            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6573
6574            if (mParent != null) {
6575                mParent.requestChildFocus(this, this);
6576                updateFocusedInCluster(oldFocus, direction);
6577            }
6578
6579            if (mAttachInfo != null) {
6580                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6581            }
6582
6583            onFocusChanged(true, direction, previouslyFocusedRect);
6584            refreshDrawableState();
6585        }
6586    }
6587
6588    /**
6589     * Sets this view's preference for reveal behavior when it gains focus.
6590     *
6591     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6592     * this view would prefer to be brought fully into view when it gains focus.
6593     * For example, a text field that a user is meant to type into. Other views such
6594     * as scrolling containers may prefer to opt-out of this behavior.</p>
6595     *
6596     * <p>The default value for views is true, though subclasses may change this
6597     * based on their preferred behavior.</p>
6598     *
6599     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6600     *
6601     * @see #getRevealOnFocusHint()
6602     */
6603    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6604        if (revealOnFocus) {
6605            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6606        } else {
6607            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6608        }
6609    }
6610
6611    /**
6612     * Returns this view's preference for reveal behavior when it gains focus.
6613     *
6614     * <p>When this method returns true for a child view requesting focus, ancestor
6615     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6616     * should make a best effort to make the newly focused child fully visible to the user.
6617     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6618     * other properties affecting visibility to the user as part of the focus change.</p>
6619     *
6620     * @return true if this view would prefer to become fully visible when it gains focus,
6621     *         false if it would prefer not to disrupt scroll positioning
6622     *
6623     * @see #setRevealOnFocusHint(boolean)
6624     */
6625    public final boolean getRevealOnFocusHint() {
6626        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6627    }
6628
6629    /**
6630     * Populates <code>outRect</code> with the hotspot bounds. By default,
6631     * the hotspot bounds are identical to the screen bounds.
6632     *
6633     * @param outRect rect to populate with hotspot bounds
6634     * @hide Only for internal use by views and widgets.
6635     */
6636    public void getHotspotBounds(Rect outRect) {
6637        final Drawable background = getBackground();
6638        if (background != null) {
6639            background.getHotspotBounds(outRect);
6640        } else {
6641            getBoundsOnScreen(outRect);
6642        }
6643    }
6644
6645    /**
6646     * Request that a rectangle of this view be visible on the screen,
6647     * scrolling if necessary just enough.
6648     *
6649     * <p>A View should call this if it maintains some notion of which part
6650     * of its content is interesting.  For example, a text editing view
6651     * should call this when its cursor moves.
6652     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6653     * It should not be affected by which part of the View is currently visible or its scroll
6654     * position.
6655     *
6656     * @param rectangle The rectangle in the View's content coordinate space
6657     * @return Whether any parent scrolled.
6658     */
6659    public boolean requestRectangleOnScreen(Rect rectangle) {
6660        return requestRectangleOnScreen(rectangle, false);
6661    }
6662
6663    /**
6664     * Request that a rectangle of this view be visible on the screen,
6665     * scrolling if necessary just enough.
6666     *
6667     * <p>A View should call this if it maintains some notion of which part
6668     * of its content is interesting.  For example, a text editing view
6669     * should call this when its cursor moves.
6670     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6671     * It should not be affected by which part of the View is currently visible or its scroll
6672     * position.
6673     * <p>When <code>immediate</code> is set to true, scrolling will not be
6674     * animated.
6675     *
6676     * @param rectangle The rectangle in the View's content coordinate space
6677     * @param immediate True to forbid animated scrolling, false otherwise
6678     * @return Whether any parent scrolled.
6679     */
6680    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6681        if (mParent == null) {
6682            return false;
6683        }
6684
6685        View child = this;
6686
6687        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6688        position.set(rectangle);
6689
6690        ViewParent parent = mParent;
6691        boolean scrolled = false;
6692        while (parent != null) {
6693            rectangle.set((int) position.left, (int) position.top,
6694                    (int) position.right, (int) position.bottom);
6695
6696            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6697
6698            if (!(parent instanceof View)) {
6699                break;
6700            }
6701
6702            // move it from child's content coordinate space to parent's content coordinate space
6703            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6704
6705            child = (View) parent;
6706            parent = child.getParent();
6707        }
6708
6709        return scrolled;
6710    }
6711
6712    /**
6713     * Called when this view wants to give up focus. If focus is cleared
6714     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6715     * <p>
6716     * <strong>Note:</strong> When a View clears focus the framework is trying
6717     * to give focus to the first focusable View from the top. Hence, if this
6718     * View is the first from the top that can take focus, then all callbacks
6719     * related to clearing focus will be invoked after which the framework will
6720     * give focus to this view.
6721     * </p>
6722     */
6723    public void clearFocus() {
6724        if (DBG) {
6725            System.out.println(this + " clearFocus()");
6726        }
6727
6728        clearFocusInternal(null, true, true);
6729    }
6730
6731    /**
6732     * Clears focus from the view, optionally propagating the change up through
6733     * the parent hierarchy and requesting that the root view place new focus.
6734     *
6735     * @param propagate whether to propagate the change up through the parent
6736     *            hierarchy
6737     * @param refocus when propagate is true, specifies whether to request the
6738     *            root view place new focus
6739     */
6740    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6741        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6742            mPrivateFlags &= ~PFLAG_FOCUSED;
6743
6744            if (propagate && mParent != null) {
6745                mParent.clearChildFocus(this);
6746            }
6747
6748            onFocusChanged(false, 0, null);
6749            refreshDrawableState();
6750
6751            if (propagate && (!refocus || !rootViewRequestFocus())) {
6752                notifyGlobalFocusCleared(this);
6753            }
6754        }
6755    }
6756
6757    void notifyGlobalFocusCleared(View oldFocus) {
6758        if (oldFocus != null && mAttachInfo != null) {
6759            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6760        }
6761    }
6762
6763    boolean rootViewRequestFocus() {
6764        final View root = getRootView();
6765        return root != null && root.requestFocus();
6766    }
6767
6768    /**
6769     * Called internally by the view system when a new view is getting focus.
6770     * This is what clears the old focus.
6771     * <p>
6772     * <b>NOTE:</b> The parent view's focused child must be updated manually
6773     * after calling this method. Otherwise, the view hierarchy may be left in
6774     * an inconstent state.
6775     */
6776    void unFocus(View focused) {
6777        if (DBG) {
6778            System.out.println(this + " unFocus()");
6779        }
6780
6781        clearFocusInternal(focused, false, false);
6782    }
6783
6784    /**
6785     * Returns true if this view has focus itself, or is the ancestor of the
6786     * view that has focus.
6787     *
6788     * @return True if this view has or contains focus, false otherwise.
6789     */
6790    @ViewDebug.ExportedProperty(category = "focus")
6791    public boolean hasFocus() {
6792        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6793    }
6794
6795    /**
6796     * Returns true if this view is focusable or if it contains a reachable View
6797     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6798     * is a view whose parents do not block descendants focus.
6799     * Only {@link #VISIBLE} views are considered focusable.
6800     *
6801     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6802     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6803     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6804     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6805     * {@code false} for views not explicitly marked as focusable.
6806     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6807     * behavior.</p>
6808     *
6809     * @return {@code true} if the view is focusable or if the view contains a focusable
6810     *         view, {@code false} otherwise
6811     *
6812     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6813     * @see ViewGroup#getTouchscreenBlocksFocus()
6814     * @see #hasExplicitFocusable()
6815     */
6816    public boolean hasFocusable() {
6817        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6818    }
6819
6820    /**
6821     * Returns true if this view is focusable or if it contains a reachable View
6822     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6823     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6824     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6825     * {@link #FOCUSABLE} are considered focusable.
6826     *
6827     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6828     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6829     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6830     * to focusable will not.</p>
6831     *
6832     * @return {@code true} if the view is focusable or if the view contains a focusable
6833     *         view, {@code false} otherwise
6834     *
6835     * @see #hasFocusable()
6836     */
6837    public boolean hasExplicitFocusable() {
6838        return hasFocusable(false, true);
6839    }
6840
6841    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6842        if (!isFocusableInTouchMode()) {
6843            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6844                final ViewGroup g = (ViewGroup) p;
6845                if (g.shouldBlockFocusForTouchscreen()) {
6846                    return false;
6847                }
6848            }
6849        }
6850
6851        // Invisible and gone views are never focusable.
6852        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6853            return false;
6854        }
6855
6856        // Only use effective focusable value when allowed.
6857        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6858            return true;
6859        }
6860
6861        return false;
6862    }
6863
6864    /**
6865     * Called by the view system when the focus state of this view changes.
6866     * When the focus change event is caused by directional navigation, direction
6867     * and previouslyFocusedRect provide insight into where the focus is coming from.
6868     * When overriding, be sure to call up through to the super class so that
6869     * the standard focus handling will occur.
6870     *
6871     * @param gainFocus True if the View has focus; false otherwise.
6872     * @param direction The direction focus has moved when requestFocus()
6873     *                  is called to give this view focus. Values are
6874     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6875     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6876     *                  It may not always apply, in which case use the default.
6877     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6878     *        system, of the previously focused view.  If applicable, this will be
6879     *        passed in as finer grained information about where the focus is coming
6880     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6881     */
6882    @CallSuper
6883    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6884            @Nullable Rect previouslyFocusedRect) {
6885        if (gainFocus) {
6886            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6887        } else {
6888            notifyViewAccessibilityStateChangedIfNeeded(
6889                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6890        }
6891
6892        // Here we check whether we still need the default focus highlight, and switch it on/off.
6893        switchDefaultFocusHighlight();
6894
6895        InputMethodManager imm = InputMethodManager.peekInstance();
6896        if (!gainFocus) {
6897            if (isPressed()) {
6898                setPressed(false);
6899            }
6900            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6901                imm.focusOut(this);
6902            }
6903            onFocusLost();
6904        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6905            imm.focusIn(this);
6906        }
6907
6908        invalidate(true);
6909        ListenerInfo li = mListenerInfo;
6910        if (li != null && li.mOnFocusChangeListener != null) {
6911            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6912        }
6913
6914        if (mAttachInfo != null) {
6915            mAttachInfo.mKeyDispatchState.reset(this);
6916        }
6917
6918        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6919    }
6920
6921    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6922        if (isAutofillable() && isAttachedToWindow()) {
6923            AutofillManager afm = getAutofillManager();
6924            if (afm != null) {
6925                if (enter && hasWindowFocus() && isFocused()) {
6926                    // We have not been laid out yet, hence cannot evaluate
6927                    // whether this view is visible to the user, we will do
6928                    // the evaluation once layout is complete.
6929                    if (!isLaidOut()) {
6930                        mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
6931                    } else if (isVisibleToUser()) {
6932                        afm.notifyViewEntered(this);
6933                    }
6934                } else if (!hasWindowFocus() || !isFocused()) {
6935                    afm.notifyViewExited(this);
6936                }
6937            }
6938        }
6939    }
6940
6941    /**
6942     * Sends an accessibility event of the given type. If accessibility is
6943     * not enabled this method has no effect. The default implementation calls
6944     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6945     * to populate information about the event source (this View), then calls
6946     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6947     * populate the text content of the event source including its descendants,
6948     * and last calls
6949     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6950     * on its parent to request sending of the event to interested parties.
6951     * <p>
6952     * If an {@link AccessibilityDelegate} has been specified via calling
6953     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6954     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6955     * responsible for handling this call.
6956     * </p>
6957     *
6958     * @param eventType The type of the event to send, as defined by several types from
6959     * {@link android.view.accessibility.AccessibilityEvent}, such as
6960     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6961     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6962     *
6963     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6964     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6965     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6966     * @see AccessibilityDelegate
6967     */
6968    public void sendAccessibilityEvent(int eventType) {
6969        if (mAccessibilityDelegate != null) {
6970            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6971        } else {
6972            sendAccessibilityEventInternal(eventType);
6973        }
6974    }
6975
6976    /**
6977     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6978     * {@link AccessibilityEvent} to make an announcement which is related to some
6979     * sort of a context change for which none of the events representing UI transitions
6980     * is a good fit. For example, announcing a new page in a book. If accessibility
6981     * is not enabled this method does nothing.
6982     *
6983     * @param text The announcement text.
6984     */
6985    public void announceForAccessibility(CharSequence text) {
6986        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6987            AccessibilityEvent event = AccessibilityEvent.obtain(
6988                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6989            onInitializeAccessibilityEvent(event);
6990            event.getText().add(text);
6991            event.setContentDescription(null);
6992            mParent.requestSendAccessibilityEvent(this, event);
6993        }
6994    }
6995
6996    /**
6997     * @see #sendAccessibilityEvent(int)
6998     *
6999     * Note: Called from the default {@link AccessibilityDelegate}.
7000     *
7001     * @hide
7002     */
7003    public void sendAccessibilityEventInternal(int eventType) {
7004        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7005            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7006        }
7007    }
7008
7009    /**
7010     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7011     * takes as an argument an empty {@link AccessibilityEvent} and does not
7012     * perform a check whether accessibility is enabled.
7013     * <p>
7014     * If an {@link AccessibilityDelegate} has been specified via calling
7015     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7016     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7017     * is responsible for handling this call.
7018     * </p>
7019     *
7020     * @param event The event to send.
7021     *
7022     * @see #sendAccessibilityEvent(int)
7023     */
7024    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7025        if (mAccessibilityDelegate != null) {
7026            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7027        } else {
7028            sendAccessibilityEventUncheckedInternal(event);
7029        }
7030    }
7031
7032    /**
7033     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7034     *
7035     * Note: Called from the default {@link AccessibilityDelegate}.
7036     *
7037     * @hide
7038     */
7039    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7040        if (!isShown()) {
7041            return;
7042        }
7043        onInitializeAccessibilityEvent(event);
7044        // Only a subset of accessibility events populates text content.
7045        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7046            dispatchPopulateAccessibilityEvent(event);
7047        }
7048        // In the beginning we called #isShown(), so we know that getParent() is not null.
7049        ViewParent parent = getParent();
7050        if (parent != null) {
7051            getParent().requestSendAccessibilityEvent(this, event);
7052        }
7053    }
7054
7055    /**
7056     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7057     * to its children for adding their text content to the event. Note that the
7058     * event text is populated in a separate dispatch path since we add to the
7059     * event not only the text of the source but also the text of all its descendants.
7060     * A typical implementation will call
7061     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7062     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7063     * on each child. Override this method if custom population of the event text
7064     * content is required.
7065     * <p>
7066     * If an {@link AccessibilityDelegate} has been specified via calling
7067     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7068     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7069     * is responsible for handling this call.
7070     * </p>
7071     * <p>
7072     * <em>Note:</em> Accessibility events of certain types are not dispatched for
7073     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7074     * </p>
7075     *
7076     * @param event The event.
7077     *
7078     * @return True if the event population was completed.
7079     */
7080    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7081        if (mAccessibilityDelegate != null) {
7082            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7083        } else {
7084            return dispatchPopulateAccessibilityEventInternal(event);
7085        }
7086    }
7087
7088    /**
7089     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7090     *
7091     * Note: Called from the default {@link AccessibilityDelegate}.
7092     *
7093     * @hide
7094     */
7095    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7096        onPopulateAccessibilityEvent(event);
7097        return false;
7098    }
7099
7100    /**
7101     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7102     * giving a chance to this View to populate the accessibility event with its
7103     * text content. While this method is free to modify event
7104     * attributes other than text content, doing so should normally be performed in
7105     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7106     * <p>
7107     * Example: Adding formatted date string to an accessibility event in addition
7108     *          to the text added by the super implementation:
7109     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7110     *     super.onPopulateAccessibilityEvent(event);
7111     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7112     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7113     *         mCurrentDate.getTimeInMillis(), flags);
7114     *     event.getText().add(selectedDateUtterance);
7115     * }</pre>
7116     * <p>
7117     * If an {@link AccessibilityDelegate} has been specified via calling
7118     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7119     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7120     * is responsible for handling this call.
7121     * </p>
7122     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7123     * information to the event, in case the default implementation has basic information to add.
7124     * </p>
7125     *
7126     * @param event The accessibility event which to populate.
7127     *
7128     * @see #sendAccessibilityEvent(int)
7129     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7130     */
7131    @CallSuper
7132    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7133        if (mAccessibilityDelegate != null) {
7134            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7135        } else {
7136            onPopulateAccessibilityEventInternal(event);
7137        }
7138    }
7139
7140    /**
7141     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7142     *
7143     * Note: Called from the default {@link AccessibilityDelegate}.
7144     *
7145     * @hide
7146     */
7147    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7148    }
7149
7150    /**
7151     * Initializes an {@link AccessibilityEvent} with information about
7152     * this View which is the event source. In other words, the source of
7153     * an accessibility event is the view whose state change triggered firing
7154     * the event.
7155     * <p>
7156     * Example: Setting the password property of an event in addition
7157     *          to properties set by the super implementation:
7158     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7159     *     super.onInitializeAccessibilityEvent(event);
7160     *     event.setPassword(true);
7161     * }</pre>
7162     * <p>
7163     * If an {@link AccessibilityDelegate} has been specified via calling
7164     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7165     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7166     * is responsible for handling this call.
7167     * </p>
7168     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7169     * information to the event, in case the default implementation has basic information to add.
7170     * </p>
7171     * @param event The event to initialize.
7172     *
7173     * @see #sendAccessibilityEvent(int)
7174     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7175     */
7176    @CallSuper
7177    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7178        if (mAccessibilityDelegate != null) {
7179            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7180        } else {
7181            onInitializeAccessibilityEventInternal(event);
7182        }
7183    }
7184
7185    /**
7186     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7187     *
7188     * Note: Called from the default {@link AccessibilityDelegate}.
7189     *
7190     * @hide
7191     */
7192    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7193        event.setSource(this);
7194        event.setClassName(getAccessibilityClassName());
7195        event.setPackageName(getContext().getPackageName());
7196        event.setEnabled(isEnabled());
7197        event.setContentDescription(mContentDescription);
7198
7199        switch (event.getEventType()) {
7200            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7201                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7202                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7203                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7204                event.setItemCount(focusablesTempList.size());
7205                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7206                if (mAttachInfo != null) {
7207                    focusablesTempList.clear();
7208                }
7209            } break;
7210            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7211                CharSequence text = getIterableTextForAccessibility();
7212                if (text != null && text.length() > 0) {
7213                    event.setFromIndex(getAccessibilitySelectionStart());
7214                    event.setToIndex(getAccessibilitySelectionEnd());
7215                    event.setItemCount(text.length());
7216                }
7217            } break;
7218        }
7219    }
7220
7221    /**
7222     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7223     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7224     * This method is responsible for obtaining an accessibility node info from a
7225     * pool of reusable instances and calling
7226     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7227     * initialize the former.
7228     * <p>
7229     * Note: The client is responsible for recycling the obtained instance by calling
7230     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7231     * </p>
7232     *
7233     * @return A populated {@link AccessibilityNodeInfo}.
7234     *
7235     * @see AccessibilityNodeInfo
7236     */
7237    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7238        if (mAccessibilityDelegate != null) {
7239            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7240        } else {
7241            return createAccessibilityNodeInfoInternal();
7242        }
7243    }
7244
7245    /**
7246     * @see #createAccessibilityNodeInfo()
7247     *
7248     * @hide
7249     */
7250    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7251        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7252        if (provider != null) {
7253            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7254        } else {
7255            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7256            onInitializeAccessibilityNodeInfo(info);
7257            return info;
7258        }
7259    }
7260
7261    /**
7262     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7263     * The base implementation sets:
7264     * <ul>
7265     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7266     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7267     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7268     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7269     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7270     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7271     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7272     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7273     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7274     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7275     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7276     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7277     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7278     * </ul>
7279     * <p>
7280     * Subclasses should override this method, call the super implementation,
7281     * and set additional attributes.
7282     * </p>
7283     * <p>
7284     * If an {@link AccessibilityDelegate} has been specified via calling
7285     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7286     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7287     * is responsible for handling this call.
7288     * </p>
7289     *
7290     * @param info The instance to initialize.
7291     */
7292    @CallSuper
7293    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7294        if (mAccessibilityDelegate != null) {
7295            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7296        } else {
7297            onInitializeAccessibilityNodeInfoInternal(info);
7298        }
7299    }
7300
7301    /**
7302     * Gets the location of this view in screen coordinates.
7303     *
7304     * @param outRect The output location
7305     * @hide
7306     */
7307    public void getBoundsOnScreen(Rect outRect) {
7308        getBoundsOnScreen(outRect, false);
7309    }
7310
7311    /**
7312     * Gets the location of this view in screen coordinates.
7313     *
7314     * @param outRect The output location
7315     * @param clipToParent Whether to clip child bounds to the parent ones.
7316     * @hide
7317     */
7318    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7319        if (mAttachInfo == null) {
7320            return;
7321        }
7322
7323        RectF position = mAttachInfo.mTmpTransformRect;
7324        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7325        mapRectFromViewToScreenCoords(position, clipToParent);
7326        outRect.set(Math.round(position.left), Math.round(position.top),
7327                Math.round(position.right), Math.round(position.bottom));
7328    }
7329
7330    /**
7331     * Map a rectangle from view-relative coordinates to screen-relative coordinates
7332     *
7333     * @param rect The rectangle to be mapped
7334     * @param clipToParent Whether to clip child bounds to the parent ones.
7335     * @hide
7336     */
7337    public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7338        if (!hasIdentityMatrix()) {
7339            getMatrix().mapRect(rect);
7340        }
7341
7342        rect.offset(mLeft, mTop);
7343
7344        ViewParent parent = mParent;
7345        while (parent instanceof View) {
7346            View parentView = (View) parent;
7347
7348            rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7349
7350            if (clipToParent) {
7351                rect.left = Math.max(rect.left, 0);
7352                rect.top = Math.max(rect.top, 0);
7353                rect.right = Math.min(rect.right, parentView.getWidth());
7354                rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7355            }
7356
7357            if (!parentView.hasIdentityMatrix()) {
7358                parentView.getMatrix().mapRect(rect);
7359            }
7360
7361            rect.offset(parentView.mLeft, parentView.mTop);
7362
7363            parent = parentView.mParent;
7364        }
7365
7366        if (parent instanceof ViewRootImpl) {
7367            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7368            rect.offset(0, -viewRootImpl.mCurScrollY);
7369        }
7370
7371        rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7372    }
7373
7374    /**
7375     * Return the class name of this object to be used for accessibility purposes.
7376     * Subclasses should only override this if they are implementing something that
7377     * should be seen as a completely new class of view when used by accessibility,
7378     * unrelated to the class it is deriving from.  This is used to fill in
7379     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7380     */
7381    public CharSequence getAccessibilityClassName() {
7382        return View.class.getName();
7383    }
7384
7385    /**
7386     * Called when assist structure is being retrieved from a view as part of
7387     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7388     * @param structure Fill in with structured view data.  The default implementation
7389     * fills in all data that can be inferred from the view itself.
7390     */
7391    public void onProvideStructure(ViewStructure structure) {
7392        onProvideStructureForAssistOrAutofill(structure, false, 0);
7393    }
7394
7395    /**
7396     * Populates a {@link ViewStructure} to fullfil an autofill request.
7397     *
7398     * <p>The structure should contain at least the following properties:
7399     * <ul>
7400     *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
7401     *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
7402     *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
7403     *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
7404     * </ul>
7405     *
7406     * <p>It's also recommended to set the following properties - the more properties the structure
7407     * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
7408     * using the structure:
7409     *
7410     * <ul>
7411     *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
7412     *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
7413     *       view can only be filled with predefined values (typically used when the autofill type
7414     *       is {@link #AUTOFILL_TYPE_LIST}).
7415     *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
7416     *   <li>Class name ({@link ViewStructure#setClassName(String)}).
7417     *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
7418     *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
7419     *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
7420     *       opacity ({@link ViewStructure#setOpaque(boolean)}).
7421     *   <li>For views representing text fields, text properties such as the text itself
7422     *       ({@link ViewStructure#setText(CharSequence)}), text hints
7423     *       ({@link ViewStructure#setHint(CharSequence)}, input type
7424     *       ({@link ViewStructure#setInputType(int)}),
7425     *   <li>For views representing HTML nodes, its web domain
7426     *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
7427     *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
7428     * </ul>
7429     *
7430     * <p>The default implementation of this method already sets most of these properties based on
7431     * related {@link View} methods (for example, the autofill id is set using
7432     * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
7433     * and views in the standard Android widgets library also override it to set their
7434     * relevant properties (for example, {@link android.widget.TextView} already sets the text
7435     * properties), so it's recommended to only override this method
7436     * (and call {@code super.onProvideAutofillStructure()}) when:
7437     *
7438     * <ul>
7439     *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7440     *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7441     *   <li>The view can only be autofilled with predefined options, so it can call
7442     *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
7443     * </ul>
7444     *
7445     * <p><b>NOTE:</b> the {@code left} and {@code top} values set in
7446     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
7447     * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
7448     *
7449     * <p>Views support the Autofill Framework mainly by:
7450     * <ul>
7451     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7452     *   <li>Notifying the Android System when the view value changed by calling
7453     *       {@link AutofillManager#notifyValueChanged(View)}.
7454     *   <li>Implementing the methods that autofill the view.
7455     * </ul>
7456     * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
7457     * for the latter.
7458     *
7459     * @param structure fill in with structured view data for autofill purposes.
7460     * @param flags optional flags.
7461     *
7462     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7463     */
7464    public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7465        onProvideStructureForAssistOrAutofill(structure, true, flags);
7466    }
7467
7468    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7469            boolean forAutofill, @AutofillFlags int flags) {
7470        final int id = mID;
7471        if (id != NO_ID && !isViewIdGenerated(id)) {
7472            String pkg, type, entry;
7473            try {
7474                final Resources res = getResources();
7475                entry = res.getResourceEntryName(id);
7476                type = res.getResourceTypeName(id);
7477                pkg = res.getResourcePackageName(id);
7478            } catch (Resources.NotFoundException e) {
7479                entry = type = pkg = null;
7480            }
7481            structure.setId(id, pkg, type, entry);
7482        } else {
7483            structure.setId(id, null, null, null);
7484        }
7485
7486        if (forAutofill) {
7487            final @AutofillType int autofillType = getAutofillType();
7488            // Don't need to fill autofill info if view does not support it.
7489            // For example, only TextViews that are editable support autofill
7490            if (autofillType != AUTOFILL_TYPE_NONE) {
7491                structure.setAutofillType(autofillType);
7492                structure.setAutofillHints(getAutofillHints());
7493                structure.setAutofillValue(getAutofillValue());
7494            }
7495        }
7496
7497        int ignoredParentLeft = 0;
7498        int ignoredParentTop = 0;
7499        if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7500            View parentGroup = null;
7501
7502            ViewParent viewParent = getParent();
7503            if (viewParent instanceof View) {
7504                parentGroup = (View) viewParent;
7505            }
7506
7507            while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7508                ignoredParentLeft += parentGroup.mLeft;
7509                ignoredParentTop += parentGroup.mTop;
7510
7511                viewParent = parentGroup.getParent();
7512                if (viewParent instanceof View) {
7513                    parentGroup = (View) viewParent;
7514                } else {
7515                    break;
7516                }
7517            }
7518        }
7519
7520        structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7521                mRight - mLeft, mBottom - mTop);
7522        if (!forAutofill) {
7523            if (!hasIdentityMatrix()) {
7524                structure.setTransformation(getMatrix());
7525            }
7526            structure.setElevation(getZ());
7527        }
7528        structure.setVisibility(getVisibility());
7529        structure.setEnabled(isEnabled());
7530        if (isClickable()) {
7531            structure.setClickable(true);
7532        }
7533        if (isFocusable()) {
7534            structure.setFocusable(true);
7535        }
7536        if (isFocused()) {
7537            structure.setFocused(true);
7538        }
7539        if (isAccessibilityFocused()) {
7540            structure.setAccessibilityFocused(true);
7541        }
7542        if (isSelected()) {
7543            structure.setSelected(true);
7544        }
7545        if (isActivated()) {
7546            structure.setActivated(true);
7547        }
7548        if (isLongClickable()) {
7549            structure.setLongClickable(true);
7550        }
7551        if (this instanceof Checkable) {
7552            structure.setCheckable(true);
7553            if (((Checkable)this).isChecked()) {
7554                structure.setChecked(true);
7555            }
7556        }
7557        if (isOpaque()) {
7558            structure.setOpaque(true);
7559        }
7560        if (isContextClickable()) {
7561            structure.setContextClickable(true);
7562        }
7563        structure.setClassName(getAccessibilityClassName().toString());
7564        structure.setContentDescription(getContentDescription());
7565    }
7566
7567    /**
7568     * Called when assist structure is being retrieved from a view as part of
7569     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7570     * generate additional virtual structure under this view.  The defaullt implementation
7571     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7572     * view's virtual accessibility nodes, if any.  You can override this for a more
7573     * optimal implementation providing this data.
7574     */
7575    public void onProvideVirtualStructure(ViewStructure structure) {
7576        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7577        if (provider != null) {
7578            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7579            structure.setChildCount(1);
7580            ViewStructure root = structure.newChild(0);
7581            populateVirtualStructure(root, provider, info);
7582            info.recycle();
7583        }
7584    }
7585
7586    /**
7587     * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
7588     * request.
7589     *
7590     * <p>This method should be used when the view manages a virtual structure under this view. For
7591     * example, a view that draws input fields using {@link #draw(Canvas)}.
7592     *
7593     * <p>When implementing this method, subclasses must follow the rules below:
7594     *
7595     * <ul>
7596     *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
7597     *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
7598     *       identifying the children in the virtual structure.
7599     *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
7600     *       exclude intermediate levels that are irrelevant for autofill; that would improve the
7601     *       autofill performance.
7602     *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7603     *       children.
7604     *   <li>Set the autofill properties of the child structure as defined by
7605     *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
7606     *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
7607     *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
7608     *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7609     *       when the focused virtual child changed.
7610     *   <li>Call
7611     *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
7612     *       when the value of a virtual child changed.
7613     *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
7614     *       changed and the current context should be committed (for example, when the user tapped
7615     *       a {@code SUBMIT} button in an HTML page).
7616     *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
7617     *       changed and the current context should be canceled (for example, when the user tapped
7618     *       a {@code CANCEL} button in an HTML page).
7619     *   <li>Provide ways for users to manually request autofill by calling
7620     *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
7621     *   <li>The {@code left} and {@code top} values set in
7622     *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
7623     *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
7624     *       structure.
7625     * </ul>
7626     *
7627     * <p>Views with virtual children support the Autofill Framework mainly by:
7628     * <ul>
7629     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7630     *       autofilled.
7631     *   <li>Implementing the methods that autofill the virtual children.
7632     * </ul>
7633     * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
7634     * for the latter.
7635     *
7636     * @param structure fill in with virtual children data for autofill purposes.
7637     * @param flags optional flags.
7638     *
7639     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7640     */
7641    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7642    }
7643
7644    /**
7645     * Automatically fills the content of this view with the {@code value}.
7646     *
7647     * <p>Views support the Autofill Framework mainly by:
7648     * <ul>
7649     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7650     *   <li>Implementing the methods that autofill the view.
7651     * </ul>
7652     * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
7653     * this method is responsible for latter.
7654     *
7655     * <p>This method does nothing by default, but when overridden it typically:
7656     * <ol>
7657     *   <li>Checks if the provided value matches the expected type (which is defined by
7658     *       {@link #getAutofillType()}).
7659     *   <li>Checks if the view is editable - if it isn't, it should return right away.
7660     *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
7661     *   <li>Pass the actual value to the equivalent setter in the view.
7662     * </ol>
7663     *
7664     * <p>For example, a text-field view could implement the method this way:
7665     *
7666     * <pre class="prettyprint">
7667     * &#64;Override
7668     * public void autofill(AutofillValue value) {
7669     *   if (!value.isText() || !this.isEditable()) {
7670     *      return;
7671     *   }
7672     *   CharSequence text = value.getTextValue();
7673     *   if (text != null) {
7674     *     this.setText(text);
7675     *   }
7676     * }
7677     * </pre>
7678     *
7679     * <p>If the value is updated asynchronously the next call to
7680     * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
7681     * changed to the autofilled value. If not, the view will not be considered autofilled.
7682     *
7683     * @param value value to be autofilled.
7684     */
7685    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7686    }
7687
7688    /**
7689     * Automatically fills the content of the virtual children within this view.
7690     *
7691     * <p>Views with virtual children support the Autofill Framework mainly by:
7692     * <ul>
7693     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7694     *       autofilled.
7695     *   <li>Implementing the methods that autofill the virtual children.
7696     * </ul>
7697     * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
7698     * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
7699     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
7700     *
7701     * <p><b>NOTE:</b> to indicate that a virtual view was autofilled,
7702     * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7703     * changes.
7704     *
7705     * @param values map of values to be autofilled, keyed by virtual child id.
7706     *
7707     * @attr ref android.R.styleable#Theme_autofilledHighlight
7708     */
7709    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7710    }
7711
7712    /**
7713     * Gets the unique identifier of this view in the screen, for autofill purposes.
7714     *
7715     * @return The View's autofill id.
7716     */
7717    public final AutofillId getAutofillId() {
7718        if (mAutofillId == null) {
7719            // The autofill id needs to be unique, but its value doesn't matter,
7720            // so it's better to reuse the accessibility id to save space.
7721            mAutofillId = new AutofillId(getAccessibilityViewId());
7722        }
7723        return mAutofillId;
7724    }
7725
7726    /**
7727     * Describes the autofill type of this view, so an
7728     * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
7729     * when autofilling the view.
7730     *
7731     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
7732     * support the Autofill Framework.
7733     *
7734     * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
7735     * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
7736     *
7737     * @see #onProvideAutofillStructure(ViewStructure, int)
7738     * @see #autofill(AutofillValue)
7739     */
7740    public @AutofillType int getAutofillType() {
7741        return AUTOFILL_TYPE_NONE;
7742    }
7743
7744    /**
7745     * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
7746     * to autofill the view with the user's data.
7747     *
7748     * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
7749     *
7750     * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
7751     * {@code null} if no hints were set.
7752     *
7753     * @attr ref android.R.styleable#View_autofillHints
7754     */
7755    @ViewDebug.ExportedProperty()
7756    @Nullable public String[] getAutofillHints() {
7757        return mAutofillHints;
7758    }
7759
7760    /**
7761     * @hide
7762     */
7763    public boolean isAutofilled() {
7764        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7765    }
7766
7767    /**
7768     * Gets the {@link View}'s current autofill value.
7769     *
7770     * <p>By default returns {@code null}, but views should override it to properly support the
7771     * Autofill Framework.
7772     *
7773     * @see #onProvideAutofillStructure(ViewStructure, int)
7774     * @see #autofill(AutofillValue)
7775     */
7776    @Nullable
7777    public AutofillValue getAutofillValue() {
7778        return null;
7779    }
7780
7781    /**
7782     * Gets the mode for determining whether this view is important for autofill.
7783     *
7784     * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
7785     * info about this mode.
7786     *
7787     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7788     * {@link #setImportantForAutofill(int)}.
7789     *
7790     * @attr ref android.R.styleable#View_importantForAutofill
7791     */
7792    @ViewDebug.ExportedProperty(mapping = {
7793            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7794            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7795            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7796            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7797                to = "yesExcludeDescendants"),
7798            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7799                to = "noExcludeDescendants")})
7800    public @AutofillImportance int getImportantForAutofill() {
7801        return (mPrivateFlags3
7802                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7803    }
7804
7805    /**
7806     * Sets the mode for determining whether this view is considered important for autofill.
7807     *
7808     * <p>The platform determines the importance for autofill automatically but you
7809     * can use this method to customize the behavior. For example:
7810     *
7811     * <ol>
7812     *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
7813     *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7814     *   <li>When both the view and its children are irrelevant for autofill (for example, the root
7815     *       view of an activity containing a spreadhseet editor), it should be
7816     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7817     *   <li>When the view content is relevant for autofill but its children aren't (for example,
7818     *       a credit card expiration date represented by a custom view that overrides the proper
7819     *       autofill methods and has 2 children representing the month and year), it should
7820     *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
7821     * </ol>
7822     *
7823     * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7824     * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
7825     * children) will be always be considered not important; for example, when the user explicitly
7826     * makes an autofill request, all views are considered important. See
7827     * {@link #isImportantForAutofill()} for more details about how the View's importance for
7828     * autofill is used.
7829     *
7830     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7831     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7832     * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7833     *
7834     * @attr ref android.R.styleable#View_importantForAutofill
7835     */
7836    public void setImportantForAutofill(@AutofillImportance int mode) {
7837        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7838        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7839                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7840    }
7841
7842    /**
7843     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7844     * associated with this view is considered important for autofill purposes.
7845     *
7846     * <p>Generally speaking, a view is important for autofill if:
7847     * <ol>
7848     * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
7849     * <li>The view contents can help an {@link android.service.autofill.AutofillService}
7850     *     determine how other views can be autofilled.
7851     * <ol>
7852     *
7853     * <p>For example, view containers should typically return {@code false} for performance reasons
7854     * (since the important info is provided by their children), but if its properties have relevant
7855     * information (for example, a resource id called {@code credentials}, it should return
7856     * {@code true}. On the other hand, views representing labels or editable fields should
7857     * typically return {@code true}, but in some cases they could return {@code false}
7858     * (for example, if they're part of a "Captcha" mechanism).
7859     *
7860     * <p>The value returned by this method depends on the value returned by
7861     * {@link #getImportantForAutofill()}:
7862     *
7863     * <ol>
7864     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
7865     *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
7866     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7867     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
7868     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
7869     *       that can return {@code true} in some cases (like a container with a resource id),
7870     *       but {@code false} in most.
7871     *   <li>otherwise, it returns {@code false}.
7872     * </ol>
7873     *
7874     * <p>When a view is considered important for autofill:
7875     * <ul>
7876     *   <li>The view might automatically trigger an autofill request when focused on.
7877     *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
7878     *       request.
7879     * </ul>
7880     *
7881     * <p>On the other hand, when a view is considered not important for autofill:
7882     * <ul>
7883     *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
7884     *       request through {@link AutofillManager#requestAutofill(View)}.
7885     *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
7886     *       autofill request, unless the request has the
7887     *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
7888     * </ul>
7889     *
7890     * @return whether the view is considered important for autofill.
7891     *
7892     * @see #setImportantForAutofill(int)
7893     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7894     * @see #IMPORTANT_FOR_AUTOFILL_YES
7895     * @see #IMPORTANT_FOR_AUTOFILL_NO
7896     * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7897     * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7898     * @see AutofillManager#requestAutofill(View)
7899     */
7900    public final boolean isImportantForAutofill() {
7901        // Check parent mode to ensure we're not hidden.
7902        ViewParent parent = mParent;
7903        while (parent instanceof View) {
7904            final int parentImportance = ((View) parent).getImportantForAutofill();
7905            if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7906                    || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7907                return false;
7908            }
7909            parent = parent.getParent();
7910        }
7911
7912        final int importance = getImportantForAutofill();
7913
7914        // First, check the explicit states.
7915        if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7916                || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7917            return true;
7918        }
7919        if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7920                || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7921            return false;
7922        }
7923
7924        // Then use some heuristics to handle AUTO.
7925
7926        // Always include views that have an explicit resource id.
7927        final int id = mID;
7928        if (id != NO_ID && !isViewIdGenerated(id)) {
7929            final Resources res = getResources();
7930            String entry = null;
7931            String pkg = null;
7932            try {
7933                entry = res.getResourceEntryName(id);
7934                pkg = res.getResourcePackageName(id);
7935            } catch (Resources.NotFoundException e) {
7936                // ignore
7937            }
7938            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7939                return true;
7940            }
7941        }
7942
7943        // Otherwise, assume it's not important...
7944        return false;
7945    }
7946
7947    @Nullable
7948    private AutofillManager getAutofillManager() {
7949        return mContext.getSystemService(AutofillManager.class);
7950    }
7951
7952    private boolean isAutofillable() {
7953        return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
7954                && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID;
7955    }
7956
7957    private void populateVirtualStructure(ViewStructure structure,
7958            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
7959        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7960                null, null, null);
7961        Rect rect = structure.getTempRect();
7962        info.getBoundsInParent(rect);
7963        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7964        structure.setVisibility(VISIBLE);
7965        structure.setEnabled(info.isEnabled());
7966        if (info.isClickable()) {
7967            structure.setClickable(true);
7968        }
7969        if (info.isFocusable()) {
7970            structure.setFocusable(true);
7971        }
7972        if (info.isFocused()) {
7973            structure.setFocused(true);
7974        }
7975        if (info.isAccessibilityFocused()) {
7976            structure.setAccessibilityFocused(true);
7977        }
7978        if (info.isSelected()) {
7979            structure.setSelected(true);
7980        }
7981        if (info.isLongClickable()) {
7982            structure.setLongClickable(true);
7983        }
7984        if (info.isCheckable()) {
7985            structure.setCheckable(true);
7986            if (info.isChecked()) {
7987                structure.setChecked(true);
7988            }
7989        }
7990        if (info.isContextClickable()) {
7991            structure.setContextClickable(true);
7992        }
7993        CharSequence cname = info.getClassName();
7994        structure.setClassName(cname != null ? cname.toString() : null);
7995        structure.setContentDescription(info.getContentDescription());
7996        if ((info.getText() != null || info.getError() != null)) {
7997            structure.setText(info.getText(), info.getTextSelectionStart(),
7998                    info.getTextSelectionEnd());
7999        }
8000        final int NCHILDREN = info.getChildCount();
8001        if (NCHILDREN > 0) {
8002            structure.setChildCount(NCHILDREN);
8003            for (int i=0; i<NCHILDREN; i++) {
8004                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
8005                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
8006                ViewStructure child = structure.newChild(i);
8007                populateVirtualStructure(child, provider, cinfo);
8008                cinfo.recycle();
8009            }
8010        }
8011    }
8012
8013    /**
8014     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
8015     * implementation calls {@link #onProvideStructure} and
8016     * {@link #onProvideVirtualStructure}.
8017     */
8018    public void dispatchProvideStructure(ViewStructure structure) {
8019        dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
8020    }
8021
8022    /**
8023     * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
8024     * when an Assist structure is being created as part of an autofill request.
8025     *
8026     * <p>The default implementation does the following:
8027     * <ul>
8028     *   <li>Sets the {@link AutofillId} in the structure.
8029     *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
8030     *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
8031     * </ul>
8032     *
8033     * <p>Typically, this method should only be overridden by subclasses that provide a view
8034     * hierarchy (such as {@link ViewGroup}) - other classes should override
8035     * {@link #onProvideAutofillStructure(ViewStructure, int)} or
8036     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
8037     *
8038     * <p>When overridden, it must:
8039     *
8040     * <ul>
8041     *   <li>Either call
8042     *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
8043     *       set the {@link AutofillId} in the structure (for example, by calling
8044     *       {@code structure.setAutofillId(getAutofillId())}).
8045     *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
8046     *       set, all views in the structure should be considered important for autofill,
8047     *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
8048     *       respect this flag to provide a better user experience - this flag is typically used
8049     *       when an user explicitly requested autofill. If the flag is not set,
8050     *       then only views marked as important for autofill should be included in the
8051     *       structure - skipping non-important views optimizes the overall autofill performance.
8052     * </ul>
8053     *
8054     * @param structure fill in with structured view data for autofill purposes.
8055     * @param flags optional flags.
8056     *
8057     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8058     */
8059    public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
8060            @AutofillFlags int flags) {
8061        dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
8062    }
8063
8064    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
8065            boolean forAutofill, @AutofillFlags int flags) {
8066        if (forAutofill) {
8067            structure.setAutofillId(getAutofillId());
8068            onProvideAutofillStructure(structure, flags);
8069            onProvideAutofillVirtualStructure(structure, flags);
8070        } else if (!isAssistBlocked()) {
8071            onProvideStructure(structure);
8072            onProvideVirtualStructure(structure);
8073        } else {
8074            structure.setClassName(getAccessibilityClassName().toString());
8075            structure.setAssistBlocked(true);
8076        }
8077    }
8078
8079    /**
8080     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
8081     *
8082     * Note: Called from the default {@link AccessibilityDelegate}.
8083     *
8084     * @hide
8085     */
8086    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
8087        if (mAttachInfo == null) {
8088            return;
8089        }
8090
8091        Rect bounds = mAttachInfo.mTmpInvalRect;
8092
8093        getDrawingRect(bounds);
8094        info.setBoundsInParent(bounds);
8095
8096        getBoundsOnScreen(bounds, true);
8097        info.setBoundsInScreen(bounds);
8098
8099        ViewParent parent = getParentForAccessibility();
8100        if (parent instanceof View) {
8101            info.setParent((View) parent);
8102        }
8103
8104        if (mID != View.NO_ID) {
8105            View rootView = getRootView();
8106            if (rootView == null) {
8107                rootView = this;
8108            }
8109
8110            View label = rootView.findLabelForView(this, mID);
8111            if (label != null) {
8112                info.setLabeledBy(label);
8113            }
8114
8115            if ((mAttachInfo.mAccessibilityFetchFlags
8116                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
8117                    && Resources.resourceHasPackage(mID)) {
8118                try {
8119                    String viewId = getResources().getResourceName(mID);
8120                    info.setViewIdResourceName(viewId);
8121                } catch (Resources.NotFoundException nfe) {
8122                    /* ignore */
8123                }
8124            }
8125        }
8126
8127        if (mLabelForId != View.NO_ID) {
8128            View rootView = getRootView();
8129            if (rootView == null) {
8130                rootView = this;
8131            }
8132            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
8133            if (labeled != null) {
8134                info.setLabelFor(labeled);
8135            }
8136        }
8137
8138        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
8139            View rootView = getRootView();
8140            if (rootView == null) {
8141                rootView = this;
8142            }
8143            View next = rootView.findViewInsideOutShouldExist(this,
8144                    mAccessibilityTraversalBeforeId);
8145            if (next != null && next.includeForAccessibility()) {
8146                info.setTraversalBefore(next);
8147            }
8148        }
8149
8150        if (mAccessibilityTraversalAfterId != View.NO_ID) {
8151            View rootView = getRootView();
8152            if (rootView == null) {
8153                rootView = this;
8154            }
8155            View next = rootView.findViewInsideOutShouldExist(this,
8156                    mAccessibilityTraversalAfterId);
8157            if (next != null && next.includeForAccessibility()) {
8158                info.setTraversalAfter(next);
8159            }
8160        }
8161
8162        info.setVisibleToUser(isVisibleToUser());
8163
8164        info.setImportantForAccessibility(isImportantForAccessibility());
8165        info.setPackageName(mContext.getPackageName());
8166        info.setClassName(getAccessibilityClassName());
8167        info.setContentDescription(getContentDescription());
8168
8169        info.setEnabled(isEnabled());
8170        info.setClickable(isClickable());
8171        info.setFocusable(isFocusable());
8172        info.setFocused(isFocused());
8173        info.setAccessibilityFocused(isAccessibilityFocused());
8174        info.setSelected(isSelected());
8175        info.setLongClickable(isLongClickable());
8176        info.setContextClickable(isContextClickable());
8177        info.setLiveRegion(getAccessibilityLiveRegion());
8178
8179        // TODO: These make sense only if we are in an AdapterView but all
8180        // views can be selected. Maybe from accessibility perspective
8181        // we should report as selectable view in an AdapterView.
8182        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8183        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8184
8185        if (isFocusable()) {
8186            if (isFocused()) {
8187                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8188            } else {
8189                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8190            }
8191        }
8192
8193        if (!isAccessibilityFocused()) {
8194            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8195        } else {
8196            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8197        }
8198
8199        if (isClickable() && isEnabled()) {
8200            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8201        }
8202
8203        if (isLongClickable() && isEnabled()) {
8204            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8205        }
8206
8207        if (isContextClickable() && isEnabled()) {
8208            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8209        }
8210
8211        CharSequence text = getIterableTextForAccessibility();
8212        if (text != null && text.length() > 0) {
8213            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8214
8215            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8216            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8217            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8218            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8219                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8220                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8221        }
8222
8223        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8224        populateAccessibilityNodeInfoDrawingOrderInParent(info);
8225    }
8226
8227    /**
8228     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8229     * additional data.
8230     * <p>
8231     * This method only needs overloading if the node is marked as having extra data available.
8232     * </p>
8233     *
8234     * @param info The info to which to add the extra data. Never {@code null}.
8235     * @param extraDataKey A key specifying the type of extra data to add to the info. The
8236     *                     extra data should be added to the {@link Bundle} returned by
8237     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8238     *                     {@code null}.
8239     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8240     *                  {@code null} if the service provided no arguments.
8241     *
8242     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8243     */
8244    public void addExtraDataToAccessibilityNodeInfo(
8245            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8246            @Nullable Bundle arguments) {
8247    }
8248
8249    /**
8250     * Determine the order in which this view will be drawn relative to its siblings for a11y
8251     *
8252     * @param info The info whose drawing order should be populated
8253     */
8254    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8255        /*
8256         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8257         * drawing order may not be well-defined, and some Views with custom drawing order may
8258         * not be initialized sufficiently to respond properly getChildDrawingOrder.
8259         */
8260        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8261            info.setDrawingOrder(0);
8262            return;
8263        }
8264        int drawingOrderInParent = 1;
8265        // Iterate up the hierarchy if parents are not important for a11y
8266        View viewAtDrawingLevel = this;
8267        final ViewParent parent = getParentForAccessibility();
8268        while (viewAtDrawingLevel != parent) {
8269            final ViewParent currentParent = viewAtDrawingLevel.getParent();
8270            if (!(currentParent instanceof ViewGroup)) {
8271                // Should only happen for the Decor
8272                drawingOrderInParent = 0;
8273                break;
8274            } else {
8275                final ViewGroup parentGroup = (ViewGroup) currentParent;
8276                final int childCount = parentGroup.getChildCount();
8277                if (childCount > 1) {
8278                    List<View> preorderedList = parentGroup.buildOrderedChildList();
8279                    if (preorderedList != null) {
8280                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8281                        for (int i = 0; i < childDrawIndex; i++) {
8282                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8283                        }
8284                    } else {
8285                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8286                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8287                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8288                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
8289                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8290                        if (childDrawIndex != 0) {
8291                            for (int i = 0; i < numChildrenToIterate; i++) {
8292                                final int otherDrawIndex = (customOrder ?
8293                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
8294                                if (otherDrawIndex < childDrawIndex) {
8295                                    drawingOrderInParent +=
8296                                            numViewsForAccessibility(parentGroup.getChildAt(i));
8297                                }
8298                            }
8299                        }
8300                    }
8301                }
8302            }
8303            viewAtDrawingLevel = (View) currentParent;
8304        }
8305        info.setDrawingOrder(drawingOrderInParent);
8306    }
8307
8308    private static int numViewsForAccessibility(View view) {
8309        if (view != null) {
8310            if (view.includeForAccessibility()) {
8311                return 1;
8312            } else if (view instanceof ViewGroup) {
8313                return ((ViewGroup) view).getNumChildrenForAccessibility();
8314            }
8315        }
8316        return 0;
8317    }
8318
8319    private View findLabelForView(View view, int labeledId) {
8320        if (mMatchLabelForPredicate == null) {
8321            mMatchLabelForPredicate = new MatchLabelForPredicate();
8322        }
8323        mMatchLabelForPredicate.mLabeledId = labeledId;
8324        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8325    }
8326
8327    /**
8328     * Computes whether this view is visible to the user. Such a view is
8329     * attached, visible, all its predecessors are visible, it is not clipped
8330     * entirely by its predecessors, and has an alpha greater than zero.
8331     *
8332     * @return Whether the view is visible on the screen.
8333     *
8334     * @hide
8335     */
8336    protected boolean isVisibleToUser() {
8337        return isVisibleToUser(null);
8338    }
8339
8340    /**
8341     * Computes whether the given portion of this view is visible to the user.
8342     * Such a view is attached, visible, all its predecessors are visible,
8343     * has an alpha greater than zero, and the specified portion is not
8344     * clipped entirely by its predecessors.
8345     *
8346     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8347     *                    <code>null</code>, and the entire view will be tested in this case.
8348     *                    When <code>true</code> is returned by the function, the actual visible
8349     *                    region will be stored in this parameter; that is, if boundInView is fully
8350     *                    contained within the view, no modification will be made, otherwise regions
8351     *                    outside of the visible area of the view will be clipped.
8352     *
8353     * @return Whether the specified portion of the view is visible on the screen.
8354     *
8355     * @hide
8356     */
8357    protected boolean isVisibleToUser(Rect boundInView) {
8358        if (mAttachInfo != null) {
8359            // Attached to invisible window means this view is not visible.
8360            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8361                return false;
8362            }
8363            // An invisible predecessor or one with alpha zero means
8364            // that this view is not visible to the user.
8365            Object current = this;
8366            while (current instanceof View) {
8367                View view = (View) current;
8368                // We have attach info so this view is attached and there is no
8369                // need to check whether we reach to ViewRootImpl on the way up.
8370                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8371                        view.getVisibility() != VISIBLE) {
8372                    return false;
8373                }
8374                current = view.mParent;
8375            }
8376            // Check if the view is entirely covered by its predecessors.
8377            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8378            Point offset = mAttachInfo.mPoint;
8379            if (!getGlobalVisibleRect(visibleRect, offset)) {
8380                return false;
8381            }
8382            // Check if the visible portion intersects the rectangle of interest.
8383            if (boundInView != null) {
8384                visibleRect.offset(-offset.x, -offset.y);
8385                return boundInView.intersect(visibleRect);
8386            }
8387            return true;
8388        }
8389        return false;
8390    }
8391
8392    /**
8393     * Returns the delegate for implementing accessibility support via
8394     * composition. For more details see {@link AccessibilityDelegate}.
8395     *
8396     * @return The delegate, or null if none set.
8397     *
8398     * @hide
8399     */
8400    public AccessibilityDelegate getAccessibilityDelegate() {
8401        return mAccessibilityDelegate;
8402    }
8403
8404    /**
8405     * Sets a delegate for implementing accessibility support via composition
8406     * (as opposed to inheritance). For more details, see
8407     * {@link AccessibilityDelegate}.
8408     * <p>
8409     * <strong>Note:</strong> On platform versions prior to
8410     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8411     * views in the {@code android.widget.*} package are called <i>before</i>
8412     * host methods. This prevents certain properties such as class name from
8413     * being modified by overriding
8414     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8415     * as any changes will be overwritten by the host class.
8416     * <p>
8417     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8418     * methods are called <i>after</i> host methods, which all properties to be
8419     * modified without being overwritten by the host class.
8420     *
8421     * @param delegate the object to which accessibility method calls should be
8422     *                 delegated
8423     * @see AccessibilityDelegate
8424     */
8425    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8426        mAccessibilityDelegate = delegate;
8427    }
8428
8429    /**
8430     * Gets the provider for managing a virtual view hierarchy rooted at this View
8431     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8432     * that explore the window content.
8433     * <p>
8434     * If this method returns an instance, this instance is responsible for managing
8435     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8436     * View including the one representing the View itself. Similarly the returned
8437     * instance is responsible for performing accessibility actions on any virtual
8438     * view or the root view itself.
8439     * </p>
8440     * <p>
8441     * If an {@link AccessibilityDelegate} has been specified via calling
8442     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8443     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8444     * is responsible for handling this call.
8445     * </p>
8446     *
8447     * @return The provider.
8448     *
8449     * @see AccessibilityNodeProvider
8450     */
8451    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8452        if (mAccessibilityDelegate != null) {
8453            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8454        } else {
8455            return null;
8456        }
8457    }
8458
8459    /**
8460     * Gets the unique identifier of this view on the screen for accessibility purposes.
8461     *
8462     * @return The view accessibility id.
8463     *
8464     * @hide
8465     */
8466    public int getAccessibilityViewId() {
8467        if (mAccessibilityViewId == NO_ID) {
8468            mAccessibilityViewId = mContext.getNextAccessibilityId();
8469        }
8470        return mAccessibilityViewId;
8471    }
8472
8473    /**
8474     * Gets the unique identifier of the window in which this View reseides.
8475     *
8476     * @return The window accessibility id.
8477     *
8478     * @hide
8479     */
8480    public int getAccessibilityWindowId() {
8481        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8482                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8483    }
8484
8485    /**
8486     * Returns the {@link View}'s content description.
8487     * <p>
8488     * <strong>Note:</strong> Do not override this method, as it will have no
8489     * effect on the content description presented to accessibility services.
8490     * You must call {@link #setContentDescription(CharSequence)} to modify the
8491     * content description.
8492     *
8493     * @return the content description
8494     * @see #setContentDescription(CharSequence)
8495     * @attr ref android.R.styleable#View_contentDescription
8496     */
8497    @ViewDebug.ExportedProperty(category = "accessibility")
8498    public CharSequence getContentDescription() {
8499        return mContentDescription;
8500    }
8501
8502    /**
8503     * Sets the {@link View}'s content description.
8504     * <p>
8505     * A content description briefly describes the view and is primarily used
8506     * for accessibility support to determine how a view should be presented to
8507     * the user. In the case of a view with no textual representation, such as
8508     * {@link android.widget.ImageButton}, a useful content description
8509     * explains what the view does. For example, an image button with a phone
8510     * icon that is used to place a call may use "Call" as its content
8511     * description. An image of a floppy disk that is used to save a file may
8512     * use "Save".
8513     *
8514     * @param contentDescription The content description.
8515     * @see #getContentDescription()
8516     * @attr ref android.R.styleable#View_contentDescription
8517     */
8518    @RemotableViewMethod
8519    public void setContentDescription(CharSequence contentDescription) {
8520        if (mContentDescription == null) {
8521            if (contentDescription == null) {
8522                return;
8523            }
8524        } else if (mContentDescription.equals(contentDescription)) {
8525            return;
8526        }
8527        mContentDescription = contentDescription;
8528        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8529        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8530            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8531            notifySubtreeAccessibilityStateChangedIfNeeded();
8532        } else {
8533            notifyViewAccessibilityStateChangedIfNeeded(
8534                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8535        }
8536    }
8537
8538    /**
8539     * Sets the id of a view before which this one is visited in accessibility traversal.
8540     * A screen-reader must visit the content of this view before the content of the one
8541     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8542     * will traverse the entire content of B before traversing the entire content of A,
8543     * regardles of what traversal strategy it is using.
8544     * <p>
8545     * Views that do not have specified before/after relationships are traversed in order
8546     * determined by the screen-reader.
8547     * </p>
8548     * <p>
8549     * Setting that this view is before a view that is not important for accessibility
8550     * or if this view is not important for accessibility will have no effect as the
8551     * screen-reader is not aware of unimportant views.
8552     * </p>
8553     *
8554     * @param beforeId The id of a view this one precedes in accessibility traversal.
8555     *
8556     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8557     *
8558     * @see #setImportantForAccessibility(int)
8559     */
8560    @RemotableViewMethod
8561    public void setAccessibilityTraversalBefore(int beforeId) {
8562        if (mAccessibilityTraversalBeforeId == beforeId) {
8563            return;
8564        }
8565        mAccessibilityTraversalBeforeId = beforeId;
8566        notifyViewAccessibilityStateChangedIfNeeded(
8567                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8568    }
8569
8570    /**
8571     * Gets the id of a view before which this one is visited in accessibility traversal.
8572     *
8573     * @return The id of a view this one precedes in accessibility traversal if
8574     *         specified, otherwise {@link #NO_ID}.
8575     *
8576     * @see #setAccessibilityTraversalBefore(int)
8577     */
8578    public int getAccessibilityTraversalBefore() {
8579        return mAccessibilityTraversalBeforeId;
8580    }
8581
8582    /**
8583     * Sets the id of a view after which this one is visited in accessibility traversal.
8584     * A screen-reader must visit the content of the other view before the content of this
8585     * one. For example, if view B is set to be after view A, then a screen-reader
8586     * will traverse the entire content of A before traversing the entire content of B,
8587     * regardles of what traversal strategy it is using.
8588     * <p>
8589     * Views that do not have specified before/after relationships are traversed in order
8590     * determined by the screen-reader.
8591     * </p>
8592     * <p>
8593     * Setting that this view is after a view that is not important for accessibility
8594     * or if this view is not important for accessibility will have no effect as the
8595     * screen-reader is not aware of unimportant views.
8596     * </p>
8597     *
8598     * @param afterId The id of a view this one succedees in accessibility traversal.
8599     *
8600     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8601     *
8602     * @see #setImportantForAccessibility(int)
8603     */
8604    @RemotableViewMethod
8605    public void setAccessibilityTraversalAfter(int afterId) {
8606        if (mAccessibilityTraversalAfterId == afterId) {
8607            return;
8608        }
8609        mAccessibilityTraversalAfterId = afterId;
8610        notifyViewAccessibilityStateChangedIfNeeded(
8611                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8612    }
8613
8614    /**
8615     * Gets the id of a view after which this one is visited in accessibility traversal.
8616     *
8617     * @return The id of a view this one succeedes in accessibility traversal if
8618     *         specified, otherwise {@link #NO_ID}.
8619     *
8620     * @see #setAccessibilityTraversalAfter(int)
8621     */
8622    public int getAccessibilityTraversalAfter() {
8623        return mAccessibilityTraversalAfterId;
8624    }
8625
8626    /**
8627     * Gets the id of a view for which this view serves as a label for
8628     * accessibility purposes.
8629     *
8630     * @return The labeled view id.
8631     */
8632    @ViewDebug.ExportedProperty(category = "accessibility")
8633    public int getLabelFor() {
8634        return mLabelForId;
8635    }
8636
8637    /**
8638     * Sets the id of a view for which this view serves as a label for
8639     * accessibility purposes.
8640     *
8641     * @param id The labeled view id.
8642     */
8643    @RemotableViewMethod
8644    public void setLabelFor(@IdRes int id) {
8645        if (mLabelForId == id) {
8646            return;
8647        }
8648        mLabelForId = id;
8649        if (mLabelForId != View.NO_ID
8650                && mID == View.NO_ID) {
8651            mID = generateViewId();
8652        }
8653        notifyViewAccessibilityStateChangedIfNeeded(
8654                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8655    }
8656
8657    /**
8658     * Invoked whenever this view loses focus, either by losing window focus or by losing
8659     * focus within its window. This method can be used to clear any state tied to the
8660     * focus. For instance, if a button is held pressed with the trackball and the window
8661     * loses focus, this method can be used to cancel the press.
8662     *
8663     * Subclasses of View overriding this method should always call super.onFocusLost().
8664     *
8665     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8666     * @see #onWindowFocusChanged(boolean)
8667     *
8668     * @hide pending API council approval
8669     */
8670    @CallSuper
8671    protected void onFocusLost() {
8672        resetPressedState();
8673    }
8674
8675    private void resetPressedState() {
8676        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8677            return;
8678        }
8679
8680        if (isPressed()) {
8681            setPressed(false);
8682
8683            if (!mHasPerformedLongPress) {
8684                removeLongPressCallback();
8685            }
8686        }
8687    }
8688
8689    /**
8690     * Returns true if this view has focus
8691     *
8692     * @return True if this view has focus, false otherwise.
8693     */
8694    @ViewDebug.ExportedProperty(category = "focus")
8695    public boolean isFocused() {
8696        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8697    }
8698
8699    /**
8700     * Find the view in the hierarchy rooted at this view that currently has
8701     * focus.
8702     *
8703     * @return The view that currently has focus, or null if no focused view can
8704     *         be found.
8705     */
8706    public View findFocus() {
8707        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8708    }
8709
8710    /**
8711     * Indicates whether this view is one of the set of scrollable containers in
8712     * its window.
8713     *
8714     * @return whether this view is one of the set of scrollable containers in
8715     * its window
8716     *
8717     * @attr ref android.R.styleable#View_isScrollContainer
8718     */
8719    public boolean isScrollContainer() {
8720        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8721    }
8722
8723    /**
8724     * Change whether this view is one of the set of scrollable containers in
8725     * its window.  This will be used to determine whether the window can
8726     * resize or must pan when a soft input area is open -- scrollable
8727     * containers allow the window to use resize mode since the container
8728     * will appropriately shrink.
8729     *
8730     * @attr ref android.R.styleable#View_isScrollContainer
8731     */
8732    public void setScrollContainer(boolean isScrollContainer) {
8733        if (isScrollContainer) {
8734            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8735                mAttachInfo.mScrollContainers.add(this);
8736                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8737            }
8738            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8739        } else {
8740            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8741                mAttachInfo.mScrollContainers.remove(this);
8742            }
8743            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8744        }
8745    }
8746
8747    /**
8748     * Returns the quality of the drawing cache.
8749     *
8750     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8751     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8752     *
8753     * @see #setDrawingCacheQuality(int)
8754     * @see #setDrawingCacheEnabled(boolean)
8755     * @see #isDrawingCacheEnabled()
8756     *
8757     * @attr ref android.R.styleable#View_drawingCacheQuality
8758     */
8759    @DrawingCacheQuality
8760    public int getDrawingCacheQuality() {
8761        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8762    }
8763
8764    /**
8765     * Set the drawing cache quality of this view. This value is used only when the
8766     * drawing cache is enabled
8767     *
8768     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8769     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8770     *
8771     * @see #getDrawingCacheQuality()
8772     * @see #setDrawingCacheEnabled(boolean)
8773     * @see #isDrawingCacheEnabled()
8774     *
8775     * @attr ref android.R.styleable#View_drawingCacheQuality
8776     */
8777    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8778        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8779    }
8780
8781    /**
8782     * Returns whether the screen should remain on, corresponding to the current
8783     * value of {@link #KEEP_SCREEN_ON}.
8784     *
8785     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8786     *
8787     * @see #setKeepScreenOn(boolean)
8788     *
8789     * @attr ref android.R.styleable#View_keepScreenOn
8790     */
8791    public boolean getKeepScreenOn() {
8792        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8793    }
8794
8795    /**
8796     * Controls whether the screen should remain on, modifying the
8797     * value of {@link #KEEP_SCREEN_ON}.
8798     *
8799     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8800     *
8801     * @see #getKeepScreenOn()
8802     *
8803     * @attr ref android.R.styleable#View_keepScreenOn
8804     */
8805    public void setKeepScreenOn(boolean keepScreenOn) {
8806        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8807    }
8808
8809    /**
8810     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8811     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8812     *
8813     * @attr ref android.R.styleable#View_nextFocusLeft
8814     */
8815    public int getNextFocusLeftId() {
8816        return mNextFocusLeftId;
8817    }
8818
8819    /**
8820     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8821     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8822     * decide automatically.
8823     *
8824     * @attr ref android.R.styleable#View_nextFocusLeft
8825     */
8826    public void setNextFocusLeftId(int nextFocusLeftId) {
8827        mNextFocusLeftId = nextFocusLeftId;
8828    }
8829
8830    /**
8831     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8832     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8833     *
8834     * @attr ref android.R.styleable#View_nextFocusRight
8835     */
8836    public int getNextFocusRightId() {
8837        return mNextFocusRightId;
8838    }
8839
8840    /**
8841     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8842     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8843     * decide automatically.
8844     *
8845     * @attr ref android.R.styleable#View_nextFocusRight
8846     */
8847    public void setNextFocusRightId(int nextFocusRightId) {
8848        mNextFocusRightId = nextFocusRightId;
8849    }
8850
8851    /**
8852     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8853     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8854     *
8855     * @attr ref android.R.styleable#View_nextFocusUp
8856     */
8857    public int getNextFocusUpId() {
8858        return mNextFocusUpId;
8859    }
8860
8861    /**
8862     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8863     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8864     * decide automatically.
8865     *
8866     * @attr ref android.R.styleable#View_nextFocusUp
8867     */
8868    public void setNextFocusUpId(int nextFocusUpId) {
8869        mNextFocusUpId = nextFocusUpId;
8870    }
8871
8872    /**
8873     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8874     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8875     *
8876     * @attr ref android.R.styleable#View_nextFocusDown
8877     */
8878    public int getNextFocusDownId() {
8879        return mNextFocusDownId;
8880    }
8881
8882    /**
8883     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8884     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8885     * decide automatically.
8886     *
8887     * @attr ref android.R.styleable#View_nextFocusDown
8888     */
8889    public void setNextFocusDownId(int nextFocusDownId) {
8890        mNextFocusDownId = nextFocusDownId;
8891    }
8892
8893    /**
8894     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8895     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8896     *
8897     * @attr ref android.R.styleable#View_nextFocusForward
8898     */
8899    public int getNextFocusForwardId() {
8900        return mNextFocusForwardId;
8901    }
8902
8903    /**
8904     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8905     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8906     * decide automatically.
8907     *
8908     * @attr ref android.R.styleable#View_nextFocusForward
8909     */
8910    public void setNextFocusForwardId(int nextFocusForwardId) {
8911        mNextFocusForwardId = nextFocusForwardId;
8912    }
8913
8914    /**
8915     * Gets the id of the root of the next keyboard navigation cluster.
8916     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8917     * decide automatically.
8918     *
8919     * @attr ref android.R.styleable#View_nextClusterForward
8920     */
8921    public int getNextClusterForwardId() {
8922        return mNextClusterForwardId;
8923    }
8924
8925    /**
8926     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8927     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8928     * decide automatically.
8929     *
8930     * @attr ref android.R.styleable#View_nextClusterForward
8931     */
8932    public void setNextClusterForwardId(int nextClusterForwardId) {
8933        mNextClusterForwardId = nextClusterForwardId;
8934    }
8935
8936    /**
8937     * Returns the visibility of this view and all of its ancestors
8938     *
8939     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8940     */
8941    public boolean isShown() {
8942        View current = this;
8943        //noinspection ConstantConditions
8944        do {
8945            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8946                return false;
8947            }
8948            ViewParent parent = current.mParent;
8949            if (parent == null) {
8950                return false; // We are not attached to the view root
8951            }
8952            if (!(parent instanceof View)) {
8953                return true;
8954            }
8955            current = (View) parent;
8956        } while (current != null);
8957
8958        return false;
8959    }
8960
8961    /**
8962     * Called by the view hierarchy when the content insets for a window have
8963     * changed, to allow it to adjust its content to fit within those windows.
8964     * The content insets tell you the space that the status bar, input method,
8965     * and other system windows infringe on the application's window.
8966     *
8967     * <p>You do not normally need to deal with this function, since the default
8968     * window decoration given to applications takes care of applying it to the
8969     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8970     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8971     * and your content can be placed under those system elements.  You can then
8972     * use this method within your view hierarchy if you have parts of your UI
8973     * which you would like to ensure are not being covered.
8974     *
8975     * <p>The default implementation of this method simply applies the content
8976     * insets to the view's padding, consuming that content (modifying the
8977     * insets to be 0), and returning true.  This behavior is off by default, but can
8978     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8979     *
8980     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8981     * insets object is propagated down the hierarchy, so any changes made to it will
8982     * be seen by all following views (including potentially ones above in
8983     * the hierarchy since this is a depth-first traversal).  The first view
8984     * that returns true will abort the entire traversal.
8985     *
8986     * <p>The default implementation works well for a situation where it is
8987     * used with a container that covers the entire window, allowing it to
8988     * apply the appropriate insets to its content on all edges.  If you need
8989     * a more complicated layout (such as two different views fitting system
8990     * windows, one on the top of the window, and one on the bottom),
8991     * you can override the method and handle the insets however you would like.
8992     * Note that the insets provided by the framework are always relative to the
8993     * far edges of the window, not accounting for the location of the called view
8994     * within that window.  (In fact when this method is called you do not yet know
8995     * where the layout will place the view, as it is done before layout happens.)
8996     *
8997     * <p>Note: unlike many View methods, there is no dispatch phase to this
8998     * call.  If you are overriding it in a ViewGroup and want to allow the
8999     * call to continue to your children, you must be sure to call the super
9000     * implementation.
9001     *
9002     * <p>Here is a sample layout that makes use of fitting system windows
9003     * to have controls for a video view placed inside of the window decorations
9004     * that it hides and shows.  This can be used with code like the second
9005     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
9006     *
9007     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
9008     *
9009     * @param insets Current content insets of the window.  Prior to
9010     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
9011     * the insets or else you and Android will be unhappy.
9012     *
9013     * @return {@code true} if this view applied the insets and it should not
9014     * continue propagating further down the hierarchy, {@code false} otherwise.
9015     * @see #getFitsSystemWindows()
9016     * @see #setFitsSystemWindows(boolean)
9017     * @see #setSystemUiVisibility(int)
9018     *
9019     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
9020     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
9021     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
9022     * to implement handling their own insets.
9023     */
9024    @Deprecated
9025    protected boolean fitSystemWindows(Rect insets) {
9026        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
9027            if (insets == null) {
9028                // Null insets by definition have already been consumed.
9029                // This call cannot apply insets since there are none to apply,
9030                // so return false.
9031                return false;
9032            }
9033            // If we're not in the process of dispatching the newer apply insets call,
9034            // that means we're not in the compatibility path. Dispatch into the newer
9035            // apply insets path and take things from there.
9036            try {
9037                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
9038                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
9039            } finally {
9040                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
9041            }
9042        } else {
9043            // We're being called from the newer apply insets path.
9044            // Perform the standard fallback behavior.
9045            return fitSystemWindowsInt(insets);
9046        }
9047    }
9048
9049    private boolean fitSystemWindowsInt(Rect insets) {
9050        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
9051            mUserPaddingStart = UNDEFINED_PADDING;
9052            mUserPaddingEnd = UNDEFINED_PADDING;
9053            Rect localInsets = sThreadLocal.get();
9054            if (localInsets == null) {
9055                localInsets = new Rect();
9056                sThreadLocal.set(localInsets);
9057            }
9058            boolean res = computeFitSystemWindows(insets, localInsets);
9059            mUserPaddingLeftInitial = localInsets.left;
9060            mUserPaddingRightInitial = localInsets.right;
9061            internalSetPadding(localInsets.left, localInsets.top,
9062                    localInsets.right, localInsets.bottom);
9063            return res;
9064        }
9065        return false;
9066    }
9067
9068    /**
9069     * Called when the view should apply {@link WindowInsets} according to its internal policy.
9070     *
9071     * <p>This method should be overridden by views that wish to apply a policy different from or
9072     * in addition to the default behavior. Clients that wish to force a view subtree
9073     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
9074     *
9075     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
9076     * it will be called during dispatch instead of this method. The listener may optionally
9077     * call this method from its own implementation if it wishes to apply the view's default
9078     * insets policy in addition to its own.</p>
9079     *
9080     * <p>Implementations of this method should either return the insets parameter unchanged
9081     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
9082     * that this view applied itself. This allows new inset types added in future platform
9083     * versions to pass through existing implementations unchanged without being erroneously
9084     * consumed.</p>
9085     *
9086     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
9087     * property is set then the view will consume the system window insets and apply them
9088     * as padding for the view.</p>
9089     *
9090     * @param insets Insets to apply
9091     * @return The supplied insets with any applied insets consumed
9092     */
9093    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
9094        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
9095            // We weren't called from within a direct call to fitSystemWindows,
9096            // call into it as a fallback in case we're in a class that overrides it
9097            // and has logic to perform.
9098            if (fitSystemWindows(insets.getSystemWindowInsets())) {
9099                return insets.consumeSystemWindowInsets();
9100            }
9101        } else {
9102            // We were called from within a direct call to fitSystemWindows.
9103            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
9104                return insets.consumeSystemWindowInsets();
9105            }
9106        }
9107        return insets;
9108    }
9109
9110    /**
9111     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
9112     * window insets to this view. The listener's
9113     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
9114     * method will be called instead of the view's
9115     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
9116     *
9117     * @param listener Listener to set
9118     *
9119     * @see #onApplyWindowInsets(WindowInsets)
9120     */
9121    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
9122        getListenerInfo().mOnApplyWindowInsetsListener = listener;
9123    }
9124
9125    /**
9126     * Request to apply the given window insets to this view or another view in its subtree.
9127     *
9128     * <p>This method should be called by clients wishing to apply insets corresponding to areas
9129     * obscured by window decorations or overlays. This can include the status and navigation bars,
9130     * action bars, input methods and more. New inset categories may be added in the future.
9131     * The method returns the insets provided minus any that were applied by this view or its
9132     * children.</p>
9133     *
9134     * <p>Clients wishing to provide custom behavior should override the
9135     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
9136     * {@link OnApplyWindowInsetsListener} via the
9137     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
9138     * method.</p>
9139     *
9140     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
9141     * </p>
9142     *
9143     * @param insets Insets to apply
9144     * @return The provided insets minus the insets that were consumed
9145     */
9146    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
9147        try {
9148            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
9149            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
9150                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
9151            } else {
9152                return onApplyWindowInsets(insets);
9153            }
9154        } finally {
9155            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9156        }
9157    }
9158
9159    /**
9160     * Compute the view's coordinate within the surface.
9161     *
9162     * <p>Computes the coordinates of this view in its surface. The argument
9163     * must be an array of two integers. After the method returns, the array
9164     * contains the x and y location in that order.</p>
9165     * @hide
9166     * @param location an array of two integers in which to hold the coordinates
9167     */
9168    public void getLocationInSurface(@Size(2) int[] location) {
9169        getLocationInWindow(location);
9170        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9171            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9172            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9173        }
9174    }
9175
9176    /**
9177     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9178     * only available if the view is attached.
9179     *
9180     * @return WindowInsets from the top of the view hierarchy or null if View is detached
9181     */
9182    public WindowInsets getRootWindowInsets() {
9183        if (mAttachInfo != null) {
9184            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9185        }
9186        return null;
9187    }
9188
9189    /**
9190     * @hide Compute the insets that should be consumed by this view and the ones
9191     * that should propagate to those under it.
9192     */
9193    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9194        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9195                || mAttachInfo == null
9196                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9197                        && !mAttachInfo.mOverscanRequested)) {
9198            outLocalInsets.set(inoutInsets);
9199            inoutInsets.set(0, 0, 0, 0);
9200            return true;
9201        } else {
9202            // The application wants to take care of fitting system window for
9203            // the content...  however we still need to take care of any overscan here.
9204            final Rect overscan = mAttachInfo.mOverscanInsets;
9205            outLocalInsets.set(overscan);
9206            inoutInsets.left -= overscan.left;
9207            inoutInsets.top -= overscan.top;
9208            inoutInsets.right -= overscan.right;
9209            inoutInsets.bottom -= overscan.bottom;
9210            return false;
9211        }
9212    }
9213
9214    /**
9215     * Compute insets that should be consumed by this view and the ones that should propagate
9216     * to those under it.
9217     *
9218     * @param in Insets currently being processed by this View, likely received as a parameter
9219     *           to {@link #onApplyWindowInsets(WindowInsets)}.
9220     * @param outLocalInsets A Rect that will receive the insets that should be consumed
9221     *                       by this view
9222     * @return Insets that should be passed along to views under this one
9223     */
9224    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9225        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9226                || mAttachInfo == null
9227                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
9228            outLocalInsets.set(in.getSystemWindowInsets());
9229            return in.consumeSystemWindowInsets();
9230        } else {
9231            outLocalInsets.set(0, 0, 0, 0);
9232            return in;
9233        }
9234    }
9235
9236    /**
9237     * Sets whether or not this view should account for system screen decorations
9238     * such as the status bar and inset its content; that is, controlling whether
9239     * the default implementation of {@link #fitSystemWindows(Rect)} will be
9240     * executed.  See that method for more details.
9241     *
9242     * <p>Note that if you are providing your own implementation of
9243     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9244     * flag to true -- your implementation will be overriding the default
9245     * implementation that checks this flag.
9246     *
9247     * @param fitSystemWindows If true, then the default implementation of
9248     * {@link #fitSystemWindows(Rect)} will be executed.
9249     *
9250     * @attr ref android.R.styleable#View_fitsSystemWindows
9251     * @see #getFitsSystemWindows()
9252     * @see #fitSystemWindows(Rect)
9253     * @see #setSystemUiVisibility(int)
9254     */
9255    public void setFitsSystemWindows(boolean fitSystemWindows) {
9256        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9257    }
9258
9259    /**
9260     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9261     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9262     * will be executed.
9263     *
9264     * @return {@code true} if the default implementation of
9265     * {@link #fitSystemWindows(Rect)} will be executed.
9266     *
9267     * @attr ref android.R.styleable#View_fitsSystemWindows
9268     * @see #setFitsSystemWindows(boolean)
9269     * @see #fitSystemWindows(Rect)
9270     * @see #setSystemUiVisibility(int)
9271     */
9272    @ViewDebug.ExportedProperty
9273    public boolean getFitsSystemWindows() {
9274        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9275    }
9276
9277    /** @hide */
9278    public boolean fitsSystemWindows() {
9279        return getFitsSystemWindows();
9280    }
9281
9282    /**
9283     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9284     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9285     */
9286    @Deprecated
9287    public void requestFitSystemWindows() {
9288        if (mParent != null) {
9289            mParent.requestFitSystemWindows();
9290        }
9291    }
9292
9293    /**
9294     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9295     */
9296    public void requestApplyInsets() {
9297        requestFitSystemWindows();
9298    }
9299
9300    /**
9301     * For use by PhoneWindow to make its own system window fitting optional.
9302     * @hide
9303     */
9304    public void makeOptionalFitsSystemWindows() {
9305        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9306    }
9307
9308    /**
9309     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9310     * treat them as such.
9311     * @hide
9312     */
9313    public void getOutsets(Rect outOutsetRect) {
9314        if (mAttachInfo != null) {
9315            outOutsetRect.set(mAttachInfo.mOutsets);
9316        } else {
9317            outOutsetRect.setEmpty();
9318        }
9319    }
9320
9321    /**
9322     * Returns the visibility status for this view.
9323     *
9324     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9325     * @attr ref android.R.styleable#View_visibility
9326     */
9327    @ViewDebug.ExportedProperty(mapping = {
9328        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9329        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9330        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9331    })
9332    @Visibility
9333    public int getVisibility() {
9334        return mViewFlags & VISIBILITY_MASK;
9335    }
9336
9337    /**
9338     * Set the visibility state of this view.
9339     *
9340     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9341     * @attr ref android.R.styleable#View_visibility
9342     */
9343    @RemotableViewMethod
9344    public void setVisibility(@Visibility int visibility) {
9345        setFlags(visibility, VISIBILITY_MASK);
9346    }
9347
9348    /**
9349     * Returns the enabled status for this view. The interpretation of the
9350     * enabled state varies by subclass.
9351     *
9352     * @return True if this view is enabled, false otherwise.
9353     */
9354    @ViewDebug.ExportedProperty
9355    public boolean isEnabled() {
9356        return (mViewFlags & ENABLED_MASK) == ENABLED;
9357    }
9358
9359    /**
9360     * Set the enabled state of this view. The interpretation of the enabled
9361     * state varies by subclass.
9362     *
9363     * @param enabled True if this view is enabled, false otherwise.
9364     */
9365    @RemotableViewMethod
9366    public void setEnabled(boolean enabled) {
9367        if (enabled == isEnabled()) return;
9368
9369        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9370
9371        /*
9372         * The View most likely has to change its appearance, so refresh
9373         * the drawable state.
9374         */
9375        refreshDrawableState();
9376
9377        // Invalidate too, since the default behavior for views is to be
9378        // be drawn at 50% alpha rather than to change the drawable.
9379        invalidate(true);
9380
9381        if (!enabled) {
9382            cancelPendingInputEvents();
9383        }
9384    }
9385
9386    /**
9387     * Set whether this view can receive the focus.
9388     * <p>
9389     * Setting this to false will also ensure that this view is not focusable
9390     * in touch mode.
9391     *
9392     * @param focusable If true, this view can receive the focus.
9393     *
9394     * @see #setFocusableInTouchMode(boolean)
9395     * @see #setFocusable(int)
9396     * @attr ref android.R.styleable#View_focusable
9397     */
9398    public void setFocusable(boolean focusable) {
9399        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9400    }
9401
9402    /**
9403     * Sets whether this view can receive focus.
9404     * <p>
9405     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9406     * automatically based on the view's interactivity. This is the default.
9407     * <p>
9408     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9409     * in touch mode.
9410     *
9411     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9412     *                  or {@link #FOCUSABLE_AUTO}.
9413     * @see #setFocusableInTouchMode(boolean)
9414     * @attr ref android.R.styleable#View_focusable
9415     */
9416    public void setFocusable(@Focusable int focusable) {
9417        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9418            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9419        }
9420        setFlags(focusable, FOCUSABLE_MASK);
9421    }
9422
9423    /**
9424     * Set whether this view can receive focus while in touch mode.
9425     *
9426     * Setting this to true will also ensure that this view is focusable.
9427     *
9428     * @param focusableInTouchMode If true, this view can receive the focus while
9429     *   in touch mode.
9430     *
9431     * @see #setFocusable(boolean)
9432     * @attr ref android.R.styleable#View_focusableInTouchMode
9433     */
9434    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9435        // Focusable in touch mode should always be set before the focusable flag
9436        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9437        // which, in touch mode, will not successfully request focus on this view
9438        // because the focusable in touch mode flag is not set
9439        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9440
9441        // Clear FOCUSABLE_AUTO if set.
9442        if (focusableInTouchMode) {
9443            // Clears FOCUSABLE_AUTO if set.
9444            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9445        }
9446    }
9447
9448    /**
9449     * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
9450     * to autofill the view with the user's data.
9451     *
9452     * <p>Typically, there is only one way to autofill a view, but there could be more than one.
9453     * For example, if the application accepts either an username or email address to identify
9454     * an user.
9455     *
9456     * <p>These hints are not validated by the Android System, but passed "as is" to the service.
9457     * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
9458     * constants such as:
9459     * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
9460     * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
9461     * {@link #AUTOFILL_HINT_NAME},
9462     * {@link #AUTOFILL_HINT_PHONE},
9463     * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
9464     * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
9465     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
9466     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
9467     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
9468     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
9469     *
9470     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9471     * @attr ref android.R.styleable#View_autofillHints
9472     */
9473    public void setAutofillHints(@Nullable String... autofillHints) {
9474        if (autofillHints == null || autofillHints.length == 0) {
9475            mAutofillHints = null;
9476        } else {
9477            mAutofillHints = autofillHints;
9478        }
9479    }
9480
9481    /**
9482     * @hide
9483     */
9484    @TestApi
9485    public void setAutofilled(boolean isAutofilled) {
9486        boolean wasChanged = isAutofilled != isAutofilled();
9487
9488        if (wasChanged) {
9489            if (isAutofilled) {
9490                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9491            } else {
9492                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9493            }
9494
9495            invalidate();
9496        }
9497    }
9498
9499    /**
9500     * Set whether this view should have sound effects enabled for events such as
9501     * clicking and touching.
9502     *
9503     * <p>You may wish to disable sound effects for a view if you already play sounds,
9504     * for instance, a dial key that plays dtmf tones.
9505     *
9506     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9507     * @see #isSoundEffectsEnabled()
9508     * @see #playSoundEffect(int)
9509     * @attr ref android.R.styleable#View_soundEffectsEnabled
9510     */
9511    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9512        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9513    }
9514
9515    /**
9516     * @return whether this view should have sound effects enabled for events such as
9517     *     clicking and touching.
9518     *
9519     * @see #setSoundEffectsEnabled(boolean)
9520     * @see #playSoundEffect(int)
9521     * @attr ref android.R.styleable#View_soundEffectsEnabled
9522     */
9523    @ViewDebug.ExportedProperty
9524    public boolean isSoundEffectsEnabled() {
9525        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9526    }
9527
9528    /**
9529     * Set whether this view should have haptic feedback for events such as
9530     * long presses.
9531     *
9532     * <p>You may wish to disable haptic feedback if your view already controls
9533     * its own haptic feedback.
9534     *
9535     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9536     * @see #isHapticFeedbackEnabled()
9537     * @see #performHapticFeedback(int)
9538     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9539     */
9540    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9541        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9542    }
9543
9544    /**
9545     * @return whether this view should have haptic feedback enabled for events
9546     * long presses.
9547     *
9548     * @see #setHapticFeedbackEnabled(boolean)
9549     * @see #performHapticFeedback(int)
9550     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9551     */
9552    @ViewDebug.ExportedProperty
9553    public boolean isHapticFeedbackEnabled() {
9554        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9555    }
9556
9557    /**
9558     * Returns the layout direction for this view.
9559     *
9560     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9561     *   {@link #LAYOUT_DIRECTION_RTL},
9562     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9563     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9564     *
9565     * @attr ref android.R.styleable#View_layoutDirection
9566     *
9567     * @hide
9568     */
9569    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9570        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9571        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9572        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9573        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9574    })
9575    @LayoutDir
9576    public int getRawLayoutDirection() {
9577        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9578    }
9579
9580    /**
9581     * Set the layout direction for this view. This will propagate a reset of layout direction
9582     * resolution to the view's children and resolve layout direction for this view.
9583     *
9584     * @param layoutDirection the layout direction to set. Should be one of:
9585     *
9586     * {@link #LAYOUT_DIRECTION_LTR},
9587     * {@link #LAYOUT_DIRECTION_RTL},
9588     * {@link #LAYOUT_DIRECTION_INHERIT},
9589     * {@link #LAYOUT_DIRECTION_LOCALE}.
9590     *
9591     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9592     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9593     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9594     *
9595     * @attr ref android.R.styleable#View_layoutDirection
9596     */
9597    @RemotableViewMethod
9598    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9599        if (getRawLayoutDirection() != layoutDirection) {
9600            // Reset the current layout direction and the resolved one
9601            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9602            resetRtlProperties();
9603            // Set the new layout direction (filtered)
9604            mPrivateFlags2 |=
9605                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9606            // We need to resolve all RTL properties as they all depend on layout direction
9607            resolveRtlPropertiesIfNeeded();
9608            requestLayout();
9609            invalidate(true);
9610        }
9611    }
9612
9613    /**
9614     * Returns the resolved layout direction for this view.
9615     *
9616     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9617     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9618     *
9619     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9620     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9621     *
9622     * @attr ref android.R.styleable#View_layoutDirection
9623     */
9624    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9625        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9626        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9627    })
9628    @ResolvedLayoutDir
9629    public int getLayoutDirection() {
9630        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9631        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9632            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9633            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9634        }
9635        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9636                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9637    }
9638
9639    /**
9640     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9641     * layout attribute and/or the inherited value from the parent
9642     *
9643     * @return true if the layout is right-to-left.
9644     *
9645     * @hide
9646     */
9647    @ViewDebug.ExportedProperty(category = "layout")
9648    public boolean isLayoutRtl() {
9649        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9650    }
9651
9652    /**
9653     * Indicates whether the view is currently tracking transient state that the
9654     * app should not need to concern itself with saving and restoring, but that
9655     * the framework should take special note to preserve when possible.
9656     *
9657     * <p>A view with transient state cannot be trivially rebound from an external
9658     * data source, such as an adapter binding item views in a list. This may be
9659     * because the view is performing an animation, tracking user selection
9660     * of content, or similar.</p>
9661     *
9662     * @return true if the view has transient state
9663     */
9664    @ViewDebug.ExportedProperty(category = "layout")
9665    public boolean hasTransientState() {
9666        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9667    }
9668
9669    /**
9670     * Set whether this view is currently tracking transient state that the
9671     * framework should attempt to preserve when possible. This flag is reference counted,
9672     * so every call to setHasTransientState(true) should be paired with a later call
9673     * to setHasTransientState(false).
9674     *
9675     * <p>A view with transient state cannot be trivially rebound from an external
9676     * data source, such as an adapter binding item views in a list. This may be
9677     * because the view is performing an animation, tracking user selection
9678     * of content, or similar.</p>
9679     *
9680     * @param hasTransientState true if this view has transient state
9681     */
9682    public void setHasTransientState(boolean hasTransientState) {
9683        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9684                mTransientStateCount - 1;
9685        if (mTransientStateCount < 0) {
9686            mTransientStateCount = 0;
9687            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9688                    "unmatched pair of setHasTransientState calls");
9689        } else if ((hasTransientState && mTransientStateCount == 1) ||
9690                (!hasTransientState && mTransientStateCount == 0)) {
9691            // update flag if we've just incremented up from 0 or decremented down to 0
9692            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9693                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9694            if (mParent != null) {
9695                try {
9696                    mParent.childHasTransientStateChanged(this, hasTransientState);
9697                } catch (AbstractMethodError e) {
9698                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9699                            " does not fully implement ViewParent", e);
9700                }
9701            }
9702        }
9703    }
9704
9705    /**
9706     * Returns true if this view is currently attached to a window.
9707     */
9708    public boolean isAttachedToWindow() {
9709        return mAttachInfo != null;
9710    }
9711
9712    /**
9713     * Returns true if this view has been through at least one layout since it
9714     * was last attached to or detached from a window.
9715     */
9716    public boolean isLaidOut() {
9717        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9718    }
9719
9720    /**
9721     * If this view doesn't do any drawing on its own, set this flag to
9722     * allow further optimizations. By default, this flag is not set on
9723     * View, but could be set on some View subclasses such as ViewGroup.
9724     *
9725     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9726     * you should clear this flag.
9727     *
9728     * @param willNotDraw whether or not this View draw on its own
9729     */
9730    public void setWillNotDraw(boolean willNotDraw) {
9731        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9732    }
9733
9734    /**
9735     * Returns whether or not this View draws on its own.
9736     *
9737     * @return true if this view has nothing to draw, false otherwise
9738     */
9739    @ViewDebug.ExportedProperty(category = "drawing")
9740    public boolean willNotDraw() {
9741        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9742    }
9743
9744    /**
9745     * When a View's drawing cache is enabled, drawing is redirected to an
9746     * offscreen bitmap. Some views, like an ImageView, must be able to
9747     * bypass this mechanism if they already draw a single bitmap, to avoid
9748     * unnecessary usage of the memory.
9749     *
9750     * @param willNotCacheDrawing true if this view does not cache its
9751     *        drawing, false otherwise
9752     */
9753    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9754        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9755    }
9756
9757    /**
9758     * Returns whether or not this View can cache its drawing or not.
9759     *
9760     * @return true if this view does not cache its drawing, false otherwise
9761     */
9762    @ViewDebug.ExportedProperty(category = "drawing")
9763    public boolean willNotCacheDrawing() {
9764        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9765    }
9766
9767    /**
9768     * Indicates whether this view reacts to click events or not.
9769     *
9770     * @return true if the view is clickable, false otherwise
9771     *
9772     * @see #setClickable(boolean)
9773     * @attr ref android.R.styleable#View_clickable
9774     */
9775    @ViewDebug.ExportedProperty
9776    public boolean isClickable() {
9777        return (mViewFlags & CLICKABLE) == CLICKABLE;
9778    }
9779
9780    /**
9781     * Enables or disables click events for this view. When a view
9782     * is clickable it will change its state to "pressed" on every click.
9783     * Subclasses should set the view clickable to visually react to
9784     * user's clicks.
9785     *
9786     * @param clickable true to make the view clickable, false otherwise
9787     *
9788     * @see #isClickable()
9789     * @attr ref android.R.styleable#View_clickable
9790     */
9791    public void setClickable(boolean clickable) {
9792        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9793    }
9794
9795    /**
9796     * Indicates whether this view reacts to long click events or not.
9797     *
9798     * @return true if the view is long clickable, false otherwise
9799     *
9800     * @see #setLongClickable(boolean)
9801     * @attr ref android.R.styleable#View_longClickable
9802     */
9803    public boolean isLongClickable() {
9804        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9805    }
9806
9807    /**
9808     * Enables or disables long click events for this view. When a view is long
9809     * clickable it reacts to the user holding down the button for a longer
9810     * duration than a tap. This event can either launch the listener or a
9811     * context menu.
9812     *
9813     * @param longClickable true to make the view long clickable, false otherwise
9814     * @see #isLongClickable()
9815     * @attr ref android.R.styleable#View_longClickable
9816     */
9817    public void setLongClickable(boolean longClickable) {
9818        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9819    }
9820
9821    /**
9822     * Indicates whether this view reacts to context clicks or not.
9823     *
9824     * @return true if the view is context clickable, false otherwise
9825     * @see #setContextClickable(boolean)
9826     * @attr ref android.R.styleable#View_contextClickable
9827     */
9828    public boolean isContextClickable() {
9829        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9830    }
9831
9832    /**
9833     * Enables or disables context clicking for this view. This event can launch the listener.
9834     *
9835     * @param contextClickable true to make the view react to a context click, false otherwise
9836     * @see #isContextClickable()
9837     * @attr ref android.R.styleable#View_contextClickable
9838     */
9839    public void setContextClickable(boolean contextClickable) {
9840        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9841    }
9842
9843    /**
9844     * Sets the pressed state for this view and provides a touch coordinate for
9845     * animation hinting.
9846     *
9847     * @param pressed Pass true to set the View's internal state to "pressed",
9848     *            or false to reverts the View's internal state from a
9849     *            previously set "pressed" state.
9850     * @param x The x coordinate of the touch that caused the press
9851     * @param y The y coordinate of the touch that caused the press
9852     */
9853    private void setPressed(boolean pressed, float x, float y) {
9854        if (pressed) {
9855            drawableHotspotChanged(x, y);
9856        }
9857
9858        setPressed(pressed);
9859    }
9860
9861    /**
9862     * Sets the pressed state for this view.
9863     *
9864     * @see #isClickable()
9865     * @see #setClickable(boolean)
9866     *
9867     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9868     *        the View's internal state from a previously set "pressed" state.
9869     */
9870    public void setPressed(boolean pressed) {
9871        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9872
9873        if (pressed) {
9874            mPrivateFlags |= PFLAG_PRESSED;
9875        } else {
9876            mPrivateFlags &= ~PFLAG_PRESSED;
9877        }
9878
9879        if (needsRefresh) {
9880            refreshDrawableState();
9881        }
9882        dispatchSetPressed(pressed);
9883    }
9884
9885    /**
9886     * Dispatch setPressed to all of this View's children.
9887     *
9888     * @see #setPressed(boolean)
9889     *
9890     * @param pressed The new pressed state
9891     */
9892    protected void dispatchSetPressed(boolean pressed) {
9893    }
9894
9895    /**
9896     * Indicates whether the view is currently in pressed state. Unless
9897     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9898     * the pressed state.
9899     *
9900     * @see #setPressed(boolean)
9901     * @see #isClickable()
9902     * @see #setClickable(boolean)
9903     *
9904     * @return true if the view is currently pressed, false otherwise
9905     */
9906    @ViewDebug.ExportedProperty
9907    public boolean isPressed() {
9908        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9909    }
9910
9911    /**
9912     * @hide
9913     * Indicates whether this view will participate in data collection through
9914     * {@link ViewStructure}.  If true, it will not provide any data
9915     * for itself or its children.  If false, the normal data collection will be allowed.
9916     *
9917     * @return Returns false if assist data collection is not blocked, else true.
9918     *
9919     * @see #setAssistBlocked(boolean)
9920     * @attr ref android.R.styleable#View_assistBlocked
9921     */
9922    public boolean isAssistBlocked() {
9923        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9924    }
9925
9926    /**
9927     * @hide
9928     * Controls whether assist data collection from this view and its children is enabled
9929     * (that is, whether {@link #onProvideStructure} and
9930     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9931     * allowing normal assist collection.  Setting this to false will disable assist collection.
9932     *
9933     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9934     * (the default) to allow it.
9935     *
9936     * @see #isAssistBlocked()
9937     * @see #onProvideStructure
9938     * @see #onProvideVirtualStructure
9939     * @attr ref android.R.styleable#View_assistBlocked
9940     */
9941    public void setAssistBlocked(boolean enabled) {
9942        if (enabled) {
9943            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9944        } else {
9945            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9946        }
9947    }
9948
9949    /**
9950     * Indicates whether this view will save its state (that is,
9951     * whether its {@link #onSaveInstanceState} method will be called).
9952     *
9953     * @return Returns true if the view state saving is enabled, else false.
9954     *
9955     * @see #setSaveEnabled(boolean)
9956     * @attr ref android.R.styleable#View_saveEnabled
9957     */
9958    public boolean isSaveEnabled() {
9959        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9960    }
9961
9962    /**
9963     * Controls whether the saving of this view's state is
9964     * enabled (that is, whether its {@link #onSaveInstanceState} method
9965     * will be called).  Note that even if freezing is enabled, the
9966     * view still must have an id assigned to it (via {@link #setId(int)})
9967     * for its state to be saved.  This flag can only disable the
9968     * saving of this view; any child views may still have their state saved.
9969     *
9970     * @param enabled Set to false to <em>disable</em> state saving, or true
9971     * (the default) to allow it.
9972     *
9973     * @see #isSaveEnabled()
9974     * @see #setId(int)
9975     * @see #onSaveInstanceState()
9976     * @attr ref android.R.styleable#View_saveEnabled
9977     */
9978    public void setSaveEnabled(boolean enabled) {
9979        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9980    }
9981
9982    /**
9983     * Gets whether the framework should discard touches when the view's
9984     * window is obscured by another visible window.
9985     * Refer to the {@link View} security documentation for more details.
9986     *
9987     * @return True if touch filtering is enabled.
9988     *
9989     * @see #setFilterTouchesWhenObscured(boolean)
9990     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9991     */
9992    @ViewDebug.ExportedProperty
9993    public boolean getFilterTouchesWhenObscured() {
9994        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9995    }
9996
9997    /**
9998     * Sets whether the framework should discard touches when the view's
9999     * window is obscured by another visible window.
10000     * Refer to the {@link View} security documentation for more details.
10001     *
10002     * @param enabled True if touch filtering should be enabled.
10003     *
10004     * @see #getFilterTouchesWhenObscured
10005     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10006     */
10007    public void setFilterTouchesWhenObscured(boolean enabled) {
10008        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
10009                FILTER_TOUCHES_WHEN_OBSCURED);
10010    }
10011
10012    /**
10013     * Indicates whether the entire hierarchy under this view will save its
10014     * state when a state saving traversal occurs from its parent.  The default
10015     * is true; if false, these views will not be saved unless
10016     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10017     *
10018     * @return Returns true if the view state saving from parent is enabled, else false.
10019     *
10020     * @see #setSaveFromParentEnabled(boolean)
10021     */
10022    public boolean isSaveFromParentEnabled() {
10023        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
10024    }
10025
10026    /**
10027     * Controls whether the entire hierarchy under this view will save its
10028     * state when a state saving traversal occurs from its parent.  The default
10029     * is true; if false, these views will not be saved unless
10030     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10031     *
10032     * @param enabled Set to false to <em>disable</em> state saving, or true
10033     * (the default) to allow it.
10034     *
10035     * @see #isSaveFromParentEnabled()
10036     * @see #setId(int)
10037     * @see #onSaveInstanceState()
10038     */
10039    public void setSaveFromParentEnabled(boolean enabled) {
10040        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
10041    }
10042
10043
10044    /**
10045     * Returns whether this View is currently able to take focus.
10046     *
10047     * @return True if this view can take focus, or false otherwise.
10048     */
10049    @ViewDebug.ExportedProperty(category = "focus")
10050    public final boolean isFocusable() {
10051        return FOCUSABLE == (mViewFlags & FOCUSABLE);
10052    }
10053
10054    /**
10055     * Returns the focusable setting for this view.
10056     *
10057     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
10058     * @attr ref android.R.styleable#View_focusable
10059     */
10060    @ViewDebug.ExportedProperty(mapping = {
10061            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
10062            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
10063            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
10064            }, category = "focus")
10065    @Focusable
10066    public int getFocusable() {
10067        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
10068    }
10069
10070    /**
10071     * When a view is focusable, it may not want to take focus when in touch mode.
10072     * For example, a button would like focus when the user is navigating via a D-pad
10073     * so that the user can click on it, but once the user starts touching the screen,
10074     * the button shouldn't take focus
10075     * @return Whether the view is focusable in touch mode.
10076     * @attr ref android.R.styleable#View_focusableInTouchMode
10077     */
10078    @ViewDebug.ExportedProperty(category = "focus")
10079    public final boolean isFocusableInTouchMode() {
10080        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
10081    }
10082
10083    /**
10084     * Find the nearest view in the specified direction that can take focus.
10085     * This does not actually give focus to that view.
10086     *
10087     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10088     *
10089     * @return The nearest focusable in the specified direction, or null if none
10090     *         can be found.
10091     */
10092    public View focusSearch(@FocusRealDirection int direction) {
10093        if (mParent != null) {
10094            return mParent.focusSearch(this, direction);
10095        } else {
10096            return null;
10097        }
10098    }
10099
10100    /**
10101     * Returns whether this View is a root of a keyboard navigation cluster.
10102     *
10103     * @return True if this view is a root of a cluster, or false otherwise.
10104     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10105     */
10106    @ViewDebug.ExportedProperty(category = "focus")
10107    public final boolean isKeyboardNavigationCluster() {
10108        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
10109    }
10110
10111    /**
10112     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
10113     * will be ignored.
10114     *
10115     * @return the keyboard navigation cluster that this view is in (can be this view)
10116     *         or {@code null} if not in one
10117     */
10118    View findKeyboardNavigationCluster() {
10119        if (mParent instanceof View) {
10120            View cluster = ((View) mParent).findKeyboardNavigationCluster();
10121            if (cluster != null) {
10122                return cluster;
10123            } else if (isKeyboardNavigationCluster()) {
10124                return this;
10125            }
10126        }
10127        return null;
10128    }
10129
10130    /**
10131     * Set whether this view is a root of a keyboard navigation cluster.
10132     *
10133     * @param isCluster If true, this view is a root of a cluster.
10134     *
10135     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10136     */
10137    public void setKeyboardNavigationCluster(boolean isCluster) {
10138        if (isCluster) {
10139            mPrivateFlags3 |= PFLAG3_CLUSTER;
10140        } else {
10141            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
10142        }
10143    }
10144
10145    /**
10146     * Sets this View as the one which receives focus the next time cluster navigation jumps
10147     * to the cluster containing this View. This does NOT change focus even if the cluster
10148     * containing this view is current.
10149     *
10150     * @hide
10151     */
10152    public final void setFocusedInCluster() {
10153        setFocusedInCluster(findKeyboardNavigationCluster());
10154    }
10155
10156    private void setFocusedInCluster(View cluster) {
10157        if (this instanceof ViewGroup) {
10158            ((ViewGroup) this).mFocusedInCluster = null;
10159        }
10160        if (cluster == this) {
10161            return;
10162        }
10163        ViewParent parent = mParent;
10164        View child = this;
10165        while (parent instanceof ViewGroup) {
10166            ((ViewGroup) parent).mFocusedInCluster = child;
10167            if (parent == cluster) {
10168                break;
10169            }
10170            child = (View) parent;
10171            parent = parent.getParent();
10172        }
10173    }
10174
10175    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10176        if (oldFocus != null) {
10177            View oldCluster = oldFocus.findKeyboardNavigationCluster();
10178            View cluster = findKeyboardNavigationCluster();
10179            if (oldCluster != cluster) {
10180                // Going from one cluster to another, so save last-focused.
10181                // This covers cluster jumps because they are always FOCUS_DOWN
10182                oldFocus.setFocusedInCluster(oldCluster);
10183                if (!(oldFocus.mParent instanceof ViewGroup)) {
10184                    return;
10185                }
10186                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10187                    // This is a result of ordered navigation so consider navigation through
10188                    // the previous cluster "complete" and clear its last-focused memory.
10189                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10190                } else if (oldFocus instanceof ViewGroup
10191                        && ((ViewGroup) oldFocus).getDescendantFocusability()
10192                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
10193                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10194                    // This means oldFocus is not focusable since it obviously has a focusable
10195                    // child (this). Don't restore focus to it in the future.
10196                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10197                }
10198            }
10199        }
10200    }
10201
10202    /**
10203     * Returns whether this View should receive focus when the focus is restored for the view
10204     * hierarchy containing this view.
10205     * <p>
10206     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10207     * window or serves as a target of cluster navigation.
10208     *
10209     * @see #restoreDefaultFocus()
10210     *
10211     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10212     * @attr ref android.R.styleable#View_focusedByDefault
10213     */
10214    @ViewDebug.ExportedProperty(category = "focus")
10215    public final boolean isFocusedByDefault() {
10216        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10217    }
10218
10219    /**
10220     * Sets whether this View should receive focus when the focus is restored for the view
10221     * hierarchy containing this view.
10222     * <p>
10223     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10224     * window or serves as a target of cluster navigation.
10225     *
10226     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10227     *                           {@code false} otherwise.
10228     *
10229     * @see #restoreDefaultFocus()
10230     *
10231     * @attr ref android.R.styleable#View_focusedByDefault
10232     */
10233    public void setFocusedByDefault(boolean isFocusedByDefault) {
10234        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10235            return;
10236        }
10237
10238        if (isFocusedByDefault) {
10239            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10240        } else {
10241            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10242        }
10243
10244        if (mParent instanceof ViewGroup) {
10245            if (isFocusedByDefault) {
10246                ((ViewGroup) mParent).setDefaultFocus(this);
10247            } else {
10248                ((ViewGroup) mParent).clearDefaultFocus(this);
10249            }
10250        }
10251    }
10252
10253    /**
10254     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
10255     *
10256     * @return {@code true} if this view has default focus, {@code false} otherwise
10257     */
10258    boolean hasDefaultFocus() {
10259        return isFocusedByDefault();
10260    }
10261
10262    /**
10263     * Find the nearest keyboard navigation cluster in the specified direction.
10264     * This does not actually give focus to that cluster.
10265     *
10266     * @param currentCluster The starting point of the search. Null means the current cluster is not
10267     *                       found yet
10268     * @param direction Direction to look
10269     *
10270     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
10271     *         can be found
10272     */
10273    public View keyboardNavigationClusterSearch(View currentCluster,
10274            @FocusDirection int direction) {
10275        if (isKeyboardNavigationCluster()) {
10276            currentCluster = this;
10277        }
10278        if (isRootNamespace()) {
10279            // Root namespace means we should consider ourselves the top of the
10280            // tree for group searching; otherwise we could be group searching
10281            // into other tabs.  see LocalActivityManager and TabHost for more info.
10282            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
10283                    this, currentCluster, direction);
10284        } else if (mParent != null) {
10285            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
10286        }
10287        return null;
10288    }
10289
10290    /**
10291     * This method is the last chance for the focused view and its ancestors to
10292     * respond to an arrow key. This is called when the focused view did not
10293     * consume the key internally, nor could the view system find a new view in
10294     * the requested direction to give focus to.
10295     *
10296     * @param focused The currently focused view.
10297     * @param direction The direction focus wants to move. One of FOCUS_UP,
10298     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
10299     * @return True if the this view consumed this unhandled move.
10300     */
10301    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
10302        return false;
10303    }
10304
10305    /**
10306     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10307     * have {@link android.R.attr#state_focused} defined in its background.
10308     *
10309     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10310     *                                      highlight, {@code false} otherwise.
10311     *
10312     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10313     */
10314    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10315        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10316    }
10317
10318    /**
10319
10320    /**
10321     * Returns whether this View should use a default focus highlight when it gets focused but
10322     * doesn't have {@link android.R.attr#state_focused} defined in its background.
10323     *
10324     * @return True if this View should use a default focus highlight.
10325     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10326     */
10327    @ViewDebug.ExportedProperty(category = "focus")
10328    public final boolean getDefaultFocusHighlightEnabled() {
10329        return mDefaultFocusHighlightEnabled;
10330    }
10331
10332    /**
10333     * If a user manually specified the next view id for a particular direction,
10334     * use the root to look up the view.
10335     * @param root The root view of the hierarchy containing this view.
10336     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10337     * or FOCUS_BACKWARD.
10338     * @return The user specified next view, or null if there is none.
10339     */
10340    View findUserSetNextFocus(View root, @FocusDirection int direction) {
10341        switch (direction) {
10342            case FOCUS_LEFT:
10343                if (mNextFocusLeftId == View.NO_ID) return null;
10344                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10345            case FOCUS_RIGHT:
10346                if (mNextFocusRightId == View.NO_ID) return null;
10347                return findViewInsideOutShouldExist(root, mNextFocusRightId);
10348            case FOCUS_UP:
10349                if (mNextFocusUpId == View.NO_ID) return null;
10350                return findViewInsideOutShouldExist(root, mNextFocusUpId);
10351            case FOCUS_DOWN:
10352                if (mNextFocusDownId == View.NO_ID) return null;
10353                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10354            case FOCUS_FORWARD:
10355                if (mNextFocusForwardId == View.NO_ID) return null;
10356                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10357            case FOCUS_BACKWARD: {
10358                if (mID == View.NO_ID) return null;
10359                final int id = mID;
10360                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10361                    @Override
10362                    public boolean test(View t) {
10363                        return t.mNextFocusForwardId == id;
10364                    }
10365                });
10366            }
10367        }
10368        return null;
10369    }
10370
10371    /**
10372     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10373     * use the root to look up the view.
10374     *
10375     * @param root the root view of the hierarchy containing this view
10376     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10377     * @return the user-specified next cluster, or {@code null} if there is none
10378     */
10379    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10380        switch (direction) {
10381            case FOCUS_FORWARD:
10382                if (mNextClusterForwardId == View.NO_ID) return null;
10383                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10384            case FOCUS_BACKWARD: {
10385                if (mID == View.NO_ID) return null;
10386                final int id = mID;
10387                return root.findViewByPredicateInsideOut(this,
10388                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10389            }
10390        }
10391        return null;
10392    }
10393
10394    private View findViewInsideOutShouldExist(View root, int id) {
10395        if (mMatchIdPredicate == null) {
10396            mMatchIdPredicate = new MatchIdPredicate();
10397        }
10398        mMatchIdPredicate.mId = id;
10399        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10400        if (result == null) {
10401            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10402        }
10403        return result;
10404    }
10405
10406    /**
10407     * Find and return all focusable views that are descendants of this view,
10408     * possibly including this view if it is focusable itself.
10409     *
10410     * @param direction The direction of the focus
10411     * @return A list of focusable views
10412     */
10413    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10414        ArrayList<View> result = new ArrayList<View>(24);
10415        addFocusables(result, direction);
10416        return result;
10417    }
10418
10419    /**
10420     * Add any focusable views that are descendants of this view (possibly
10421     * including this view if it is focusable itself) to views.  If we are in touch mode,
10422     * only add views that are also focusable in touch mode.
10423     *
10424     * @param views Focusable views found so far
10425     * @param direction The direction of the focus
10426     */
10427    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10428        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10429    }
10430
10431    /**
10432     * Adds any focusable views that are descendants of this view (possibly
10433     * including this view if it is focusable itself) to views. This method
10434     * adds all focusable views regardless if we are in touch mode or
10435     * only views focusable in touch mode if we are in touch mode or
10436     * only views that can take accessibility focus if accessibility is enabled
10437     * depending on the focusable mode parameter.
10438     *
10439     * @param views Focusable views found so far or null if all we are interested is
10440     *        the number of focusables.
10441     * @param direction The direction of the focus.
10442     * @param focusableMode The type of focusables to be added.
10443     *
10444     * @see #FOCUSABLES_ALL
10445     * @see #FOCUSABLES_TOUCH_MODE
10446     */
10447    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10448            @FocusableMode int focusableMode) {
10449        if (views == null) {
10450            return;
10451        }
10452        if (!isFocusable()) {
10453            return;
10454        }
10455        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10456                && !isFocusableInTouchMode()) {
10457            return;
10458        }
10459        views.add(this);
10460    }
10461
10462    /**
10463     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10464     * including this view if it is a cluster root itself) to views.
10465     *
10466     * @param views Keyboard navigation cluster roots found so far
10467     * @param direction Direction to look
10468     */
10469    public void addKeyboardNavigationClusters(
10470            @NonNull Collection<View> views,
10471            int direction) {
10472        if (!isKeyboardNavigationCluster()) {
10473            return;
10474        }
10475        if (!hasFocusable()) {
10476            return;
10477        }
10478        views.add(this);
10479    }
10480
10481    /**
10482     * Finds the Views that contain given text. The containment is case insensitive.
10483     * The search is performed by either the text that the View renders or the content
10484     * description that describes the view for accessibility purposes and the view does
10485     * not render or both. Clients can specify how the search is to be performed via
10486     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10487     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10488     *
10489     * @param outViews The output list of matching Views.
10490     * @param searched The text to match against.
10491     *
10492     * @see #FIND_VIEWS_WITH_TEXT
10493     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10494     * @see #setContentDescription(CharSequence)
10495     */
10496    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10497            @FindViewFlags int flags) {
10498        if (getAccessibilityNodeProvider() != null) {
10499            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10500                outViews.add(this);
10501            }
10502        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10503                && (searched != null && searched.length() > 0)
10504                && (mContentDescription != null && mContentDescription.length() > 0)) {
10505            String searchedLowerCase = searched.toString().toLowerCase();
10506            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10507            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10508                outViews.add(this);
10509            }
10510        }
10511    }
10512
10513    /**
10514     * Find and return all touchable views that are descendants of this view,
10515     * possibly including this view if it is touchable itself.
10516     *
10517     * @return A list of touchable views
10518     */
10519    public ArrayList<View> getTouchables() {
10520        ArrayList<View> result = new ArrayList<View>();
10521        addTouchables(result);
10522        return result;
10523    }
10524
10525    /**
10526     * Add any touchable views that are descendants of this view (possibly
10527     * including this view if it is touchable itself) to views.
10528     *
10529     * @param views Touchable views found so far
10530     */
10531    public void addTouchables(ArrayList<View> views) {
10532        final int viewFlags = mViewFlags;
10533
10534        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10535                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10536                && (viewFlags & ENABLED_MASK) == ENABLED) {
10537            views.add(this);
10538        }
10539    }
10540
10541    /**
10542     * Returns whether this View is accessibility focused.
10543     *
10544     * @return True if this View is accessibility focused.
10545     */
10546    public boolean isAccessibilityFocused() {
10547        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10548    }
10549
10550    /**
10551     * Call this to try to give accessibility focus to this view.
10552     *
10553     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10554     * returns false or the view is no visible or the view already has accessibility
10555     * focus.
10556     *
10557     * See also {@link #focusSearch(int)}, which is what you call to say that you
10558     * have focus, and you want your parent to look for the next one.
10559     *
10560     * @return Whether this view actually took accessibility focus.
10561     *
10562     * @hide
10563     */
10564    public boolean requestAccessibilityFocus() {
10565        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10566        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10567            return false;
10568        }
10569        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10570            return false;
10571        }
10572        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10573            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10574            ViewRootImpl viewRootImpl = getViewRootImpl();
10575            if (viewRootImpl != null) {
10576                viewRootImpl.setAccessibilityFocus(this, null);
10577            }
10578            invalidate();
10579            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10580            return true;
10581        }
10582        return false;
10583    }
10584
10585    /**
10586     * Call this to try to clear accessibility focus of this view.
10587     *
10588     * See also {@link #focusSearch(int)}, which is what you call to say that you
10589     * have focus, and you want your parent to look for the next one.
10590     *
10591     * @hide
10592     */
10593    public void clearAccessibilityFocus() {
10594        clearAccessibilityFocusNoCallbacks(0);
10595
10596        // Clear the global reference of accessibility focus if this view or
10597        // any of its descendants had accessibility focus. This will NOT send
10598        // an event or update internal state if focus is cleared from a
10599        // descendant view, which may leave views in inconsistent states.
10600        final ViewRootImpl viewRootImpl = getViewRootImpl();
10601        if (viewRootImpl != null) {
10602            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10603            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10604                viewRootImpl.setAccessibilityFocus(null, null);
10605            }
10606        }
10607    }
10608
10609    private void sendAccessibilityHoverEvent(int eventType) {
10610        // Since we are not delivering to a client accessibility events from not
10611        // important views (unless the clinet request that) we need to fire the
10612        // event from the deepest view exposed to the client. As a consequence if
10613        // the user crosses a not exposed view the client will see enter and exit
10614        // of the exposed predecessor followed by and enter and exit of that same
10615        // predecessor when entering and exiting the not exposed descendant. This
10616        // is fine since the client has a clear idea which view is hovered at the
10617        // price of a couple more events being sent. This is a simple and
10618        // working solution.
10619        View source = this;
10620        while (true) {
10621            if (source.includeForAccessibility()) {
10622                source.sendAccessibilityEvent(eventType);
10623                return;
10624            }
10625            ViewParent parent = source.getParent();
10626            if (parent instanceof View) {
10627                source = (View) parent;
10628            } else {
10629                return;
10630            }
10631        }
10632    }
10633
10634    /**
10635     * Clears accessibility focus without calling any callback methods
10636     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10637     * is used separately from that one for clearing accessibility focus when
10638     * giving this focus to another view.
10639     *
10640     * @param action The action, if any, that led to focus being cleared. Set to
10641     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10642     * the window.
10643     */
10644    void clearAccessibilityFocusNoCallbacks(int action) {
10645        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10646            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10647            invalidate();
10648            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10649                AccessibilityEvent event = AccessibilityEvent.obtain(
10650                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10651                event.setAction(action);
10652                if (mAccessibilityDelegate != null) {
10653                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10654                } else {
10655                    sendAccessibilityEventUnchecked(event);
10656                }
10657            }
10658        }
10659    }
10660
10661    /**
10662     * Call this to try to give focus to a specific view or to one of its
10663     * descendants.
10664     *
10665     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10666     * false), or if it is focusable and it is not focusable in touch mode
10667     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10668     *
10669     * See also {@link #focusSearch(int)}, which is what you call to say that you
10670     * have focus, and you want your parent to look for the next one.
10671     *
10672     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10673     * {@link #FOCUS_DOWN} and <code>null</code>.
10674     *
10675     * @return Whether this view or one of its descendants actually took focus.
10676     */
10677    public final boolean requestFocus() {
10678        return requestFocus(View.FOCUS_DOWN);
10679    }
10680
10681    /**
10682     * This will request focus for whichever View was last focused within this
10683     * cluster before a focus-jump out of it.
10684     *
10685     * @hide
10686     */
10687    @TestApi
10688    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10689        // Prioritize focusableByDefault over algorithmic focus selection.
10690        if (restoreDefaultFocus()) {
10691            return true;
10692        }
10693        return requestFocus(direction);
10694    }
10695
10696    /**
10697     * This will request focus for whichever View not in a cluster was last focused before a
10698     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10699     * the "first" focusable view it finds.
10700     *
10701     * @hide
10702     */
10703    @TestApi
10704    public boolean restoreFocusNotInCluster() {
10705        return requestFocus(View.FOCUS_DOWN);
10706    }
10707
10708    /**
10709     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10710     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10711     *
10712     * @return Whether this view or one of its descendants actually took focus
10713     */
10714    public boolean restoreDefaultFocus() {
10715        return requestFocus(View.FOCUS_DOWN);
10716    }
10717
10718    /**
10719     * Call this to try to give focus to a specific view or to one of its
10720     * descendants and give it a hint about what direction focus is heading.
10721     *
10722     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10723     * false), or if it is focusable and it is not focusable in touch mode
10724     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10725     *
10726     * See also {@link #focusSearch(int)}, which is what you call to say that you
10727     * have focus, and you want your parent to look for the next one.
10728     *
10729     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10730     * <code>null</code> set for the previously focused rectangle.
10731     *
10732     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10733     * @return Whether this view or one of its descendants actually took focus.
10734     */
10735    public final boolean requestFocus(int direction) {
10736        return requestFocus(direction, null);
10737    }
10738
10739    /**
10740     * Call this to try to give focus to a specific view or to one of its descendants
10741     * and give it hints about the direction and a specific rectangle that the focus
10742     * is coming from.  The rectangle can help give larger views a finer grained hint
10743     * about where focus is coming from, and therefore, where to show selection, or
10744     * forward focus change internally.
10745     *
10746     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10747     * false), or if it is focusable and it is not focusable in touch mode
10748     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10749     *
10750     * A View will not take focus if it is not visible.
10751     *
10752     * A View will not take focus if one of its parents has
10753     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10754     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10755     *
10756     * See also {@link #focusSearch(int)}, which is what you call to say that you
10757     * have focus, and you want your parent to look for the next one.
10758     *
10759     * You may wish to override this method if your custom {@link View} has an internal
10760     * {@link View} that it wishes to forward the request to.
10761     *
10762     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10763     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10764     *        to give a finer grained hint about where focus is coming from.  May be null
10765     *        if there is no hint.
10766     * @return Whether this view or one of its descendants actually took focus.
10767     */
10768    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10769        return requestFocusNoSearch(direction, previouslyFocusedRect);
10770    }
10771
10772    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10773        // need to be focusable
10774        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10775                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10776            return false;
10777        }
10778
10779        // need to be focusable in touch mode if in touch mode
10780        if (isInTouchMode() &&
10781            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10782               return false;
10783        }
10784
10785        // need to not have any parents blocking us
10786        if (hasAncestorThatBlocksDescendantFocus()) {
10787            return false;
10788        }
10789
10790        handleFocusGainInternal(direction, previouslyFocusedRect);
10791        return true;
10792    }
10793
10794    /**
10795     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10796     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10797     * touch mode to request focus when they are touched.
10798     *
10799     * @return Whether this view or one of its descendants actually took focus.
10800     *
10801     * @see #isInTouchMode()
10802     *
10803     */
10804    public final boolean requestFocusFromTouch() {
10805        // Leave touch mode if we need to
10806        if (isInTouchMode()) {
10807            ViewRootImpl viewRoot = getViewRootImpl();
10808            if (viewRoot != null) {
10809                viewRoot.ensureTouchMode(false);
10810            }
10811        }
10812        return requestFocus(View.FOCUS_DOWN);
10813    }
10814
10815    /**
10816     * @return Whether any ancestor of this view blocks descendant focus.
10817     */
10818    private boolean hasAncestorThatBlocksDescendantFocus() {
10819        final boolean focusableInTouchMode = isFocusableInTouchMode();
10820        ViewParent ancestor = mParent;
10821        while (ancestor instanceof ViewGroup) {
10822            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10823            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10824                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10825                return true;
10826            } else {
10827                ancestor = vgAncestor.getParent();
10828            }
10829        }
10830        return false;
10831    }
10832
10833    /**
10834     * Gets the mode for determining whether this View is important for accessibility.
10835     * A view is important for accessibility if it fires accessibility events and if it
10836     * is reported to accessibility services that query the screen.
10837     *
10838     * @return The mode for determining whether a view is important for accessibility, one
10839     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10840     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10841     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10842     *
10843     * @attr ref android.R.styleable#View_importantForAccessibility
10844     *
10845     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10846     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10847     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10848     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10849     */
10850    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10851            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10852            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10853            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10854            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10855                    to = "noHideDescendants")
10856        })
10857    public int getImportantForAccessibility() {
10858        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10859                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10860    }
10861
10862    /**
10863     * Sets the live region mode for this view. This indicates to accessibility
10864     * services whether they should automatically notify the user about changes
10865     * to the view's content description or text, or to the content descriptions
10866     * or text of the view's children (where applicable).
10867     * <p>
10868     * For example, in a login screen with a TextView that displays an "incorrect
10869     * password" notification, that view should be marked as a live region with
10870     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10871     * <p>
10872     * To disable change notifications for this view, use
10873     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10874     * mode for most views.
10875     * <p>
10876     * To indicate that the user should be notified of changes, use
10877     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10878     * <p>
10879     * If the view's changes should interrupt ongoing speech and notify the user
10880     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10881     *
10882     * @param mode The live region mode for this view, one of:
10883     *        <ul>
10884     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10885     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10886     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10887     *        </ul>
10888     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10889     */
10890    public void setAccessibilityLiveRegion(int mode) {
10891        if (mode != getAccessibilityLiveRegion()) {
10892            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10893            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10894                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10895            notifyViewAccessibilityStateChangedIfNeeded(
10896                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10897        }
10898    }
10899
10900    /**
10901     * Gets the live region mode for this View.
10902     *
10903     * @return The live region mode for the view.
10904     *
10905     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10906     *
10907     * @see #setAccessibilityLiveRegion(int)
10908     */
10909    public int getAccessibilityLiveRegion() {
10910        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10911                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10912    }
10913
10914    /**
10915     * Sets how to determine whether this view is important for accessibility
10916     * which is if it fires accessibility events and if it is reported to
10917     * accessibility services that query the screen.
10918     *
10919     * @param mode How to determine whether this view is important for accessibility.
10920     *
10921     * @attr ref android.R.styleable#View_importantForAccessibility
10922     *
10923     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10924     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10925     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10926     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10927     */
10928    public void setImportantForAccessibility(int mode) {
10929        final int oldMode = getImportantForAccessibility();
10930        if (mode != oldMode) {
10931            final boolean hideDescendants =
10932                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10933
10934            // If this node or its descendants are no longer important, try to
10935            // clear accessibility focus.
10936            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10937                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10938                if (focusHost != null) {
10939                    focusHost.clearAccessibilityFocus();
10940                }
10941            }
10942
10943            // If we're moving between AUTO and another state, we might not need
10944            // to send a subtree changed notification. We'll store the computed
10945            // importance, since we'll need to check it later to make sure.
10946            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10947                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10948            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10949            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10950            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10951                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10952            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10953                notifySubtreeAccessibilityStateChangedIfNeeded();
10954            } else {
10955                notifyViewAccessibilityStateChangedIfNeeded(
10956                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10957            }
10958        }
10959    }
10960
10961    /**
10962     * Returns the view within this view's hierarchy that is hosting
10963     * accessibility focus.
10964     *
10965     * @param searchDescendants whether to search for focus in descendant views
10966     * @return the view hosting accessibility focus, or {@code null}
10967     */
10968    private View findAccessibilityFocusHost(boolean searchDescendants) {
10969        if (isAccessibilityFocusedViewOrHost()) {
10970            return this;
10971        }
10972
10973        if (searchDescendants) {
10974            final ViewRootImpl viewRoot = getViewRootImpl();
10975            if (viewRoot != null) {
10976                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10977                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10978                    return focusHost;
10979                }
10980            }
10981        }
10982
10983        return null;
10984    }
10985
10986    /**
10987     * Computes whether this view should be exposed for accessibility. In
10988     * general, views that are interactive or provide information are exposed
10989     * while views that serve only as containers are hidden.
10990     * <p>
10991     * If an ancestor of this view has importance
10992     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10993     * returns <code>false</code>.
10994     * <p>
10995     * Otherwise, the value is computed according to the view's
10996     * {@link #getImportantForAccessibility()} value:
10997     * <ol>
10998     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10999     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
11000     * </code>
11001     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
11002     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
11003     * view satisfies any of the following:
11004     * <ul>
11005     * <li>Is actionable, e.g. {@link #isClickable()},
11006     * {@link #isLongClickable()}, or {@link #isFocusable()}
11007     * <li>Has an {@link AccessibilityDelegate}
11008     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
11009     * {@link OnKeyListener}, etc.
11010     * <li>Is an accessibility live region, e.g.
11011     * {@link #getAccessibilityLiveRegion()} is not
11012     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
11013     * </ul>
11014     * </ol>
11015     *
11016     * @return Whether the view is exposed for accessibility.
11017     * @see #setImportantForAccessibility(int)
11018     * @see #getImportantForAccessibility()
11019     */
11020    public boolean isImportantForAccessibility() {
11021        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11022                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11023        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
11024                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11025            return false;
11026        }
11027
11028        // Check parent mode to ensure we're not hidden.
11029        ViewParent parent = mParent;
11030        while (parent instanceof View) {
11031            if (((View) parent).getImportantForAccessibility()
11032                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11033                return false;
11034            }
11035            parent = parent.getParent();
11036        }
11037
11038        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
11039                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
11040                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
11041    }
11042
11043    /**
11044     * Gets the parent for accessibility purposes. Note that the parent for
11045     * accessibility is not necessary the immediate parent. It is the first
11046     * predecessor that is important for accessibility.
11047     *
11048     * @return The parent for accessibility purposes.
11049     */
11050    public ViewParent getParentForAccessibility() {
11051        if (mParent instanceof View) {
11052            View parentView = (View) mParent;
11053            if (parentView.includeForAccessibility()) {
11054                return mParent;
11055            } else {
11056                return mParent.getParentForAccessibility();
11057            }
11058        }
11059        return null;
11060    }
11061
11062    /**
11063     * Adds the children of this View relevant for accessibility to the given list
11064     * as output. Since some Views are not important for accessibility the added
11065     * child views are not necessarily direct children of this view, rather they are
11066     * the first level of descendants important for accessibility.
11067     *
11068     * @param outChildren The output list that will receive children for accessibility.
11069     */
11070    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
11071
11072    }
11073
11074    /**
11075     * Whether to regard this view for accessibility. A view is regarded for
11076     * accessibility if it is important for accessibility or the querying
11077     * accessibility service has explicitly requested that view not
11078     * important for accessibility are regarded.
11079     *
11080     * @return Whether to regard the view for accessibility.
11081     *
11082     * @hide
11083     */
11084    public boolean includeForAccessibility() {
11085        if (mAttachInfo != null) {
11086            return (mAttachInfo.mAccessibilityFetchFlags
11087                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
11088                    || isImportantForAccessibility();
11089        }
11090        return false;
11091    }
11092
11093    /**
11094     * Returns whether the View is considered actionable from
11095     * accessibility perspective. Such view are important for
11096     * accessibility.
11097     *
11098     * @return True if the view is actionable for accessibility.
11099     *
11100     * @hide
11101     */
11102    public boolean isActionableForAccessibility() {
11103        return (isClickable() || isLongClickable() || isFocusable());
11104    }
11105
11106    /**
11107     * Returns whether the View has registered callbacks which makes it
11108     * important for accessibility.
11109     *
11110     * @return True if the view is actionable for accessibility.
11111     */
11112    private boolean hasListenersForAccessibility() {
11113        ListenerInfo info = getListenerInfo();
11114        return mTouchDelegate != null || info.mOnKeyListener != null
11115                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
11116                || info.mOnHoverListener != null || info.mOnDragListener != null;
11117    }
11118
11119    /**
11120     * Notifies that the accessibility state of this view changed. The change
11121     * is local to this view and does not represent structural changes such
11122     * as children and parent. For example, the view became focusable. The
11123     * notification is at at most once every
11124     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11125     * to avoid unnecessary load to the system. Also once a view has a pending
11126     * notification this method is a NOP until the notification has been sent.
11127     *
11128     * @hide
11129     */
11130    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
11131        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11132            return;
11133        }
11134        if (mSendViewStateChangedAccessibilityEvent == null) {
11135            mSendViewStateChangedAccessibilityEvent =
11136                    new SendViewStateChangedAccessibilityEvent();
11137        }
11138        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
11139    }
11140
11141    /**
11142     * Notifies that the accessibility state of this view changed. The change
11143     * is *not* local to this view and does represent structural changes such
11144     * as children and parent. For example, the view size changed. The
11145     * notification is at at most once every
11146     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11147     * to avoid unnecessary load to the system. Also once a view has a pending
11148     * notification this method is a NOP until the notification has been sent.
11149     *
11150     * @hide
11151     */
11152    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11153        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11154            return;
11155        }
11156        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11157            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11158            if (mParent != null) {
11159                try {
11160                    mParent.notifySubtreeAccessibilityStateChanged(
11161                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11162                } catch (AbstractMethodError e) {
11163                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11164                            " does not fully implement ViewParent", e);
11165                }
11166            }
11167        }
11168    }
11169
11170    /**
11171     * Change the visibility of the View without triggering any other changes. This is
11172     * important for transitions, where visibility changes should not adjust focus or
11173     * trigger a new layout. This is only used when the visibility has already been changed
11174     * and we need a transient value during an animation. When the animation completes,
11175     * the original visibility value is always restored.
11176     *
11177     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11178     * @hide
11179     */
11180    public void setTransitionVisibility(@Visibility int visibility) {
11181        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11182    }
11183
11184    /**
11185     * Reset the flag indicating the accessibility state of the subtree rooted
11186     * at this view changed.
11187     */
11188    void resetSubtreeAccessibilityStateChanged() {
11189        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11190    }
11191
11192    /**
11193     * Report an accessibility action to this view's parents for delegated processing.
11194     *
11195     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
11196     * call this method to delegate an accessibility action to a supporting parent. If the parent
11197     * returns true from its
11198     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
11199     * method this method will return true to signify that the action was consumed.</p>
11200     *
11201     * <p>This method is useful for implementing nested scrolling child views. If
11202     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
11203     * a custom view implementation may invoke this method to allow a parent to consume the
11204     * scroll first. If this method returns true the custom view should skip its own scrolling
11205     * behavior.</p>
11206     *
11207     * @param action Accessibility action to delegate
11208     * @param arguments Optional action arguments
11209     * @return true if the action was consumed by a parent
11210     */
11211    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
11212        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
11213            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
11214                return true;
11215            }
11216        }
11217        return false;
11218    }
11219
11220    /**
11221     * Performs the specified accessibility action on the view. For
11222     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
11223     * <p>
11224     * If an {@link AccessibilityDelegate} has been specified via calling
11225     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11226     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
11227     * is responsible for handling this call.
11228     * </p>
11229     *
11230     * <p>The default implementation will delegate
11231     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
11232     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
11233     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
11234     *
11235     * @param action The action to perform.
11236     * @param arguments Optional action arguments.
11237     * @return Whether the action was performed.
11238     */
11239    public boolean performAccessibilityAction(int action, Bundle arguments) {
11240      if (mAccessibilityDelegate != null) {
11241          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
11242      } else {
11243          return performAccessibilityActionInternal(action, arguments);
11244      }
11245    }
11246
11247   /**
11248    * @see #performAccessibilityAction(int, Bundle)
11249    *
11250    * Note: Called from the default {@link AccessibilityDelegate}.
11251    *
11252    * @hide
11253    */
11254    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
11255        if (isNestedScrollingEnabled()
11256                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
11257                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
11258                || action == R.id.accessibilityActionScrollUp
11259                || action == R.id.accessibilityActionScrollLeft
11260                || action == R.id.accessibilityActionScrollDown
11261                || action == R.id.accessibilityActionScrollRight)) {
11262            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
11263                return true;
11264            }
11265        }
11266
11267        switch (action) {
11268            case AccessibilityNodeInfo.ACTION_CLICK: {
11269                if (isClickable()) {
11270                    performClick();
11271                    return true;
11272                }
11273            } break;
11274            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
11275                if (isLongClickable()) {
11276                    performLongClick();
11277                    return true;
11278                }
11279            } break;
11280            case AccessibilityNodeInfo.ACTION_FOCUS: {
11281                if (!hasFocus()) {
11282                    // Get out of touch mode since accessibility
11283                    // wants to move focus around.
11284                    getViewRootImpl().ensureTouchMode(false);
11285                    return requestFocus();
11286                }
11287            } break;
11288            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
11289                if (hasFocus()) {
11290                    clearFocus();
11291                    return !isFocused();
11292                }
11293            } break;
11294            case AccessibilityNodeInfo.ACTION_SELECT: {
11295                if (!isSelected()) {
11296                    setSelected(true);
11297                    return isSelected();
11298                }
11299            } break;
11300            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
11301                if (isSelected()) {
11302                    setSelected(false);
11303                    return !isSelected();
11304                }
11305            } break;
11306            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11307                if (!isAccessibilityFocused()) {
11308                    return requestAccessibilityFocus();
11309                }
11310            } break;
11311            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11312                if (isAccessibilityFocused()) {
11313                    clearAccessibilityFocus();
11314                    return true;
11315                }
11316            } break;
11317            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11318                if (arguments != null) {
11319                    final int granularity = arguments.getInt(
11320                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11321                    final boolean extendSelection = arguments.getBoolean(
11322                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11323                    return traverseAtGranularity(granularity, true, extendSelection);
11324                }
11325            } break;
11326            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11327                if (arguments != null) {
11328                    final int granularity = arguments.getInt(
11329                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11330                    final boolean extendSelection = arguments.getBoolean(
11331                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11332                    return traverseAtGranularity(granularity, false, extendSelection);
11333                }
11334            } break;
11335            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11336                CharSequence text = getIterableTextForAccessibility();
11337                if (text == null) {
11338                    return false;
11339                }
11340                final int start = (arguments != null) ? arguments.getInt(
11341                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11342                final int end = (arguments != null) ? arguments.getInt(
11343                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11344                // Only cursor position can be specified (selection length == 0)
11345                if ((getAccessibilitySelectionStart() != start
11346                        || getAccessibilitySelectionEnd() != end)
11347                        && (start == end)) {
11348                    setAccessibilitySelection(start, end);
11349                    notifyViewAccessibilityStateChangedIfNeeded(
11350                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11351                    return true;
11352                }
11353            } break;
11354            case R.id.accessibilityActionShowOnScreen: {
11355                if (mAttachInfo != null) {
11356                    final Rect r = mAttachInfo.mTmpInvalRect;
11357                    getDrawingRect(r);
11358                    return requestRectangleOnScreen(r, true);
11359                }
11360            } break;
11361            case R.id.accessibilityActionContextClick: {
11362                if (isContextClickable()) {
11363                    performContextClick();
11364                    return true;
11365                }
11366            } break;
11367        }
11368        return false;
11369    }
11370
11371    private boolean traverseAtGranularity(int granularity, boolean forward,
11372            boolean extendSelection) {
11373        CharSequence text = getIterableTextForAccessibility();
11374        if (text == null || text.length() == 0) {
11375            return false;
11376        }
11377        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11378        if (iterator == null) {
11379            return false;
11380        }
11381        int current = getAccessibilitySelectionEnd();
11382        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11383            current = forward ? 0 : text.length();
11384        }
11385        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11386        if (range == null) {
11387            return false;
11388        }
11389        final int segmentStart = range[0];
11390        final int segmentEnd = range[1];
11391        int selectionStart;
11392        int selectionEnd;
11393        if (extendSelection && isAccessibilitySelectionExtendable()) {
11394            selectionStart = getAccessibilitySelectionStart();
11395            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11396                selectionStart = forward ? segmentStart : segmentEnd;
11397            }
11398            selectionEnd = forward ? segmentEnd : segmentStart;
11399        } else {
11400            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11401        }
11402        setAccessibilitySelection(selectionStart, selectionEnd);
11403        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11404                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11405        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11406        return true;
11407    }
11408
11409    /**
11410     * Gets the text reported for accessibility purposes.
11411     *
11412     * @return The accessibility text.
11413     *
11414     * @hide
11415     */
11416    public CharSequence getIterableTextForAccessibility() {
11417        return getContentDescription();
11418    }
11419
11420    /**
11421     * Gets whether accessibility selection can be extended.
11422     *
11423     * @return If selection is extensible.
11424     *
11425     * @hide
11426     */
11427    public boolean isAccessibilitySelectionExtendable() {
11428        return false;
11429    }
11430
11431    /**
11432     * @hide
11433     */
11434    public int getAccessibilitySelectionStart() {
11435        return mAccessibilityCursorPosition;
11436    }
11437
11438    /**
11439     * @hide
11440     */
11441    public int getAccessibilitySelectionEnd() {
11442        return getAccessibilitySelectionStart();
11443    }
11444
11445    /**
11446     * @hide
11447     */
11448    public void setAccessibilitySelection(int start, int end) {
11449        if (start ==  end && end == mAccessibilityCursorPosition) {
11450            return;
11451        }
11452        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11453            mAccessibilityCursorPosition = start;
11454        } else {
11455            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11456        }
11457        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11458    }
11459
11460    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11461            int fromIndex, int toIndex) {
11462        if (mParent == null) {
11463            return;
11464        }
11465        AccessibilityEvent event = AccessibilityEvent.obtain(
11466                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11467        onInitializeAccessibilityEvent(event);
11468        onPopulateAccessibilityEvent(event);
11469        event.setFromIndex(fromIndex);
11470        event.setToIndex(toIndex);
11471        event.setAction(action);
11472        event.setMovementGranularity(granularity);
11473        mParent.requestSendAccessibilityEvent(this, event);
11474    }
11475
11476    /**
11477     * @hide
11478     */
11479    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11480        switch (granularity) {
11481            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11482                CharSequence text = getIterableTextForAccessibility();
11483                if (text != null && text.length() > 0) {
11484                    CharacterTextSegmentIterator iterator =
11485                        CharacterTextSegmentIterator.getInstance(
11486                                mContext.getResources().getConfiguration().locale);
11487                    iterator.initialize(text.toString());
11488                    return iterator;
11489                }
11490            } break;
11491            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11492                CharSequence text = getIterableTextForAccessibility();
11493                if (text != null && text.length() > 0) {
11494                    WordTextSegmentIterator iterator =
11495                        WordTextSegmentIterator.getInstance(
11496                                mContext.getResources().getConfiguration().locale);
11497                    iterator.initialize(text.toString());
11498                    return iterator;
11499                }
11500            } break;
11501            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11502                CharSequence text = getIterableTextForAccessibility();
11503                if (text != null && text.length() > 0) {
11504                    ParagraphTextSegmentIterator iterator =
11505                        ParagraphTextSegmentIterator.getInstance();
11506                    iterator.initialize(text.toString());
11507                    return iterator;
11508                }
11509            } break;
11510        }
11511        return null;
11512    }
11513
11514    /**
11515     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11516     * and {@link #onFinishTemporaryDetach()}.
11517     *
11518     * <p>This method always returns {@code true} when called directly or indirectly from
11519     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11520     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11521     * <ul>
11522     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11523     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11524     * </ul>
11525     * </p>
11526     *
11527     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11528     * and {@link #onFinishTemporaryDetach()}.
11529     */
11530    public final boolean isTemporarilyDetached() {
11531        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11532    }
11533
11534    /**
11535     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11536     * a container View.
11537     */
11538    @CallSuper
11539    public void dispatchStartTemporaryDetach() {
11540        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11541        notifyEnterOrExitForAutoFillIfNeeded(false);
11542        onStartTemporaryDetach();
11543    }
11544
11545    /**
11546     * This is called when a container is going to temporarily detach a child, with
11547     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11548     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11549     * {@link #onDetachedFromWindow()} when the container is done.
11550     */
11551    public void onStartTemporaryDetach() {
11552        removeUnsetPressCallback();
11553        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11554    }
11555
11556    /**
11557     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11558     * a container View.
11559     */
11560    @CallSuper
11561    public void dispatchFinishTemporaryDetach() {
11562        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11563        onFinishTemporaryDetach();
11564        if (hasWindowFocus() && hasFocus()) {
11565            InputMethodManager.getInstance().focusIn(this);
11566        }
11567        notifyEnterOrExitForAutoFillIfNeeded(true);
11568    }
11569
11570    /**
11571     * Called after {@link #onStartTemporaryDetach} when the container is done
11572     * changing the view.
11573     */
11574    public void onFinishTemporaryDetach() {
11575    }
11576
11577    /**
11578     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11579     * for this view's window.  Returns null if the view is not currently attached
11580     * to the window.  Normally you will not need to use this directly, but
11581     * just use the standard high-level event callbacks like
11582     * {@link #onKeyDown(int, KeyEvent)}.
11583     */
11584    public KeyEvent.DispatcherState getKeyDispatcherState() {
11585        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11586    }
11587
11588    /**
11589     * Dispatch a key event before it is processed by any input method
11590     * associated with the view hierarchy.  This can be used to intercept
11591     * key events in special situations before the IME consumes them; a
11592     * typical example would be handling the BACK key to update the application's
11593     * UI instead of allowing the IME to see it and close itself.
11594     *
11595     * @param event The key event to be dispatched.
11596     * @return True if the event was handled, false otherwise.
11597     */
11598    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11599        return onKeyPreIme(event.getKeyCode(), event);
11600    }
11601
11602    /**
11603     * Dispatch a key event to the next view on the focus path. This path runs
11604     * from the top of the view tree down to the currently focused view. If this
11605     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11606     * the next node down the focus path. This method also fires any key
11607     * listeners.
11608     *
11609     * @param event The key event to be dispatched.
11610     * @return True if the event was handled, false otherwise.
11611     */
11612    public boolean dispatchKeyEvent(KeyEvent event) {
11613        if (mInputEventConsistencyVerifier != null) {
11614            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11615        }
11616
11617        // Give any attached key listener a first crack at the event.
11618        //noinspection SimplifiableIfStatement
11619        ListenerInfo li = mListenerInfo;
11620        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11621                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11622            return true;
11623        }
11624
11625        if (event.dispatch(this, mAttachInfo != null
11626                ? mAttachInfo.mKeyDispatchState : null, this)) {
11627            return true;
11628        }
11629
11630        if (mInputEventConsistencyVerifier != null) {
11631            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11632        }
11633        return false;
11634    }
11635
11636    /**
11637     * Dispatches a key shortcut event.
11638     *
11639     * @param event The key event to be dispatched.
11640     * @return True if the event was handled by the view, false otherwise.
11641     */
11642    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11643        return onKeyShortcut(event.getKeyCode(), event);
11644    }
11645
11646    /**
11647     * Pass the touch screen motion event down to the target view, or this
11648     * view if it is the target.
11649     *
11650     * @param event The motion event to be dispatched.
11651     * @return True if the event was handled by the view, false otherwise.
11652     */
11653    public boolean dispatchTouchEvent(MotionEvent event) {
11654        // If the event should be handled by accessibility focus first.
11655        if (event.isTargetAccessibilityFocus()) {
11656            // We don't have focus or no virtual descendant has it, do not handle the event.
11657            if (!isAccessibilityFocusedViewOrHost()) {
11658                return false;
11659            }
11660            // We have focus and got the event, then use normal event dispatch.
11661            event.setTargetAccessibilityFocus(false);
11662        }
11663
11664        boolean result = false;
11665
11666        if (mInputEventConsistencyVerifier != null) {
11667            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11668        }
11669
11670        final int actionMasked = event.getActionMasked();
11671        if (actionMasked == MotionEvent.ACTION_DOWN) {
11672            // Defensive cleanup for new gesture
11673            stopNestedScroll();
11674        }
11675
11676        if (onFilterTouchEventForSecurity(event)) {
11677            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11678                result = true;
11679            }
11680            //noinspection SimplifiableIfStatement
11681            ListenerInfo li = mListenerInfo;
11682            if (li != null && li.mOnTouchListener != null
11683                    && (mViewFlags & ENABLED_MASK) == ENABLED
11684                    && li.mOnTouchListener.onTouch(this, event)) {
11685                result = true;
11686            }
11687
11688            if (!result && onTouchEvent(event)) {
11689                result = true;
11690            }
11691        }
11692
11693        if (!result && mInputEventConsistencyVerifier != null) {
11694            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11695        }
11696
11697        // Clean up after nested scrolls if this is the end of a gesture;
11698        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11699        // of the gesture.
11700        if (actionMasked == MotionEvent.ACTION_UP ||
11701                actionMasked == MotionEvent.ACTION_CANCEL ||
11702                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11703            stopNestedScroll();
11704        }
11705
11706        return result;
11707    }
11708
11709    boolean isAccessibilityFocusedViewOrHost() {
11710        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11711                .getAccessibilityFocusedHost() == this);
11712    }
11713
11714    /**
11715     * Filter the touch event to apply security policies.
11716     *
11717     * @param event The motion event to be filtered.
11718     * @return True if the event should be dispatched, false if the event should be dropped.
11719     *
11720     * @see #getFilterTouchesWhenObscured
11721     */
11722    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11723        //noinspection RedundantIfStatement
11724        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11725                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11726            // Window is obscured, drop this touch.
11727            return false;
11728        }
11729        return true;
11730    }
11731
11732    /**
11733     * Pass a trackball motion event down to the focused view.
11734     *
11735     * @param event The motion event to be dispatched.
11736     * @return True if the event was handled by the view, false otherwise.
11737     */
11738    public boolean dispatchTrackballEvent(MotionEvent event) {
11739        if (mInputEventConsistencyVerifier != null) {
11740            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11741        }
11742
11743        return onTrackballEvent(event);
11744    }
11745
11746    /**
11747     * Pass a captured pointer event down to the focused view.
11748     *
11749     * @param event The motion event to be dispatched.
11750     * @return True if the event was handled by the view, false otherwise.
11751     */
11752    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11753        if (!hasPointerCapture()) {
11754            return false;
11755        }
11756        //noinspection SimplifiableIfStatement
11757        ListenerInfo li = mListenerInfo;
11758        if (li != null && li.mOnCapturedPointerListener != null
11759                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11760            return true;
11761        }
11762        return onCapturedPointerEvent(event);
11763    }
11764
11765    /**
11766     * Dispatch a generic motion event.
11767     * <p>
11768     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11769     * are delivered to the view under the pointer.  All other generic motion events are
11770     * delivered to the focused view.  Hover events are handled specially and are delivered
11771     * to {@link #onHoverEvent(MotionEvent)}.
11772     * </p>
11773     *
11774     * @param event The motion event to be dispatched.
11775     * @return True if the event was handled by the view, false otherwise.
11776     */
11777    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11778        if (mInputEventConsistencyVerifier != null) {
11779            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11780        }
11781
11782        final int source = event.getSource();
11783        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11784            final int action = event.getAction();
11785            if (action == MotionEvent.ACTION_HOVER_ENTER
11786                    || action == MotionEvent.ACTION_HOVER_MOVE
11787                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11788                if (dispatchHoverEvent(event)) {
11789                    return true;
11790                }
11791            } else if (dispatchGenericPointerEvent(event)) {
11792                return true;
11793            }
11794        } else if (dispatchGenericFocusedEvent(event)) {
11795            return true;
11796        }
11797
11798        if (dispatchGenericMotionEventInternal(event)) {
11799            return true;
11800        }
11801
11802        if (mInputEventConsistencyVerifier != null) {
11803            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11804        }
11805        return false;
11806    }
11807
11808    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11809        //noinspection SimplifiableIfStatement
11810        ListenerInfo li = mListenerInfo;
11811        if (li != null && li.mOnGenericMotionListener != null
11812                && (mViewFlags & ENABLED_MASK) == ENABLED
11813                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11814            return true;
11815        }
11816
11817        if (onGenericMotionEvent(event)) {
11818            return true;
11819        }
11820
11821        final int actionButton = event.getActionButton();
11822        switch (event.getActionMasked()) {
11823            case MotionEvent.ACTION_BUTTON_PRESS:
11824                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11825                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11826                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11827                    if (performContextClick(event.getX(), event.getY())) {
11828                        mInContextButtonPress = true;
11829                        setPressed(true, event.getX(), event.getY());
11830                        removeTapCallback();
11831                        removeLongPressCallback();
11832                        return true;
11833                    }
11834                }
11835                break;
11836
11837            case MotionEvent.ACTION_BUTTON_RELEASE:
11838                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11839                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11840                    mInContextButtonPress = false;
11841                    mIgnoreNextUpEvent = true;
11842                }
11843                break;
11844        }
11845
11846        if (mInputEventConsistencyVerifier != null) {
11847            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11848        }
11849        return false;
11850    }
11851
11852    /**
11853     * Dispatch a hover event.
11854     * <p>
11855     * Do not call this method directly.
11856     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11857     * </p>
11858     *
11859     * @param event The motion event to be dispatched.
11860     * @return True if the event was handled by the view, false otherwise.
11861     */
11862    protected boolean dispatchHoverEvent(MotionEvent event) {
11863        ListenerInfo li = mListenerInfo;
11864        //noinspection SimplifiableIfStatement
11865        if (li != null && li.mOnHoverListener != null
11866                && (mViewFlags & ENABLED_MASK) == ENABLED
11867                && li.mOnHoverListener.onHover(this, event)) {
11868            return true;
11869        }
11870
11871        return onHoverEvent(event);
11872    }
11873
11874    /**
11875     * Returns true if the view has a child to which it has recently sent
11876     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11877     * it does not have a hovered child, then it must be the innermost hovered view.
11878     * @hide
11879     */
11880    protected boolean hasHoveredChild() {
11881        return false;
11882    }
11883
11884    /**
11885     * Dispatch a generic motion event to the view under the first pointer.
11886     * <p>
11887     * Do not call this method directly.
11888     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11889     * </p>
11890     *
11891     * @param event The motion event to be dispatched.
11892     * @return True if the event was handled by the view, false otherwise.
11893     */
11894    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11895        return false;
11896    }
11897
11898    /**
11899     * Dispatch a generic motion event to the currently focused view.
11900     * <p>
11901     * Do not call this method directly.
11902     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11903     * </p>
11904     *
11905     * @param event The motion event to be dispatched.
11906     * @return True if the event was handled by the view, false otherwise.
11907     */
11908    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11909        return false;
11910    }
11911
11912    /**
11913     * Dispatch a pointer event.
11914     * <p>
11915     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11916     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11917     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11918     * and should not be expected to handle other pointing device features.
11919     * </p>
11920     *
11921     * @param event The motion event to be dispatched.
11922     * @return True if the event was handled by the view, false otherwise.
11923     * @hide
11924     */
11925    public final boolean dispatchPointerEvent(MotionEvent event) {
11926        if (event.isTouchEvent()) {
11927            return dispatchTouchEvent(event);
11928        } else {
11929            return dispatchGenericMotionEvent(event);
11930        }
11931    }
11932
11933    /**
11934     * Called when the window containing this view gains or loses window focus.
11935     * ViewGroups should override to route to their children.
11936     *
11937     * @param hasFocus True if the window containing this view now has focus,
11938     *        false otherwise.
11939     */
11940    public void dispatchWindowFocusChanged(boolean hasFocus) {
11941        onWindowFocusChanged(hasFocus);
11942    }
11943
11944    /**
11945     * Called when the window containing this view gains or loses focus.  Note
11946     * that this is separate from view focus: to receive key events, both
11947     * your view and its window must have focus.  If a window is displayed
11948     * on top of yours that takes input focus, then your own window will lose
11949     * focus but the view focus will remain unchanged.
11950     *
11951     * @param hasWindowFocus True if the window containing this view now has
11952     *        focus, false otherwise.
11953     */
11954    public void onWindowFocusChanged(boolean hasWindowFocus) {
11955        InputMethodManager imm = InputMethodManager.peekInstance();
11956        if (!hasWindowFocus) {
11957            if (isPressed()) {
11958                setPressed(false);
11959            }
11960            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11961            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11962                imm.focusOut(this);
11963            }
11964            removeLongPressCallback();
11965            removeTapCallback();
11966            onFocusLost();
11967        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11968            imm.focusIn(this);
11969        }
11970
11971        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11972
11973        refreshDrawableState();
11974    }
11975
11976    /**
11977     * Returns true if this view is in a window that currently has window focus.
11978     * Note that this is not the same as the view itself having focus.
11979     *
11980     * @return True if this view is in a window that currently has window focus.
11981     */
11982    public boolean hasWindowFocus() {
11983        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11984    }
11985
11986    /**
11987     * Dispatch a view visibility change down the view hierarchy.
11988     * ViewGroups should override to route to their children.
11989     * @param changedView The view whose visibility changed. Could be 'this' or
11990     * an ancestor view.
11991     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11992     * {@link #INVISIBLE} or {@link #GONE}.
11993     */
11994    protected void dispatchVisibilityChanged(@NonNull View changedView,
11995            @Visibility int visibility) {
11996        onVisibilityChanged(changedView, visibility);
11997    }
11998
11999    /**
12000     * Called when the visibility of the view or an ancestor of the view has
12001     * changed.
12002     *
12003     * @param changedView The view whose visibility changed. May be
12004     *                    {@code this} or an ancestor view.
12005     * @param visibility The new visibility, one of {@link #VISIBLE},
12006     *                   {@link #INVISIBLE} or {@link #GONE}.
12007     */
12008    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
12009    }
12010
12011    /**
12012     * Dispatch a hint about whether this view is displayed. For instance, when
12013     * a View moves out of the screen, it might receives a display hint indicating
12014     * the view is not displayed. Applications should not <em>rely</em> on this hint
12015     * as there is no guarantee that they will receive one.
12016     *
12017     * @param hint A hint about whether or not this view is displayed:
12018     * {@link #VISIBLE} or {@link #INVISIBLE}.
12019     */
12020    public void dispatchDisplayHint(@Visibility int hint) {
12021        onDisplayHint(hint);
12022    }
12023
12024    /**
12025     * Gives this view a hint about whether is displayed or not. For instance, when
12026     * a View moves out of the screen, it might receives a display hint indicating
12027     * the view is not displayed. Applications should not <em>rely</em> on this hint
12028     * as there is no guarantee that they will receive one.
12029     *
12030     * @param hint A hint about whether or not this view is displayed:
12031     * {@link #VISIBLE} or {@link #INVISIBLE}.
12032     */
12033    protected void onDisplayHint(@Visibility int hint) {
12034    }
12035
12036    /**
12037     * Dispatch a window visibility change down the view hierarchy.
12038     * ViewGroups should override to route to their children.
12039     *
12040     * @param visibility The new visibility of the window.
12041     *
12042     * @see #onWindowVisibilityChanged(int)
12043     */
12044    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
12045        onWindowVisibilityChanged(visibility);
12046    }
12047
12048    /**
12049     * Called when the window containing has change its visibility
12050     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
12051     * that this tells you whether or not your window is being made visible
12052     * to the window manager; this does <em>not</em> tell you whether or not
12053     * your window is obscured by other windows on the screen, even if it
12054     * is itself visible.
12055     *
12056     * @param visibility The new visibility of the window.
12057     */
12058    protected void onWindowVisibilityChanged(@Visibility int visibility) {
12059        if (visibility == VISIBLE) {
12060            initialAwakenScrollBars();
12061        }
12062    }
12063
12064    /**
12065     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
12066     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
12067     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
12068     *
12069     * @param isVisible true if this view's visibility to the user is uninterrupted by its
12070     *                  ancestors or by window visibility
12071     * @return true if this view is visible to the user, not counting clipping or overlapping
12072     */
12073    boolean dispatchVisibilityAggregated(boolean isVisible) {
12074        final boolean thisVisible = getVisibility() == VISIBLE;
12075        // If we're not visible but something is telling us we are, ignore it.
12076        if (thisVisible || !isVisible) {
12077            onVisibilityAggregated(isVisible);
12078        }
12079        return thisVisible && isVisible;
12080    }
12081
12082    /**
12083     * Called when the user-visibility of this View is potentially affected by a change
12084     * to this view itself, an ancestor view or the window this view is attached to.
12085     *
12086     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
12087     *                  and this view's window is also visible
12088     */
12089    @CallSuper
12090    public void onVisibilityAggregated(boolean isVisible) {
12091        if (isVisible && mAttachInfo != null) {
12092            initialAwakenScrollBars();
12093        }
12094
12095        final Drawable dr = mBackground;
12096        if (dr != null && isVisible != dr.isVisible()) {
12097            dr.setVisible(isVisible, false);
12098        }
12099        final Drawable hl = mDefaultFocusHighlight;
12100        if (hl != null && isVisible != hl.isVisible()) {
12101            hl.setVisible(isVisible, false);
12102        }
12103        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
12104        if (fg != null && isVisible != fg.isVisible()) {
12105            fg.setVisible(isVisible, false);
12106        }
12107
12108        if (isAutofillable()) {
12109            AutofillManager afm = getAutofillManager();
12110
12111            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
12112                if (mVisibilityChangeForAutofillHandler != null) {
12113                    mVisibilityChangeForAutofillHandler.removeMessages(0);
12114                }
12115
12116                // If the view is in the background but still part of the hierarchy this is called
12117                // with isVisible=false. Hence visibility==false requires further checks
12118                if (isVisible) {
12119                    afm.notifyViewVisibilityChange(this, true);
12120                } else {
12121                    if (mVisibilityChangeForAutofillHandler == null) {
12122                        mVisibilityChangeForAutofillHandler =
12123                                new VisibilityChangeForAutofillHandler(afm, this);
12124                    }
12125                    // Let current operation (e.g. removal of the view from the hierarchy)
12126                    // finish before checking state
12127                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
12128                }
12129            }
12130        }
12131    }
12132
12133    /**
12134     * Returns the current visibility of the window this view is attached to
12135     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
12136     *
12137     * @return Returns the current visibility of the view's window.
12138     */
12139    @Visibility
12140    public int getWindowVisibility() {
12141        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
12142    }
12143
12144    /**
12145     * Retrieve the overall visible display size in which the window this view is
12146     * attached to has been positioned in.  This takes into account screen
12147     * decorations above the window, for both cases where the window itself
12148     * is being position inside of them or the window is being placed under
12149     * then and covered insets are used for the window to position its content
12150     * inside.  In effect, this tells you the available area where content can
12151     * be placed and remain visible to users.
12152     *
12153     * <p>This function requires an IPC back to the window manager to retrieve
12154     * the requested information, so should not be used in performance critical
12155     * code like drawing.
12156     *
12157     * @param outRect Filled in with the visible display frame.  If the view
12158     * is not attached to a window, this is simply the raw display size.
12159     */
12160    public void getWindowVisibleDisplayFrame(Rect outRect) {
12161        if (mAttachInfo != null) {
12162            try {
12163                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12164            } catch (RemoteException e) {
12165                return;
12166            }
12167            // XXX This is really broken, and probably all needs to be done
12168            // in the window manager, and we need to know more about whether
12169            // we want the area behind or in front of the IME.
12170            final Rect insets = mAttachInfo.mVisibleInsets;
12171            outRect.left += insets.left;
12172            outRect.top += insets.top;
12173            outRect.right -= insets.right;
12174            outRect.bottom -= insets.bottom;
12175            return;
12176        }
12177        // The view is not attached to a display so we don't have a context.
12178        // Make a best guess about the display size.
12179        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12180        d.getRectSize(outRect);
12181    }
12182
12183    /**
12184     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
12185     * is currently in without any insets.
12186     *
12187     * @hide
12188     */
12189    public void getWindowDisplayFrame(Rect outRect) {
12190        if (mAttachInfo != null) {
12191            try {
12192                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12193            } catch (RemoteException e) {
12194                return;
12195            }
12196            return;
12197        }
12198        // The view is not attached to a display so we don't have a context.
12199        // Make a best guess about the display size.
12200        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12201        d.getRectSize(outRect);
12202    }
12203
12204    /**
12205     * Dispatch a notification about a resource configuration change down
12206     * the view hierarchy.
12207     * ViewGroups should override to route to their children.
12208     *
12209     * @param newConfig The new resource configuration.
12210     *
12211     * @see #onConfigurationChanged(android.content.res.Configuration)
12212     */
12213    public void dispatchConfigurationChanged(Configuration newConfig) {
12214        onConfigurationChanged(newConfig);
12215    }
12216
12217    /**
12218     * Called when the current configuration of the resources being used
12219     * by the application have changed.  You can use this to decide when
12220     * to reload resources that can changed based on orientation and other
12221     * configuration characteristics.  You only need to use this if you are
12222     * not relying on the normal {@link android.app.Activity} mechanism of
12223     * recreating the activity instance upon a configuration change.
12224     *
12225     * @param newConfig The new resource configuration.
12226     */
12227    protected void onConfigurationChanged(Configuration newConfig) {
12228    }
12229
12230    /**
12231     * Private function to aggregate all per-view attributes in to the view
12232     * root.
12233     */
12234    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12235        performCollectViewAttributes(attachInfo, visibility);
12236    }
12237
12238    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12239        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
12240            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
12241                attachInfo.mKeepScreenOn = true;
12242            }
12243            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
12244            ListenerInfo li = mListenerInfo;
12245            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
12246                attachInfo.mHasSystemUiListeners = true;
12247            }
12248        }
12249    }
12250
12251    void needGlobalAttributesUpdate(boolean force) {
12252        final AttachInfo ai = mAttachInfo;
12253        if (ai != null && !ai.mRecomputeGlobalAttributes) {
12254            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
12255                    || ai.mHasSystemUiListeners) {
12256                ai.mRecomputeGlobalAttributes = true;
12257            }
12258        }
12259    }
12260
12261    /**
12262     * Returns whether the device is currently in touch mode.  Touch mode is entered
12263     * once the user begins interacting with the device by touch, and affects various
12264     * things like whether focus is always visible to the user.
12265     *
12266     * @return Whether the device is in touch mode.
12267     */
12268    @ViewDebug.ExportedProperty
12269    public boolean isInTouchMode() {
12270        if (mAttachInfo != null) {
12271            return mAttachInfo.mInTouchMode;
12272        } else {
12273            return ViewRootImpl.isInTouchMode();
12274        }
12275    }
12276
12277    /**
12278     * Returns the context the view is running in, through which it can
12279     * access the current theme, resources, etc.
12280     *
12281     * @return The view's Context.
12282     */
12283    @ViewDebug.CapturedViewProperty
12284    public final Context getContext() {
12285        return mContext;
12286    }
12287
12288    /**
12289     * Handle a key event before it is processed by any input method
12290     * associated with the view hierarchy.  This can be used to intercept
12291     * key events in special situations before the IME consumes them; a
12292     * typical example would be handling the BACK key to update the application's
12293     * UI instead of allowing the IME to see it and close itself.
12294     *
12295     * @param keyCode The value in event.getKeyCode().
12296     * @param event Description of the key event.
12297     * @return If you handled the event, return true. If you want to allow the
12298     *         event to be handled by the next receiver, return false.
12299     */
12300    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
12301        return false;
12302    }
12303
12304    /**
12305     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12306     * KeyEvent.Callback.onKeyDown()}: perform press of the view
12307     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12308     * is released, if the view is enabled and clickable.
12309     * <p>
12310     * Key presses in software keyboards will generally NOT trigger this
12311     * listener, although some may elect to do so in some situations. Do not
12312     * rely on this to catch software key presses.
12313     *
12314     * @param keyCode a key code that represents the button pressed, from
12315     *                {@link android.view.KeyEvent}
12316     * @param event the KeyEvent object that defines the button action
12317     */
12318    public boolean onKeyDown(int keyCode, KeyEvent event) {
12319        if (KeyEvent.isConfirmKey(keyCode)) {
12320            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12321                return true;
12322            }
12323
12324            if (event.getRepeatCount() == 0) {
12325                // Long clickable items don't necessarily have to be clickable.
12326                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12327                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12328                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12329                    // For the purposes of menu anchoring and drawable hotspots,
12330                    // key events are considered to be at the center of the view.
12331                    final float x = getWidth() / 2f;
12332                    final float y = getHeight() / 2f;
12333                    if (clickable) {
12334                        setPressed(true, x, y);
12335                    }
12336                    checkForLongClick(0, x, y);
12337                    return true;
12338                }
12339            }
12340        }
12341
12342        return false;
12343    }
12344
12345    /**
12346     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12347     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12348     * the event).
12349     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12350     * although some may elect to do so in some situations. Do not rely on this to
12351     * catch software key presses.
12352     */
12353    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12354        return false;
12355    }
12356
12357    /**
12358     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12359     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12360     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12361     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12362     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12363     * although some may elect to do so in some situations. Do not rely on this to
12364     * catch software key presses.
12365     *
12366     * @param keyCode A key code that represents the button pressed, from
12367     *                {@link android.view.KeyEvent}.
12368     * @param event   The KeyEvent object that defines the button action.
12369     */
12370    public boolean onKeyUp(int keyCode, KeyEvent event) {
12371        if (KeyEvent.isConfirmKey(keyCode)) {
12372            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12373                return true;
12374            }
12375            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12376                setPressed(false);
12377
12378                if (!mHasPerformedLongPress) {
12379                    // This is a tap, so remove the longpress check
12380                    removeLongPressCallback();
12381                    if (!event.isCanceled()) {
12382                        return performClick();
12383                    }
12384                }
12385            }
12386        }
12387        return false;
12388    }
12389
12390    /**
12391     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12392     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12393     * the event).
12394     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12395     * although some may elect to do so in some situations. Do not rely on this to
12396     * catch software key presses.
12397     *
12398     * @param keyCode     A key code that represents the button pressed, from
12399     *                    {@link android.view.KeyEvent}.
12400     * @param repeatCount The number of times the action was made.
12401     * @param event       The KeyEvent object that defines the button action.
12402     */
12403    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12404        return false;
12405    }
12406
12407    /**
12408     * Called on the focused view when a key shortcut event is not handled.
12409     * Override this method to implement local key shortcuts for the View.
12410     * Key shortcuts can also be implemented by setting the
12411     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12412     *
12413     * @param keyCode The value in event.getKeyCode().
12414     * @param event Description of the key event.
12415     * @return If you handled the event, return true. If you want to allow the
12416     *         event to be handled by the next receiver, return false.
12417     */
12418    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12419        return false;
12420    }
12421
12422    /**
12423     * Check whether the called view is a text editor, in which case it
12424     * would make sense to automatically display a soft input window for
12425     * it.  Subclasses should override this if they implement
12426     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12427     * a call on that method would return a non-null InputConnection, and
12428     * they are really a first-class editor that the user would normally
12429     * start typing on when the go into a window containing your view.
12430     *
12431     * <p>The default implementation always returns false.  This does
12432     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12433     * will not be called or the user can not otherwise perform edits on your
12434     * view; it is just a hint to the system that this is not the primary
12435     * purpose of this view.
12436     *
12437     * @return Returns true if this view is a text editor, else false.
12438     */
12439    public boolean onCheckIsTextEditor() {
12440        return false;
12441    }
12442
12443    /**
12444     * Create a new InputConnection for an InputMethod to interact
12445     * with the view.  The default implementation returns null, since it doesn't
12446     * support input methods.  You can override this to implement such support.
12447     * This is only needed for views that take focus and text input.
12448     *
12449     * <p>When implementing this, you probably also want to implement
12450     * {@link #onCheckIsTextEditor()} to indicate you will return a
12451     * non-null InputConnection.</p>
12452     *
12453     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12454     * object correctly and in its entirety, so that the connected IME can rely
12455     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12456     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12457     * must be filled in with the correct cursor position for IMEs to work correctly
12458     * with your application.</p>
12459     *
12460     * @param outAttrs Fill in with attribute information about the connection.
12461     */
12462    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12463        return null;
12464    }
12465
12466    /**
12467     * Called by the {@link android.view.inputmethod.InputMethodManager}
12468     * when a view who is not the current
12469     * input connection target is trying to make a call on the manager.  The
12470     * default implementation returns false; you can override this to return
12471     * true for certain views if you are performing InputConnection proxying
12472     * to them.
12473     * @param view The View that is making the InputMethodManager call.
12474     * @return Return true to allow the call, false to reject.
12475     */
12476    public boolean checkInputConnectionProxy(View view) {
12477        return false;
12478    }
12479
12480    /**
12481     * Show the context menu for this view. It is not safe to hold on to the
12482     * menu after returning from this method.
12483     *
12484     * You should normally not overload this method. Overload
12485     * {@link #onCreateContextMenu(ContextMenu)} or define an
12486     * {@link OnCreateContextMenuListener} to add items to the context menu.
12487     *
12488     * @param menu The context menu to populate
12489     */
12490    public void createContextMenu(ContextMenu menu) {
12491        ContextMenuInfo menuInfo = getContextMenuInfo();
12492
12493        // Sets the current menu info so all items added to menu will have
12494        // my extra info set.
12495        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12496
12497        onCreateContextMenu(menu);
12498        ListenerInfo li = mListenerInfo;
12499        if (li != null && li.mOnCreateContextMenuListener != null) {
12500            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12501        }
12502
12503        // Clear the extra information so subsequent items that aren't mine don't
12504        // have my extra info.
12505        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12506
12507        if (mParent != null) {
12508            mParent.createContextMenu(menu);
12509        }
12510    }
12511
12512    /**
12513     * Views should implement this if they have extra information to associate
12514     * with the context menu. The return result is supplied as a parameter to
12515     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12516     * callback.
12517     *
12518     * @return Extra information about the item for which the context menu
12519     *         should be shown. This information will vary across different
12520     *         subclasses of View.
12521     */
12522    protected ContextMenuInfo getContextMenuInfo() {
12523        return null;
12524    }
12525
12526    /**
12527     * Views should implement this if the view itself is going to add items to
12528     * the context menu.
12529     *
12530     * @param menu the context menu to populate
12531     */
12532    protected void onCreateContextMenu(ContextMenu menu) {
12533    }
12534
12535    /**
12536     * Implement this method to handle trackball motion events.  The
12537     * <em>relative</em> movement of the trackball since the last event
12538     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12539     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12540     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12541     * they will often be fractional values, representing the more fine-grained
12542     * movement information available from a trackball).
12543     *
12544     * @param event The motion event.
12545     * @return True if the event was handled, false otherwise.
12546     */
12547    public boolean onTrackballEvent(MotionEvent event) {
12548        return false;
12549    }
12550
12551    /**
12552     * Implement this method to handle generic motion events.
12553     * <p>
12554     * Generic motion events describe joystick movements, mouse hovers, track pad
12555     * touches, scroll wheel movements and other input events.  The
12556     * {@link MotionEvent#getSource() source} of the motion event specifies
12557     * the class of input that was received.  Implementations of this method
12558     * must examine the bits in the source before processing the event.
12559     * The following code example shows how this is done.
12560     * </p><p>
12561     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12562     * are delivered to the view under the pointer.  All other generic motion events are
12563     * delivered to the focused view.
12564     * </p>
12565     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12566     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12567     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12568     *             // process the joystick movement...
12569     *             return true;
12570     *         }
12571     *     }
12572     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12573     *         switch (event.getAction()) {
12574     *             case MotionEvent.ACTION_HOVER_MOVE:
12575     *                 // process the mouse hover movement...
12576     *                 return true;
12577     *             case MotionEvent.ACTION_SCROLL:
12578     *                 // process the scroll wheel movement...
12579     *                 return true;
12580     *         }
12581     *     }
12582     *     return super.onGenericMotionEvent(event);
12583     * }</pre>
12584     *
12585     * @param event The generic motion event being processed.
12586     * @return True if the event was handled, false otherwise.
12587     */
12588    public boolean onGenericMotionEvent(MotionEvent event) {
12589        return false;
12590    }
12591
12592    /**
12593     * Implement this method to handle hover events.
12594     * <p>
12595     * This method is called whenever a pointer is hovering into, over, or out of the
12596     * bounds of a view and the view is not currently being touched.
12597     * Hover events are represented as pointer events with action
12598     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12599     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12600     * </p>
12601     * <ul>
12602     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12603     * when the pointer enters the bounds of the view.</li>
12604     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12605     * when the pointer has already entered the bounds of the view and has moved.</li>
12606     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12607     * when the pointer has exited the bounds of the view or when the pointer is
12608     * about to go down due to a button click, tap, or similar user action that
12609     * causes the view to be touched.</li>
12610     * </ul>
12611     * <p>
12612     * The view should implement this method to return true to indicate that it is
12613     * handling the hover event, such as by changing its drawable state.
12614     * </p><p>
12615     * The default implementation calls {@link #setHovered} to update the hovered state
12616     * of the view when a hover enter or hover exit event is received, if the view
12617     * is enabled and is clickable.  The default implementation also sends hover
12618     * accessibility events.
12619     * </p>
12620     *
12621     * @param event The motion event that describes the hover.
12622     * @return True if the view handled the hover event.
12623     *
12624     * @see #isHovered
12625     * @see #setHovered
12626     * @see #onHoverChanged
12627     */
12628    public boolean onHoverEvent(MotionEvent event) {
12629        // The root view may receive hover (or touch) events that are outside the bounds of
12630        // the window.  This code ensures that we only send accessibility events for
12631        // hovers that are actually within the bounds of the root view.
12632        final int action = event.getActionMasked();
12633        if (!mSendingHoverAccessibilityEvents) {
12634            if ((action == MotionEvent.ACTION_HOVER_ENTER
12635                    || action == MotionEvent.ACTION_HOVER_MOVE)
12636                    && !hasHoveredChild()
12637                    && pointInView(event.getX(), event.getY())) {
12638                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12639                mSendingHoverAccessibilityEvents = true;
12640            }
12641        } else {
12642            if (action == MotionEvent.ACTION_HOVER_EXIT
12643                    || (action == MotionEvent.ACTION_MOVE
12644                            && !pointInView(event.getX(), event.getY()))) {
12645                mSendingHoverAccessibilityEvents = false;
12646                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12647            }
12648        }
12649
12650        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12651                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12652                && isOnScrollbar(event.getX(), event.getY())) {
12653            awakenScrollBars();
12654        }
12655
12656        // If we consider ourself hoverable, or if we we're already hovered,
12657        // handle changing state in response to ENTER and EXIT events.
12658        if (isHoverable() || isHovered()) {
12659            switch (action) {
12660                case MotionEvent.ACTION_HOVER_ENTER:
12661                    setHovered(true);
12662                    break;
12663                case MotionEvent.ACTION_HOVER_EXIT:
12664                    setHovered(false);
12665                    break;
12666            }
12667
12668            // Dispatch the event to onGenericMotionEvent before returning true.
12669            // This is to provide compatibility with existing applications that
12670            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12671            // break because of the new default handling for hoverable views
12672            // in onHoverEvent.
12673            // Note that onGenericMotionEvent will be called by default when
12674            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12675            dispatchGenericMotionEventInternal(event);
12676            // The event was already handled by calling setHovered(), so always
12677            // return true.
12678            return true;
12679        }
12680
12681        return false;
12682    }
12683
12684    /**
12685     * Returns true if the view should handle {@link #onHoverEvent}
12686     * by calling {@link #setHovered} to change its hovered state.
12687     *
12688     * @return True if the view is hoverable.
12689     */
12690    private boolean isHoverable() {
12691        final int viewFlags = mViewFlags;
12692        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12693            return false;
12694        }
12695
12696        return (viewFlags & CLICKABLE) == CLICKABLE
12697                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12698                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12699    }
12700
12701    /**
12702     * Returns true if the view is currently hovered.
12703     *
12704     * @return True if the view is currently hovered.
12705     *
12706     * @see #setHovered
12707     * @see #onHoverChanged
12708     */
12709    @ViewDebug.ExportedProperty
12710    public boolean isHovered() {
12711        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12712    }
12713
12714    /**
12715     * Sets whether the view is currently hovered.
12716     * <p>
12717     * Calling this method also changes the drawable state of the view.  This
12718     * enables the view to react to hover by using different drawable resources
12719     * to change its appearance.
12720     * </p><p>
12721     * The {@link #onHoverChanged} method is called when the hovered state changes.
12722     * </p>
12723     *
12724     * @param hovered True if the view is hovered.
12725     *
12726     * @see #isHovered
12727     * @see #onHoverChanged
12728     */
12729    public void setHovered(boolean hovered) {
12730        if (hovered) {
12731            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12732                mPrivateFlags |= PFLAG_HOVERED;
12733                refreshDrawableState();
12734                onHoverChanged(true);
12735            }
12736        } else {
12737            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12738                mPrivateFlags &= ~PFLAG_HOVERED;
12739                refreshDrawableState();
12740                onHoverChanged(false);
12741            }
12742        }
12743    }
12744
12745    /**
12746     * Implement this method to handle hover state changes.
12747     * <p>
12748     * This method is called whenever the hover state changes as a result of a
12749     * call to {@link #setHovered}.
12750     * </p>
12751     *
12752     * @param hovered The current hover state, as returned by {@link #isHovered}.
12753     *
12754     * @see #isHovered
12755     * @see #setHovered
12756     */
12757    public void onHoverChanged(boolean hovered) {
12758    }
12759
12760    /**
12761     * Handles scroll bar dragging by mouse input.
12762     *
12763     * @hide
12764     * @param event The motion event.
12765     *
12766     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12767     */
12768    protected boolean handleScrollBarDragging(MotionEvent event) {
12769        if (mScrollCache == null) {
12770            return false;
12771        }
12772        final float x = event.getX();
12773        final float y = event.getY();
12774        final int action = event.getAction();
12775        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12776                && action != MotionEvent.ACTION_DOWN)
12777                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12778                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12779            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12780            return false;
12781        }
12782
12783        switch (action) {
12784            case MotionEvent.ACTION_MOVE:
12785                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12786                    return false;
12787                }
12788                if (mScrollCache.mScrollBarDraggingState
12789                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12790                    final Rect bounds = mScrollCache.mScrollBarBounds;
12791                    getVerticalScrollBarBounds(bounds, null);
12792                    final int range = computeVerticalScrollRange();
12793                    final int offset = computeVerticalScrollOffset();
12794                    final int extent = computeVerticalScrollExtent();
12795
12796                    final int thumbLength = ScrollBarUtils.getThumbLength(
12797                            bounds.height(), bounds.width(), extent, range);
12798                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12799                            bounds.height(), thumbLength, extent, range, offset);
12800
12801                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12802                    final float maxThumbOffset = bounds.height() - thumbLength;
12803                    final float newThumbOffset =
12804                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12805                    final int height = getHeight();
12806                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12807                            && height > 0 && extent > 0) {
12808                        final int newY = Math.round((range - extent)
12809                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12810                        if (newY != getScrollY()) {
12811                            mScrollCache.mScrollBarDraggingPos = y;
12812                            setScrollY(newY);
12813                        }
12814                    }
12815                    return true;
12816                }
12817                if (mScrollCache.mScrollBarDraggingState
12818                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12819                    final Rect bounds = mScrollCache.mScrollBarBounds;
12820                    getHorizontalScrollBarBounds(bounds, null);
12821                    final int range = computeHorizontalScrollRange();
12822                    final int offset = computeHorizontalScrollOffset();
12823                    final int extent = computeHorizontalScrollExtent();
12824
12825                    final int thumbLength = ScrollBarUtils.getThumbLength(
12826                            bounds.width(), bounds.height(), extent, range);
12827                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12828                            bounds.width(), thumbLength, extent, range, offset);
12829
12830                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12831                    final float maxThumbOffset = bounds.width() - thumbLength;
12832                    final float newThumbOffset =
12833                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12834                    final int width = getWidth();
12835                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12836                            && width > 0 && extent > 0) {
12837                        final int newX = Math.round((range - extent)
12838                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12839                        if (newX != getScrollX()) {
12840                            mScrollCache.mScrollBarDraggingPos = x;
12841                            setScrollX(newX);
12842                        }
12843                    }
12844                    return true;
12845                }
12846            case MotionEvent.ACTION_DOWN:
12847                if (mScrollCache.state == ScrollabilityCache.OFF) {
12848                    return false;
12849                }
12850                if (isOnVerticalScrollbarThumb(x, y)) {
12851                    mScrollCache.mScrollBarDraggingState =
12852                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12853                    mScrollCache.mScrollBarDraggingPos = y;
12854                    return true;
12855                }
12856                if (isOnHorizontalScrollbarThumb(x, y)) {
12857                    mScrollCache.mScrollBarDraggingState =
12858                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12859                    mScrollCache.mScrollBarDraggingPos = x;
12860                    return true;
12861                }
12862        }
12863        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12864        return false;
12865    }
12866
12867    /**
12868     * Implement this method to handle touch screen motion events.
12869     * <p>
12870     * If this method is used to detect click actions, it is recommended that
12871     * the actions be performed by implementing and calling
12872     * {@link #performClick()}. This will ensure consistent system behavior,
12873     * including:
12874     * <ul>
12875     * <li>obeying click sound preferences
12876     * <li>dispatching OnClickListener calls
12877     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12878     * accessibility features are enabled
12879     * </ul>
12880     *
12881     * @param event The motion event.
12882     * @return True if the event was handled, false otherwise.
12883     */
12884    public boolean onTouchEvent(MotionEvent event) {
12885        final float x = event.getX();
12886        final float y = event.getY();
12887        final int viewFlags = mViewFlags;
12888        final int action = event.getAction();
12889
12890        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12891                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12892                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12893
12894        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12895            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12896                setPressed(false);
12897            }
12898            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12899            // A disabled view that is clickable still consumes the touch
12900            // events, it just doesn't respond to them.
12901            return clickable;
12902        }
12903        if (mTouchDelegate != null) {
12904            if (mTouchDelegate.onTouchEvent(event)) {
12905                return true;
12906            }
12907        }
12908
12909        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12910            switch (action) {
12911                case MotionEvent.ACTION_UP:
12912                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12913                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12914                        handleTooltipUp();
12915                    }
12916                    if (!clickable) {
12917                        removeTapCallback();
12918                        removeLongPressCallback();
12919                        mInContextButtonPress = false;
12920                        mHasPerformedLongPress = false;
12921                        mIgnoreNextUpEvent = false;
12922                        break;
12923                    }
12924                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12925                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12926                        // take focus if we don't have it already and we should in
12927                        // touch mode.
12928                        boolean focusTaken = false;
12929                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12930                            focusTaken = requestFocus();
12931                        }
12932
12933                        if (prepressed) {
12934                            // The button is being released before we actually
12935                            // showed it as pressed.  Make it show the pressed
12936                            // state now (before scheduling the click) to ensure
12937                            // the user sees it.
12938                            setPressed(true, x, y);
12939                        }
12940
12941                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12942                            // This is a tap, so remove the longpress check
12943                            removeLongPressCallback();
12944
12945                            // Only perform take click actions if we were in the pressed state
12946                            if (!focusTaken) {
12947                                // Use a Runnable and post this rather than calling
12948                                // performClick directly. This lets other visual state
12949                                // of the view update before click actions start.
12950                                if (mPerformClick == null) {
12951                                    mPerformClick = new PerformClick();
12952                                }
12953                                if (!post(mPerformClick)) {
12954                                    performClick();
12955                                }
12956                            }
12957                        }
12958
12959                        if (mUnsetPressedState == null) {
12960                            mUnsetPressedState = new UnsetPressedState();
12961                        }
12962
12963                        if (prepressed) {
12964                            postDelayed(mUnsetPressedState,
12965                                    ViewConfiguration.getPressedStateDuration());
12966                        } else if (!post(mUnsetPressedState)) {
12967                            // If the post failed, unpress right now
12968                            mUnsetPressedState.run();
12969                        }
12970
12971                        removeTapCallback();
12972                    }
12973                    mIgnoreNextUpEvent = false;
12974                    break;
12975
12976                case MotionEvent.ACTION_DOWN:
12977                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12978                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12979                    }
12980                    mHasPerformedLongPress = false;
12981
12982                    if (!clickable) {
12983                        checkForLongClick(0, x, y);
12984                        break;
12985                    }
12986
12987                    if (performButtonActionOnTouchDown(event)) {
12988                        break;
12989                    }
12990
12991                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12992                    boolean isInScrollingContainer = isInScrollingContainer();
12993
12994                    // For views inside a scrolling container, delay the pressed feedback for
12995                    // a short period in case this is a scroll.
12996                    if (isInScrollingContainer) {
12997                        mPrivateFlags |= PFLAG_PREPRESSED;
12998                        if (mPendingCheckForTap == null) {
12999                            mPendingCheckForTap = new CheckForTap();
13000                        }
13001                        mPendingCheckForTap.x = event.getX();
13002                        mPendingCheckForTap.y = event.getY();
13003                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
13004                    } else {
13005                        // Not inside a scrolling container, so show the feedback right away
13006                        setPressed(true, x, y);
13007                        checkForLongClick(0, x, y);
13008                    }
13009                    break;
13010
13011                case MotionEvent.ACTION_CANCEL:
13012                    if (clickable) {
13013                        setPressed(false);
13014                    }
13015                    removeTapCallback();
13016                    removeLongPressCallback();
13017                    mInContextButtonPress = false;
13018                    mHasPerformedLongPress = false;
13019                    mIgnoreNextUpEvent = false;
13020                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13021                    break;
13022
13023                case MotionEvent.ACTION_MOVE:
13024                    if (clickable) {
13025                        drawableHotspotChanged(x, y);
13026                    }
13027
13028                    // Be lenient about moving outside of buttons
13029                    if (!pointInView(x, y, mTouchSlop)) {
13030                        // Outside button
13031                        // Remove any future long press/tap checks
13032                        removeTapCallback();
13033                        removeLongPressCallback();
13034                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
13035                            setPressed(false);
13036                        }
13037                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13038                    }
13039                    break;
13040            }
13041
13042            return true;
13043        }
13044
13045        return false;
13046    }
13047
13048    /**
13049     * @hide
13050     */
13051    public boolean isInScrollingContainer() {
13052        ViewParent p = getParent();
13053        while (p != null && p instanceof ViewGroup) {
13054            if (((ViewGroup) p).shouldDelayChildPressedState()) {
13055                return true;
13056            }
13057            p = p.getParent();
13058        }
13059        return false;
13060    }
13061
13062    /**
13063     * Remove the longpress detection timer.
13064     */
13065    private void removeLongPressCallback() {
13066        if (mPendingCheckForLongPress != null) {
13067            removeCallbacks(mPendingCheckForLongPress);
13068        }
13069    }
13070
13071    /**
13072     * Remove the pending click action
13073     */
13074    private void removePerformClickCallback() {
13075        if (mPerformClick != null) {
13076            removeCallbacks(mPerformClick);
13077        }
13078    }
13079
13080    /**
13081     * Remove the prepress detection timer.
13082     */
13083    private void removeUnsetPressCallback() {
13084        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
13085            setPressed(false);
13086            removeCallbacks(mUnsetPressedState);
13087        }
13088    }
13089
13090    /**
13091     * Remove the tap detection timer.
13092     */
13093    private void removeTapCallback() {
13094        if (mPendingCheckForTap != null) {
13095            mPrivateFlags &= ~PFLAG_PREPRESSED;
13096            removeCallbacks(mPendingCheckForTap);
13097        }
13098    }
13099
13100    /**
13101     * Cancels a pending long press.  Your subclass can use this if you
13102     * want the context menu to come up if the user presses and holds
13103     * at the same place, but you don't want it to come up if they press
13104     * and then move around enough to cause scrolling.
13105     */
13106    public void cancelLongPress() {
13107        removeLongPressCallback();
13108
13109        /*
13110         * The prepressed state handled by the tap callback is a display
13111         * construct, but the tap callback will post a long press callback
13112         * less its own timeout. Remove it here.
13113         */
13114        removeTapCallback();
13115    }
13116
13117    /**
13118     * Remove the pending callback for sending a
13119     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
13120     */
13121    private void removeSendViewScrolledAccessibilityEventCallback() {
13122        if (mSendViewScrolledAccessibilityEvent != null) {
13123            removeCallbacks(mSendViewScrolledAccessibilityEvent);
13124            mSendViewScrolledAccessibilityEvent.mIsPending = false;
13125        }
13126    }
13127
13128    /**
13129     * Sets the TouchDelegate for this View.
13130     */
13131    public void setTouchDelegate(TouchDelegate delegate) {
13132        mTouchDelegate = delegate;
13133    }
13134
13135    /**
13136     * Gets the TouchDelegate for this View.
13137     */
13138    public TouchDelegate getTouchDelegate() {
13139        return mTouchDelegate;
13140    }
13141
13142    /**
13143     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
13144     *
13145     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
13146     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
13147     * available. This method should only be called for touch events.
13148     *
13149     * <p class="note">This api is not intended for most applications. Buffered dispatch
13150     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
13151     * streams will not improve your input latency. Side effects include: increased latency,
13152     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13153     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13154     * you.</p>
13155     */
13156    public final void requestUnbufferedDispatch(MotionEvent event) {
13157        final int action = event.getAction();
13158        if (mAttachInfo == null
13159                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13160                || !event.isTouchEvent()) {
13161            return;
13162        }
13163        mAttachInfo.mUnbufferedDispatchRequested = true;
13164    }
13165
13166    /**
13167     * Set flags controlling behavior of this view.
13168     *
13169     * @param flags Constant indicating the value which should be set
13170     * @param mask Constant indicating the bit range that should be changed
13171     */
13172    void setFlags(int flags, int mask) {
13173        final boolean accessibilityEnabled =
13174                AccessibilityManager.getInstance(mContext).isEnabled();
13175        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
13176
13177        int old = mViewFlags;
13178        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
13179
13180        int changed = mViewFlags ^ old;
13181        if (changed == 0) {
13182            return;
13183        }
13184        int privateFlags = mPrivateFlags;
13185
13186        // If focusable is auto, update the FOCUSABLE bit.
13187        int focusableChangedByAuto = 0;
13188        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
13189                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
13190            // Heuristic only takes into account whether view is clickable.
13191            final int newFocus;
13192            if ((mViewFlags & CLICKABLE) != 0) {
13193                newFocus = FOCUSABLE;
13194            } else {
13195                newFocus = NOT_FOCUSABLE;
13196            }
13197            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
13198            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
13199            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
13200        }
13201
13202        /* Check if the FOCUSABLE bit has changed */
13203        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
13204            if (((old & FOCUSABLE) == FOCUSABLE)
13205                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
13206                /* Give up focus if we are no longer focusable */
13207                clearFocus();
13208            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
13209                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
13210                /*
13211                 * Tell the view system that we are now available to take focus
13212                 * if no one else already has it.
13213                 */
13214                if (mParent != null) {
13215                    ViewRootImpl viewRootImpl = getViewRootImpl();
13216                    if (!sAutoFocusableOffUIThreadWontNotifyParents
13217                            || focusableChangedByAuto == 0
13218                            || viewRootImpl == null
13219                            || viewRootImpl.mThread == Thread.currentThread()) {
13220                        mParent.focusableViewAvailable(this);
13221                    }
13222                }
13223            }
13224        }
13225
13226        final int newVisibility = flags & VISIBILITY_MASK;
13227        if (newVisibility == VISIBLE) {
13228            if ((changed & VISIBILITY_MASK) != 0) {
13229                /*
13230                 * If this view is becoming visible, invalidate it in case it changed while
13231                 * it was not visible. Marking it drawn ensures that the invalidation will
13232                 * go through.
13233                 */
13234                mPrivateFlags |= PFLAG_DRAWN;
13235                invalidate(true);
13236
13237                needGlobalAttributesUpdate(true);
13238
13239                // a view becoming visible is worth notifying the parent
13240                // about in case nothing has focus.  even if this specific view
13241                // isn't focusable, it may contain something that is, so let
13242                // the root view try to give this focus if nothing else does.
13243                if ((mParent != null)) {
13244                    mParent.focusableViewAvailable(this);
13245                }
13246            }
13247        }
13248
13249        /* Check if the GONE bit has changed */
13250        if ((changed & GONE) != 0) {
13251            needGlobalAttributesUpdate(false);
13252            requestLayout();
13253
13254            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
13255                if (hasFocus()) clearFocus();
13256                clearAccessibilityFocus();
13257                destroyDrawingCache();
13258                if (mParent instanceof View) {
13259                    // GONE views noop invalidation, so invalidate the parent
13260                    ((View) mParent).invalidate(true);
13261                }
13262                // Mark the view drawn to ensure that it gets invalidated properly the next
13263                // time it is visible and gets invalidated
13264                mPrivateFlags |= PFLAG_DRAWN;
13265            }
13266            if (mAttachInfo != null) {
13267                mAttachInfo.mViewVisibilityChanged = true;
13268            }
13269        }
13270
13271        /* Check if the VISIBLE bit has changed */
13272        if ((changed & INVISIBLE) != 0) {
13273            needGlobalAttributesUpdate(false);
13274            /*
13275             * If this view is becoming invisible, set the DRAWN flag so that
13276             * the next invalidate() will not be skipped.
13277             */
13278            mPrivateFlags |= PFLAG_DRAWN;
13279
13280            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
13281                // root view becoming invisible shouldn't clear focus and accessibility focus
13282                if (getRootView() != this) {
13283                    if (hasFocus()) clearFocus();
13284                    clearAccessibilityFocus();
13285                }
13286            }
13287            if (mAttachInfo != null) {
13288                mAttachInfo.mViewVisibilityChanged = true;
13289            }
13290        }
13291
13292        if ((changed & VISIBILITY_MASK) != 0) {
13293            // If the view is invisible, cleanup its display list to free up resources
13294            if (newVisibility != VISIBLE && mAttachInfo != null) {
13295                cleanupDraw();
13296            }
13297
13298            if (mParent instanceof ViewGroup) {
13299                ((ViewGroup) mParent).onChildVisibilityChanged(this,
13300                        (changed & VISIBILITY_MASK), newVisibility);
13301                ((View) mParent).invalidate(true);
13302            } else if (mParent != null) {
13303                mParent.invalidateChild(this, null);
13304            }
13305
13306            if (mAttachInfo != null) {
13307                dispatchVisibilityChanged(this, newVisibility);
13308
13309                // Aggregated visibility changes are dispatched to attached views
13310                // in visible windows where the parent is currently shown/drawn
13311                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13312                // discounting clipping or overlapping. This makes it a good place
13313                // to change animation states.
13314                if (mParent != null && getWindowVisibility() == VISIBLE &&
13315                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13316                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
13317                }
13318                notifySubtreeAccessibilityStateChangedIfNeeded();
13319            }
13320        }
13321
13322        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13323            destroyDrawingCache();
13324        }
13325
13326        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13327            destroyDrawingCache();
13328            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13329            invalidateParentCaches();
13330        }
13331
13332        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13333            destroyDrawingCache();
13334            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13335        }
13336
13337        if ((changed & DRAW_MASK) != 0) {
13338            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13339                if (mBackground != null
13340                        || mDefaultFocusHighlight != null
13341                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13342                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13343                } else {
13344                    mPrivateFlags |= PFLAG_SKIP_DRAW;
13345                }
13346            } else {
13347                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13348            }
13349            requestLayout();
13350            invalidate(true);
13351        }
13352
13353        if ((changed & KEEP_SCREEN_ON) != 0) {
13354            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13355                mParent.recomputeViewAttributes(this);
13356            }
13357        }
13358
13359        if (accessibilityEnabled) {
13360            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13361                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13362                    || (changed & CONTEXT_CLICKABLE) != 0) {
13363                if (oldIncludeForAccessibility != includeForAccessibility()) {
13364                    notifySubtreeAccessibilityStateChangedIfNeeded();
13365                } else {
13366                    notifyViewAccessibilityStateChangedIfNeeded(
13367                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13368                }
13369            } else if ((changed & ENABLED_MASK) != 0) {
13370                notifyViewAccessibilityStateChangedIfNeeded(
13371                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13372            }
13373        }
13374    }
13375
13376    /**
13377     * Change the view's z order in the tree, so it's on top of other sibling
13378     * views. This ordering change may affect layout, if the parent container
13379     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13380     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13381     * method should be followed by calls to {@link #requestLayout()} and
13382     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13383     * with the new child ordering.
13384     *
13385     * @see ViewGroup#bringChildToFront(View)
13386     */
13387    public void bringToFront() {
13388        if (mParent != null) {
13389            mParent.bringChildToFront(this);
13390        }
13391    }
13392
13393    /**
13394     * This is called in response to an internal scroll in this view (i.e., the
13395     * view scrolled its own contents). This is typically as a result of
13396     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13397     * called.
13398     *
13399     * @param l Current horizontal scroll origin.
13400     * @param t Current vertical scroll origin.
13401     * @param oldl Previous horizontal scroll origin.
13402     * @param oldt Previous vertical scroll origin.
13403     */
13404    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13405        notifySubtreeAccessibilityStateChangedIfNeeded();
13406
13407        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13408            postSendViewScrolledAccessibilityEventCallback();
13409        }
13410
13411        mBackgroundSizeChanged = true;
13412        mDefaultFocusHighlightSizeChanged = true;
13413        if (mForegroundInfo != null) {
13414            mForegroundInfo.mBoundsChanged = true;
13415        }
13416
13417        final AttachInfo ai = mAttachInfo;
13418        if (ai != null) {
13419            ai.mViewScrollChanged = true;
13420        }
13421
13422        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13423            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13424        }
13425    }
13426
13427    /**
13428     * Interface definition for a callback to be invoked when the scroll
13429     * X or Y positions of a view change.
13430     * <p>
13431     * <b>Note:</b> Some views handle scrolling independently from View and may
13432     * have their own separate listeners for scroll-type events. For example,
13433     * {@link android.widget.ListView ListView} allows clients to register an
13434     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13435     * to listen for changes in list scroll position.
13436     *
13437     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13438     */
13439    public interface OnScrollChangeListener {
13440        /**
13441         * Called when the scroll position of a view changes.
13442         *
13443         * @param v The view whose scroll position has changed.
13444         * @param scrollX Current horizontal scroll origin.
13445         * @param scrollY Current vertical scroll origin.
13446         * @param oldScrollX Previous horizontal scroll origin.
13447         * @param oldScrollY Previous vertical scroll origin.
13448         */
13449        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13450    }
13451
13452    /**
13453     * Interface definition for a callback to be invoked when the layout bounds of a view
13454     * changes due to layout processing.
13455     */
13456    public interface OnLayoutChangeListener {
13457        /**
13458         * Called when the layout bounds of a view changes due to layout processing.
13459         *
13460         * @param v The view whose bounds have changed.
13461         * @param left The new value of the view's left property.
13462         * @param top The new value of the view's top property.
13463         * @param right The new value of the view's right property.
13464         * @param bottom The new value of the view's bottom property.
13465         * @param oldLeft The previous value of the view's left property.
13466         * @param oldTop The previous value of the view's top property.
13467         * @param oldRight The previous value of the view's right property.
13468         * @param oldBottom The previous value of the view's bottom property.
13469         */
13470        void onLayoutChange(View v, int left, int top, int right, int bottom,
13471            int oldLeft, int oldTop, int oldRight, int oldBottom);
13472    }
13473
13474    /**
13475     * This is called during layout when the size of this view has changed. If
13476     * you were just added to the view hierarchy, you're called with the old
13477     * values of 0.
13478     *
13479     * @param w Current width of this view.
13480     * @param h Current height of this view.
13481     * @param oldw Old width of this view.
13482     * @param oldh Old height of this view.
13483     */
13484    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13485    }
13486
13487    /**
13488     * Called by draw to draw the child views. This may be overridden
13489     * by derived classes to gain control just before its children are drawn
13490     * (but after its own view has been drawn).
13491     * @param canvas the canvas on which to draw the view
13492     */
13493    protected void dispatchDraw(Canvas canvas) {
13494
13495    }
13496
13497    /**
13498     * Gets the parent of this view. Note that the parent is a
13499     * ViewParent and not necessarily a View.
13500     *
13501     * @return Parent of this view.
13502     */
13503    public final ViewParent getParent() {
13504        return mParent;
13505    }
13506
13507    /**
13508     * Set the horizontal scrolled position of your view. This will cause a call to
13509     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13510     * invalidated.
13511     * @param value the x position to scroll to
13512     */
13513    public void setScrollX(int value) {
13514        scrollTo(value, mScrollY);
13515    }
13516
13517    /**
13518     * Set the vertical scrolled position of your view. This will cause a call to
13519     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13520     * invalidated.
13521     * @param value the y position to scroll to
13522     */
13523    public void setScrollY(int value) {
13524        scrollTo(mScrollX, value);
13525    }
13526
13527    /**
13528     * Return the scrolled left position of this view. This is the left edge of
13529     * the displayed part of your view. You do not need to draw any pixels
13530     * farther left, since those are outside of the frame of your view on
13531     * screen.
13532     *
13533     * @return The left edge of the displayed part of your view, in pixels.
13534     */
13535    public final int getScrollX() {
13536        return mScrollX;
13537    }
13538
13539    /**
13540     * Return the scrolled top position of this view. This is the top edge of
13541     * the displayed part of your view. You do not need to draw any pixels above
13542     * it, since those are outside of the frame of your view on screen.
13543     *
13544     * @return The top edge of the displayed part of your view, in pixels.
13545     */
13546    public final int getScrollY() {
13547        return mScrollY;
13548    }
13549
13550    /**
13551     * Return the width of the your view.
13552     *
13553     * @return The width of your view, in pixels.
13554     */
13555    @ViewDebug.ExportedProperty(category = "layout")
13556    public final int getWidth() {
13557        return mRight - mLeft;
13558    }
13559
13560    /**
13561     * Return the height of your view.
13562     *
13563     * @return The height of your view, in pixels.
13564     */
13565    @ViewDebug.ExportedProperty(category = "layout")
13566    public final int getHeight() {
13567        return mBottom - mTop;
13568    }
13569
13570    /**
13571     * Return the visible drawing bounds of your view. Fills in the output
13572     * rectangle with the values from getScrollX(), getScrollY(),
13573     * getWidth(), and getHeight(). These bounds do not account for any
13574     * transformation properties currently set on the view, such as
13575     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13576     *
13577     * @param outRect The (scrolled) drawing bounds of the view.
13578     */
13579    public void getDrawingRect(Rect outRect) {
13580        outRect.left = mScrollX;
13581        outRect.top = mScrollY;
13582        outRect.right = mScrollX + (mRight - mLeft);
13583        outRect.bottom = mScrollY + (mBottom - mTop);
13584    }
13585
13586    /**
13587     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13588     * raw width component (that is the result is masked by
13589     * {@link #MEASURED_SIZE_MASK}).
13590     *
13591     * @return The raw measured width of this view.
13592     */
13593    public final int getMeasuredWidth() {
13594        return mMeasuredWidth & MEASURED_SIZE_MASK;
13595    }
13596
13597    /**
13598     * Return the full width measurement information for this view as computed
13599     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13600     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13601     * This should be used during measurement and layout calculations only. Use
13602     * {@link #getWidth()} to see how wide a view is after layout.
13603     *
13604     * @return The measured width of this view as a bit mask.
13605     */
13606    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13607            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13608                    name = "MEASURED_STATE_TOO_SMALL"),
13609    })
13610    public final int getMeasuredWidthAndState() {
13611        return mMeasuredWidth;
13612    }
13613
13614    /**
13615     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13616     * raw height component (that is the result is masked by
13617     * {@link #MEASURED_SIZE_MASK}).
13618     *
13619     * @return The raw measured height of this view.
13620     */
13621    public final int getMeasuredHeight() {
13622        return mMeasuredHeight & MEASURED_SIZE_MASK;
13623    }
13624
13625    /**
13626     * Return the full height measurement information for this view as computed
13627     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13628     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13629     * This should be used during measurement and layout calculations only. Use
13630     * {@link #getHeight()} to see how wide a view is after layout.
13631     *
13632     * @return The measured height of this view as a bit mask.
13633     */
13634    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13635            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13636                    name = "MEASURED_STATE_TOO_SMALL"),
13637    })
13638    public final int getMeasuredHeightAndState() {
13639        return mMeasuredHeight;
13640    }
13641
13642    /**
13643     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13644     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13645     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13646     * and the height component is at the shifted bits
13647     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13648     */
13649    public final int getMeasuredState() {
13650        return (mMeasuredWidth&MEASURED_STATE_MASK)
13651                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13652                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13653    }
13654
13655    /**
13656     * The transform matrix of this view, which is calculated based on the current
13657     * rotation, scale, and pivot properties.
13658     *
13659     * @see #getRotation()
13660     * @see #getScaleX()
13661     * @see #getScaleY()
13662     * @see #getPivotX()
13663     * @see #getPivotY()
13664     * @return The current transform matrix for the view
13665     */
13666    public Matrix getMatrix() {
13667        ensureTransformationInfo();
13668        final Matrix matrix = mTransformationInfo.mMatrix;
13669        mRenderNode.getMatrix(matrix);
13670        return matrix;
13671    }
13672
13673    /**
13674     * Returns true if the transform matrix is the identity matrix.
13675     * Recomputes the matrix if necessary.
13676     *
13677     * @return True if the transform matrix is the identity matrix, false otherwise.
13678     */
13679    final boolean hasIdentityMatrix() {
13680        return mRenderNode.hasIdentityMatrix();
13681    }
13682
13683    void ensureTransformationInfo() {
13684        if (mTransformationInfo == null) {
13685            mTransformationInfo = new TransformationInfo();
13686        }
13687    }
13688
13689    /**
13690     * Utility method to retrieve the inverse of the current mMatrix property.
13691     * We cache the matrix to avoid recalculating it when transform properties
13692     * have not changed.
13693     *
13694     * @return The inverse of the current matrix of this view.
13695     * @hide
13696     */
13697    public final Matrix getInverseMatrix() {
13698        ensureTransformationInfo();
13699        if (mTransformationInfo.mInverseMatrix == null) {
13700            mTransformationInfo.mInverseMatrix = new Matrix();
13701        }
13702        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13703        mRenderNode.getInverseMatrix(matrix);
13704        return matrix;
13705    }
13706
13707    /**
13708     * Gets the distance along the Z axis from the camera to this view.
13709     *
13710     * @see #setCameraDistance(float)
13711     *
13712     * @return The distance along the Z axis.
13713     */
13714    public float getCameraDistance() {
13715        final float dpi = mResources.getDisplayMetrics().densityDpi;
13716        return -(mRenderNode.getCameraDistance() * dpi);
13717    }
13718
13719    /**
13720     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13721     * views are drawn) from the camera to this view. The camera's distance
13722     * affects 3D transformations, for instance rotations around the X and Y
13723     * axis. If the rotationX or rotationY properties are changed and this view is
13724     * large (more than half the size of the screen), it is recommended to always
13725     * use a camera distance that's greater than the height (X axis rotation) or
13726     * the width (Y axis rotation) of this view.</p>
13727     *
13728     * <p>The distance of the camera from the view plane can have an affect on the
13729     * perspective distortion of the view when it is rotated around the x or y axis.
13730     * For example, a large distance will result in a large viewing angle, and there
13731     * will not be much perspective distortion of the view as it rotates. A short
13732     * distance may cause much more perspective distortion upon rotation, and can
13733     * also result in some drawing artifacts if the rotated view ends up partially
13734     * behind the camera (which is why the recommendation is to use a distance at
13735     * least as far as the size of the view, if the view is to be rotated.)</p>
13736     *
13737     * <p>The distance is expressed in "depth pixels." The default distance depends
13738     * on the screen density. For instance, on a medium density display, the
13739     * default distance is 1280. On a high density display, the default distance
13740     * is 1920.</p>
13741     *
13742     * <p>If you want to specify a distance that leads to visually consistent
13743     * results across various densities, use the following formula:</p>
13744     * <pre>
13745     * float scale = context.getResources().getDisplayMetrics().density;
13746     * view.setCameraDistance(distance * scale);
13747     * </pre>
13748     *
13749     * <p>The density scale factor of a high density display is 1.5,
13750     * and 1920 = 1280 * 1.5.</p>
13751     *
13752     * @param distance The distance in "depth pixels", if negative the opposite
13753     *        value is used
13754     *
13755     * @see #setRotationX(float)
13756     * @see #setRotationY(float)
13757     */
13758    public void setCameraDistance(float distance) {
13759        final float dpi = mResources.getDisplayMetrics().densityDpi;
13760
13761        invalidateViewProperty(true, false);
13762        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13763        invalidateViewProperty(false, false);
13764
13765        invalidateParentIfNeededAndWasQuickRejected();
13766    }
13767
13768    /**
13769     * The degrees that the view is rotated around the pivot point.
13770     *
13771     * @see #setRotation(float)
13772     * @see #getPivotX()
13773     * @see #getPivotY()
13774     *
13775     * @return The degrees of rotation.
13776     */
13777    @ViewDebug.ExportedProperty(category = "drawing")
13778    public float getRotation() {
13779        return mRenderNode.getRotation();
13780    }
13781
13782    /**
13783     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13784     * result in clockwise rotation.
13785     *
13786     * @param rotation The degrees of rotation.
13787     *
13788     * @see #getRotation()
13789     * @see #getPivotX()
13790     * @see #getPivotY()
13791     * @see #setRotationX(float)
13792     * @see #setRotationY(float)
13793     *
13794     * @attr ref android.R.styleable#View_rotation
13795     */
13796    public void setRotation(float rotation) {
13797        if (rotation != getRotation()) {
13798            // Double-invalidation is necessary to capture view's old and new areas
13799            invalidateViewProperty(true, false);
13800            mRenderNode.setRotation(rotation);
13801            invalidateViewProperty(false, true);
13802
13803            invalidateParentIfNeededAndWasQuickRejected();
13804            notifySubtreeAccessibilityStateChangedIfNeeded();
13805        }
13806    }
13807
13808    /**
13809     * The degrees that the view is rotated around the vertical axis through the pivot point.
13810     *
13811     * @see #getPivotX()
13812     * @see #getPivotY()
13813     * @see #setRotationY(float)
13814     *
13815     * @return The degrees of Y rotation.
13816     */
13817    @ViewDebug.ExportedProperty(category = "drawing")
13818    public float getRotationY() {
13819        return mRenderNode.getRotationY();
13820    }
13821
13822    /**
13823     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13824     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13825     * down the y axis.
13826     *
13827     * When rotating large views, it is recommended to adjust the camera distance
13828     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13829     *
13830     * @param rotationY The degrees of Y rotation.
13831     *
13832     * @see #getRotationY()
13833     * @see #getPivotX()
13834     * @see #getPivotY()
13835     * @see #setRotation(float)
13836     * @see #setRotationX(float)
13837     * @see #setCameraDistance(float)
13838     *
13839     * @attr ref android.R.styleable#View_rotationY
13840     */
13841    public void setRotationY(float rotationY) {
13842        if (rotationY != getRotationY()) {
13843            invalidateViewProperty(true, false);
13844            mRenderNode.setRotationY(rotationY);
13845            invalidateViewProperty(false, true);
13846
13847            invalidateParentIfNeededAndWasQuickRejected();
13848            notifySubtreeAccessibilityStateChangedIfNeeded();
13849        }
13850    }
13851
13852    /**
13853     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13854     *
13855     * @see #getPivotX()
13856     * @see #getPivotY()
13857     * @see #setRotationX(float)
13858     *
13859     * @return The degrees of X rotation.
13860     */
13861    @ViewDebug.ExportedProperty(category = "drawing")
13862    public float getRotationX() {
13863        return mRenderNode.getRotationX();
13864    }
13865
13866    /**
13867     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13868     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13869     * x axis.
13870     *
13871     * When rotating large views, it is recommended to adjust the camera distance
13872     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13873     *
13874     * @param rotationX The degrees of X rotation.
13875     *
13876     * @see #getRotationX()
13877     * @see #getPivotX()
13878     * @see #getPivotY()
13879     * @see #setRotation(float)
13880     * @see #setRotationY(float)
13881     * @see #setCameraDistance(float)
13882     *
13883     * @attr ref android.R.styleable#View_rotationX
13884     */
13885    public void setRotationX(float rotationX) {
13886        if (rotationX != getRotationX()) {
13887            invalidateViewProperty(true, false);
13888            mRenderNode.setRotationX(rotationX);
13889            invalidateViewProperty(false, true);
13890
13891            invalidateParentIfNeededAndWasQuickRejected();
13892            notifySubtreeAccessibilityStateChangedIfNeeded();
13893        }
13894    }
13895
13896    /**
13897     * The amount that the view is scaled in x around the pivot point, as a proportion of
13898     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13899     *
13900     * <p>By default, this is 1.0f.
13901     *
13902     * @see #getPivotX()
13903     * @see #getPivotY()
13904     * @return The scaling factor.
13905     */
13906    @ViewDebug.ExportedProperty(category = "drawing")
13907    public float getScaleX() {
13908        return mRenderNode.getScaleX();
13909    }
13910
13911    /**
13912     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13913     * the view's unscaled width. A value of 1 means that no scaling is applied.
13914     *
13915     * @param scaleX The scaling factor.
13916     * @see #getPivotX()
13917     * @see #getPivotY()
13918     *
13919     * @attr ref android.R.styleable#View_scaleX
13920     */
13921    public void setScaleX(float scaleX) {
13922        if (scaleX != getScaleX()) {
13923            invalidateViewProperty(true, false);
13924            mRenderNode.setScaleX(scaleX);
13925            invalidateViewProperty(false, true);
13926
13927            invalidateParentIfNeededAndWasQuickRejected();
13928            notifySubtreeAccessibilityStateChangedIfNeeded();
13929        }
13930    }
13931
13932    /**
13933     * The amount that the view is scaled in y around the pivot point, as a proportion of
13934     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13935     *
13936     * <p>By default, this is 1.0f.
13937     *
13938     * @see #getPivotX()
13939     * @see #getPivotY()
13940     * @return The scaling factor.
13941     */
13942    @ViewDebug.ExportedProperty(category = "drawing")
13943    public float getScaleY() {
13944        return mRenderNode.getScaleY();
13945    }
13946
13947    /**
13948     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13949     * the view's unscaled width. A value of 1 means that no scaling is applied.
13950     *
13951     * @param scaleY The scaling factor.
13952     * @see #getPivotX()
13953     * @see #getPivotY()
13954     *
13955     * @attr ref android.R.styleable#View_scaleY
13956     */
13957    public void setScaleY(float scaleY) {
13958        if (scaleY != getScaleY()) {
13959            invalidateViewProperty(true, false);
13960            mRenderNode.setScaleY(scaleY);
13961            invalidateViewProperty(false, true);
13962
13963            invalidateParentIfNeededAndWasQuickRejected();
13964            notifySubtreeAccessibilityStateChangedIfNeeded();
13965        }
13966    }
13967
13968    /**
13969     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13970     * and {@link #setScaleX(float) scaled}.
13971     *
13972     * @see #getRotation()
13973     * @see #getScaleX()
13974     * @see #getScaleY()
13975     * @see #getPivotY()
13976     * @return The x location of the pivot point.
13977     *
13978     * @attr ref android.R.styleable#View_transformPivotX
13979     */
13980    @ViewDebug.ExportedProperty(category = "drawing")
13981    public float getPivotX() {
13982        return mRenderNode.getPivotX();
13983    }
13984
13985    /**
13986     * Sets the x location of the point around which the view is
13987     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13988     * By default, the pivot point is centered on the object.
13989     * Setting this property disables this behavior and causes the view to use only the
13990     * explicitly set pivotX and pivotY values.
13991     *
13992     * @param pivotX The x location of the pivot point.
13993     * @see #getRotation()
13994     * @see #getScaleX()
13995     * @see #getScaleY()
13996     * @see #getPivotY()
13997     *
13998     * @attr ref android.R.styleable#View_transformPivotX
13999     */
14000    public void setPivotX(float pivotX) {
14001        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
14002            invalidateViewProperty(true, false);
14003            mRenderNode.setPivotX(pivotX);
14004            invalidateViewProperty(false, true);
14005
14006            invalidateParentIfNeededAndWasQuickRejected();
14007        }
14008    }
14009
14010    /**
14011     * The y location of the point around which the view is {@link #setRotation(float) rotated}
14012     * and {@link #setScaleY(float) scaled}.
14013     *
14014     * @see #getRotation()
14015     * @see #getScaleX()
14016     * @see #getScaleY()
14017     * @see #getPivotY()
14018     * @return The y location of the pivot point.
14019     *
14020     * @attr ref android.R.styleable#View_transformPivotY
14021     */
14022    @ViewDebug.ExportedProperty(category = "drawing")
14023    public float getPivotY() {
14024        return mRenderNode.getPivotY();
14025    }
14026
14027    /**
14028     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
14029     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
14030     * Setting this property disables this behavior and causes the view to use only the
14031     * explicitly set pivotX and pivotY values.
14032     *
14033     * @param pivotY The y location of the pivot point.
14034     * @see #getRotation()
14035     * @see #getScaleX()
14036     * @see #getScaleY()
14037     * @see #getPivotY()
14038     *
14039     * @attr ref android.R.styleable#View_transformPivotY
14040     */
14041    public void setPivotY(float pivotY) {
14042        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
14043            invalidateViewProperty(true, false);
14044            mRenderNode.setPivotY(pivotY);
14045            invalidateViewProperty(false, true);
14046
14047            invalidateParentIfNeededAndWasQuickRejected();
14048        }
14049    }
14050
14051    /**
14052     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
14053     * completely transparent and 1 means the view is completely opaque.
14054     *
14055     * <p>By default this is 1.0f.
14056     * @return The opacity of the view.
14057     */
14058    @ViewDebug.ExportedProperty(category = "drawing")
14059    public float getAlpha() {
14060        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
14061    }
14062
14063    /**
14064     * Sets the behavior for overlapping rendering for this view (see {@link
14065     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
14066     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
14067     * providing the value which is then used internally. That is, when {@link
14068     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
14069     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
14070     * instead.
14071     *
14072     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
14073     * instead of that returned by {@link #hasOverlappingRendering()}.
14074     *
14075     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
14076     */
14077    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
14078        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
14079        if (hasOverlappingRendering) {
14080            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14081        } else {
14082            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14083        }
14084    }
14085
14086    /**
14087     * Returns the value for overlapping rendering that is used internally. This is either
14088     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
14089     * the return value of {@link #hasOverlappingRendering()}, otherwise.
14090     *
14091     * @return The value for overlapping rendering being used internally.
14092     */
14093    public final boolean getHasOverlappingRendering() {
14094        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
14095                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
14096                hasOverlappingRendering();
14097    }
14098
14099    /**
14100     * Returns whether this View has content which overlaps.
14101     *
14102     * <p>This function, intended to be overridden by specific View types, is an optimization when
14103     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
14104     * an offscreen buffer and then composited into place, which can be expensive. If the view has
14105     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
14106     * directly. An example of overlapping rendering is a TextView with a background image, such as
14107     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
14108     * ImageView with only the foreground image. The default implementation returns true; subclasses
14109     * should override if they have cases which can be optimized.</p>
14110     *
14111     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
14112     * necessitates that a View return true if it uses the methods internally without passing the
14113     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
14114     *
14115     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
14116     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
14117     *
14118     * @return true if the content in this view might overlap, false otherwise.
14119     */
14120    @ViewDebug.ExportedProperty(category = "drawing")
14121    public boolean hasOverlappingRendering() {
14122        return true;
14123    }
14124
14125    /**
14126     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
14127     * completely transparent and 1 means the view is completely opaque.
14128     *
14129     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
14130     * can have significant performance implications, especially for large views. It is best to use
14131     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
14132     *
14133     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
14134     * strongly recommended for performance reasons to either override
14135     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
14136     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
14137     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
14138     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
14139     * of rendering cost, even for simple or small views. Starting with
14140     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
14141     * applied to the view at the rendering level.</p>
14142     *
14143     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
14144     * responsible for applying the opacity itself.</p>
14145     *
14146     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
14147     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
14148     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
14149     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
14150     *
14151     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
14152     * value will clip a View to its bounds, unless the View returns <code>false</code> from
14153     * {@link #hasOverlappingRendering}.</p>
14154     *
14155     * @param alpha The opacity of the view.
14156     *
14157     * @see #hasOverlappingRendering()
14158     * @see #setLayerType(int, android.graphics.Paint)
14159     *
14160     * @attr ref android.R.styleable#View_alpha
14161     */
14162    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
14163        ensureTransformationInfo();
14164        if (mTransformationInfo.mAlpha != alpha) {
14165            // Report visibility changes, which can affect children, to accessibility
14166            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
14167                notifySubtreeAccessibilityStateChangedIfNeeded();
14168            }
14169            mTransformationInfo.mAlpha = alpha;
14170            if (onSetAlpha((int) (alpha * 255))) {
14171                mPrivateFlags |= PFLAG_ALPHA_SET;
14172                // subclass is handling alpha - don't optimize rendering cache invalidation
14173                invalidateParentCaches();
14174                invalidate(true);
14175            } else {
14176                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14177                invalidateViewProperty(true, false);
14178                mRenderNode.setAlpha(getFinalAlpha());
14179            }
14180        }
14181    }
14182
14183    /**
14184     * Faster version of setAlpha() which performs the same steps except there are
14185     * no calls to invalidate(). The caller of this function should perform proper invalidation
14186     * on the parent and this object. The return value indicates whether the subclass handles
14187     * alpha (the return value for onSetAlpha()).
14188     *
14189     * @param alpha The new value for the alpha property
14190     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
14191     *         the new value for the alpha property is different from the old value
14192     */
14193    boolean setAlphaNoInvalidation(float alpha) {
14194        ensureTransformationInfo();
14195        if (mTransformationInfo.mAlpha != alpha) {
14196            mTransformationInfo.mAlpha = alpha;
14197            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
14198            if (subclassHandlesAlpha) {
14199                mPrivateFlags |= PFLAG_ALPHA_SET;
14200                return true;
14201            } else {
14202                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14203                mRenderNode.setAlpha(getFinalAlpha());
14204            }
14205        }
14206        return false;
14207    }
14208
14209    /**
14210     * This property is hidden and intended only for use by the Fade transition, which
14211     * animates it to produce a visual translucency that does not side-effect (or get
14212     * affected by) the real alpha property. This value is composited with the other
14213     * alpha value (and the AlphaAnimation value, when that is present) to produce
14214     * a final visual translucency result, which is what is passed into the DisplayList.
14215     *
14216     * @hide
14217     */
14218    public void setTransitionAlpha(float alpha) {
14219        ensureTransformationInfo();
14220        if (mTransformationInfo.mTransitionAlpha != alpha) {
14221            mTransformationInfo.mTransitionAlpha = alpha;
14222            mPrivateFlags &= ~PFLAG_ALPHA_SET;
14223            invalidateViewProperty(true, false);
14224            mRenderNode.setAlpha(getFinalAlpha());
14225        }
14226    }
14227
14228    /**
14229     * Calculates the visual alpha of this view, which is a combination of the actual
14230     * alpha value and the transitionAlpha value (if set).
14231     */
14232    private float getFinalAlpha() {
14233        if (mTransformationInfo != null) {
14234            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
14235        }
14236        return 1;
14237    }
14238
14239    /**
14240     * This property is hidden and intended only for use by the Fade transition, which
14241     * animates it to produce a visual translucency that does not side-effect (or get
14242     * affected by) the real alpha property. This value is composited with the other
14243     * alpha value (and the AlphaAnimation value, when that is present) to produce
14244     * a final visual translucency result, which is what is passed into the DisplayList.
14245     *
14246     * @hide
14247     */
14248    @ViewDebug.ExportedProperty(category = "drawing")
14249    public float getTransitionAlpha() {
14250        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
14251    }
14252
14253    /**
14254     * Top position of this view relative to its parent.
14255     *
14256     * @return The top of this view, in pixels.
14257     */
14258    @ViewDebug.CapturedViewProperty
14259    public final int getTop() {
14260        return mTop;
14261    }
14262
14263    /**
14264     * Sets the top position of this view relative to its parent. This method is meant to be called
14265     * by the layout system and should not generally be called otherwise, because the property
14266     * may be changed at any time by the layout.
14267     *
14268     * @param top The top of this view, in pixels.
14269     */
14270    public final void setTop(int top) {
14271        if (top != mTop) {
14272            final boolean matrixIsIdentity = hasIdentityMatrix();
14273            if (matrixIsIdentity) {
14274                if (mAttachInfo != null) {
14275                    int minTop;
14276                    int yLoc;
14277                    if (top < mTop) {
14278                        minTop = top;
14279                        yLoc = top - mTop;
14280                    } else {
14281                        minTop = mTop;
14282                        yLoc = 0;
14283                    }
14284                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
14285                }
14286            } else {
14287                // Double-invalidation is necessary to capture view's old and new areas
14288                invalidate(true);
14289            }
14290
14291            int width = mRight - mLeft;
14292            int oldHeight = mBottom - mTop;
14293
14294            mTop = top;
14295            mRenderNode.setTop(mTop);
14296
14297            sizeChange(width, mBottom - mTop, width, oldHeight);
14298
14299            if (!matrixIsIdentity) {
14300                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14301                invalidate(true);
14302            }
14303            mBackgroundSizeChanged = true;
14304            mDefaultFocusHighlightSizeChanged = true;
14305            if (mForegroundInfo != null) {
14306                mForegroundInfo.mBoundsChanged = true;
14307            }
14308            invalidateParentIfNeeded();
14309            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14310                // View was rejected last time it was drawn by its parent; this may have changed
14311                invalidateParentIfNeeded();
14312            }
14313        }
14314    }
14315
14316    /**
14317     * Bottom position of this view relative to its parent.
14318     *
14319     * @return The bottom of this view, in pixels.
14320     */
14321    @ViewDebug.CapturedViewProperty
14322    public final int getBottom() {
14323        return mBottom;
14324    }
14325
14326    /**
14327     * True if this view has changed since the last time being drawn.
14328     *
14329     * @return The dirty state of this view.
14330     */
14331    public boolean isDirty() {
14332        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14333    }
14334
14335    /**
14336     * Sets the bottom position of this view relative to its parent. This method is meant to be
14337     * called by the layout system and should not generally be called otherwise, because the
14338     * property may be changed at any time by the layout.
14339     *
14340     * @param bottom The bottom of this view, in pixels.
14341     */
14342    public final void setBottom(int bottom) {
14343        if (bottom != mBottom) {
14344            final boolean matrixIsIdentity = hasIdentityMatrix();
14345            if (matrixIsIdentity) {
14346                if (mAttachInfo != null) {
14347                    int maxBottom;
14348                    if (bottom < mBottom) {
14349                        maxBottom = mBottom;
14350                    } else {
14351                        maxBottom = bottom;
14352                    }
14353                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14354                }
14355            } else {
14356                // Double-invalidation is necessary to capture view's old and new areas
14357                invalidate(true);
14358            }
14359
14360            int width = mRight - mLeft;
14361            int oldHeight = mBottom - mTop;
14362
14363            mBottom = bottom;
14364            mRenderNode.setBottom(mBottom);
14365
14366            sizeChange(width, mBottom - mTop, width, oldHeight);
14367
14368            if (!matrixIsIdentity) {
14369                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14370                invalidate(true);
14371            }
14372            mBackgroundSizeChanged = true;
14373            mDefaultFocusHighlightSizeChanged = true;
14374            if (mForegroundInfo != null) {
14375                mForegroundInfo.mBoundsChanged = true;
14376            }
14377            invalidateParentIfNeeded();
14378            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14379                // View was rejected last time it was drawn by its parent; this may have changed
14380                invalidateParentIfNeeded();
14381            }
14382        }
14383    }
14384
14385    /**
14386     * Left position of this view relative to its parent.
14387     *
14388     * @return The left edge of this view, in pixels.
14389     */
14390    @ViewDebug.CapturedViewProperty
14391    public final int getLeft() {
14392        return mLeft;
14393    }
14394
14395    /**
14396     * Sets the left position of this view relative to its parent. This method is meant to be called
14397     * by the layout system and should not generally be called otherwise, because the property
14398     * may be changed at any time by the layout.
14399     *
14400     * @param left The left of this view, in pixels.
14401     */
14402    public final void setLeft(int left) {
14403        if (left != mLeft) {
14404            final boolean matrixIsIdentity = hasIdentityMatrix();
14405            if (matrixIsIdentity) {
14406                if (mAttachInfo != null) {
14407                    int minLeft;
14408                    int xLoc;
14409                    if (left < mLeft) {
14410                        minLeft = left;
14411                        xLoc = left - mLeft;
14412                    } else {
14413                        minLeft = mLeft;
14414                        xLoc = 0;
14415                    }
14416                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14417                }
14418            } else {
14419                // Double-invalidation is necessary to capture view's old and new areas
14420                invalidate(true);
14421            }
14422
14423            int oldWidth = mRight - mLeft;
14424            int height = mBottom - mTop;
14425
14426            mLeft = left;
14427            mRenderNode.setLeft(left);
14428
14429            sizeChange(mRight - mLeft, height, oldWidth, height);
14430
14431            if (!matrixIsIdentity) {
14432                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14433                invalidate(true);
14434            }
14435            mBackgroundSizeChanged = true;
14436            mDefaultFocusHighlightSizeChanged = true;
14437            if (mForegroundInfo != null) {
14438                mForegroundInfo.mBoundsChanged = true;
14439            }
14440            invalidateParentIfNeeded();
14441            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14442                // View was rejected last time it was drawn by its parent; this may have changed
14443                invalidateParentIfNeeded();
14444            }
14445        }
14446    }
14447
14448    /**
14449     * Right position of this view relative to its parent.
14450     *
14451     * @return The right edge of this view, in pixels.
14452     */
14453    @ViewDebug.CapturedViewProperty
14454    public final int getRight() {
14455        return mRight;
14456    }
14457
14458    /**
14459     * Sets the right position of this view relative to its parent. This method is meant to be called
14460     * by the layout system and should not generally be called otherwise, because the property
14461     * may be changed at any time by the layout.
14462     *
14463     * @param right The right of this view, in pixels.
14464     */
14465    public final void setRight(int right) {
14466        if (right != mRight) {
14467            final boolean matrixIsIdentity = hasIdentityMatrix();
14468            if (matrixIsIdentity) {
14469                if (mAttachInfo != null) {
14470                    int maxRight;
14471                    if (right < mRight) {
14472                        maxRight = mRight;
14473                    } else {
14474                        maxRight = right;
14475                    }
14476                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14477                }
14478            } else {
14479                // Double-invalidation is necessary to capture view's old and new areas
14480                invalidate(true);
14481            }
14482
14483            int oldWidth = mRight - mLeft;
14484            int height = mBottom - mTop;
14485
14486            mRight = right;
14487            mRenderNode.setRight(mRight);
14488
14489            sizeChange(mRight - mLeft, height, oldWidth, height);
14490
14491            if (!matrixIsIdentity) {
14492                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14493                invalidate(true);
14494            }
14495            mBackgroundSizeChanged = true;
14496            mDefaultFocusHighlightSizeChanged = true;
14497            if (mForegroundInfo != null) {
14498                mForegroundInfo.mBoundsChanged = true;
14499            }
14500            invalidateParentIfNeeded();
14501            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14502                // View was rejected last time it was drawn by its parent; this may have changed
14503                invalidateParentIfNeeded();
14504            }
14505        }
14506    }
14507
14508    /**
14509     * The visual x position of this view, in pixels. This is equivalent to the
14510     * {@link #setTranslationX(float) translationX} property plus the current
14511     * {@link #getLeft() left} property.
14512     *
14513     * @return The visual x position of this view, in pixels.
14514     */
14515    @ViewDebug.ExportedProperty(category = "drawing")
14516    public float getX() {
14517        return mLeft + getTranslationX();
14518    }
14519
14520    /**
14521     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14522     * {@link #setTranslationX(float) translationX} property to be the difference between
14523     * the x value passed in and the current {@link #getLeft() left} property.
14524     *
14525     * @param x The visual x position of this view, in pixels.
14526     */
14527    public void setX(float x) {
14528        setTranslationX(x - mLeft);
14529    }
14530
14531    /**
14532     * The visual y position of this view, in pixels. This is equivalent to the
14533     * {@link #setTranslationY(float) translationY} property plus the current
14534     * {@link #getTop() top} property.
14535     *
14536     * @return The visual y position of this view, in pixels.
14537     */
14538    @ViewDebug.ExportedProperty(category = "drawing")
14539    public float getY() {
14540        return mTop + getTranslationY();
14541    }
14542
14543    /**
14544     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14545     * {@link #setTranslationY(float) translationY} property to be the difference between
14546     * the y value passed in and the current {@link #getTop() top} property.
14547     *
14548     * @param y The visual y position of this view, in pixels.
14549     */
14550    public void setY(float y) {
14551        setTranslationY(y - mTop);
14552    }
14553
14554    /**
14555     * The visual z position of this view, in pixels. This is equivalent to the
14556     * {@link #setTranslationZ(float) translationZ} property plus the current
14557     * {@link #getElevation() elevation} property.
14558     *
14559     * @return The visual z position of this view, in pixels.
14560     */
14561    @ViewDebug.ExportedProperty(category = "drawing")
14562    public float getZ() {
14563        return getElevation() + getTranslationZ();
14564    }
14565
14566    /**
14567     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14568     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14569     * the x value passed in and the current {@link #getElevation() elevation} property.
14570     *
14571     * @param z The visual z position of this view, in pixels.
14572     */
14573    public void setZ(float z) {
14574        setTranslationZ(z - getElevation());
14575    }
14576
14577    /**
14578     * The base elevation of this view relative to its parent, in pixels.
14579     *
14580     * @return The base depth position of the view, in pixels.
14581     */
14582    @ViewDebug.ExportedProperty(category = "drawing")
14583    public float getElevation() {
14584        return mRenderNode.getElevation();
14585    }
14586
14587    /**
14588     * Sets the base elevation of this view, in pixels.
14589     *
14590     * @attr ref android.R.styleable#View_elevation
14591     */
14592    public void setElevation(float elevation) {
14593        if (elevation != getElevation()) {
14594            invalidateViewProperty(true, false);
14595            mRenderNode.setElevation(elevation);
14596            invalidateViewProperty(false, true);
14597
14598            invalidateParentIfNeededAndWasQuickRejected();
14599        }
14600    }
14601
14602    /**
14603     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14604     * This position is post-layout, in addition to wherever the object's
14605     * layout placed it.
14606     *
14607     * @return The horizontal position of this view relative to its left position, in pixels.
14608     */
14609    @ViewDebug.ExportedProperty(category = "drawing")
14610    public float getTranslationX() {
14611        return mRenderNode.getTranslationX();
14612    }
14613
14614    /**
14615     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14616     * This effectively positions the object post-layout, in addition to wherever the object's
14617     * layout placed it.
14618     *
14619     * @param translationX The horizontal position of this view relative to its left position,
14620     * in pixels.
14621     *
14622     * @attr ref android.R.styleable#View_translationX
14623     */
14624    public void setTranslationX(float translationX) {
14625        if (translationX != getTranslationX()) {
14626            invalidateViewProperty(true, false);
14627            mRenderNode.setTranslationX(translationX);
14628            invalidateViewProperty(false, true);
14629
14630            invalidateParentIfNeededAndWasQuickRejected();
14631            notifySubtreeAccessibilityStateChangedIfNeeded();
14632        }
14633    }
14634
14635    /**
14636     * The vertical location of this view relative to its {@link #getTop() top} position.
14637     * This position is post-layout, in addition to wherever the object's
14638     * layout placed it.
14639     *
14640     * @return The vertical position of this view relative to its top position,
14641     * in pixels.
14642     */
14643    @ViewDebug.ExportedProperty(category = "drawing")
14644    public float getTranslationY() {
14645        return mRenderNode.getTranslationY();
14646    }
14647
14648    /**
14649     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14650     * This effectively positions the object post-layout, in addition to wherever the object's
14651     * layout placed it.
14652     *
14653     * @param translationY The vertical position of this view relative to its top position,
14654     * in pixels.
14655     *
14656     * @attr ref android.R.styleable#View_translationY
14657     */
14658    public void setTranslationY(float translationY) {
14659        if (translationY != getTranslationY()) {
14660            invalidateViewProperty(true, false);
14661            mRenderNode.setTranslationY(translationY);
14662            invalidateViewProperty(false, true);
14663
14664            invalidateParentIfNeededAndWasQuickRejected();
14665            notifySubtreeAccessibilityStateChangedIfNeeded();
14666        }
14667    }
14668
14669    /**
14670     * The depth location of this view relative to its {@link #getElevation() elevation}.
14671     *
14672     * @return The depth of this view relative to its elevation.
14673     */
14674    @ViewDebug.ExportedProperty(category = "drawing")
14675    public float getTranslationZ() {
14676        return mRenderNode.getTranslationZ();
14677    }
14678
14679    /**
14680     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14681     *
14682     * @attr ref android.R.styleable#View_translationZ
14683     */
14684    public void setTranslationZ(float translationZ) {
14685        if (translationZ != getTranslationZ()) {
14686            invalidateViewProperty(true, false);
14687            mRenderNode.setTranslationZ(translationZ);
14688            invalidateViewProperty(false, true);
14689
14690            invalidateParentIfNeededAndWasQuickRejected();
14691        }
14692    }
14693
14694    /** @hide */
14695    public void setAnimationMatrix(Matrix matrix) {
14696        invalidateViewProperty(true, false);
14697        mRenderNode.setAnimationMatrix(matrix);
14698        invalidateViewProperty(false, true);
14699
14700        invalidateParentIfNeededAndWasQuickRejected();
14701    }
14702
14703    /**
14704     * Returns the current StateListAnimator if exists.
14705     *
14706     * @return StateListAnimator or null if it does not exists
14707     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14708     */
14709    public StateListAnimator getStateListAnimator() {
14710        return mStateListAnimator;
14711    }
14712
14713    /**
14714     * Attaches the provided StateListAnimator to this View.
14715     * <p>
14716     * Any previously attached StateListAnimator will be detached.
14717     *
14718     * @param stateListAnimator The StateListAnimator to update the view
14719     * @see android.animation.StateListAnimator
14720     */
14721    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14722        if (mStateListAnimator == stateListAnimator) {
14723            return;
14724        }
14725        if (mStateListAnimator != null) {
14726            mStateListAnimator.setTarget(null);
14727        }
14728        mStateListAnimator = stateListAnimator;
14729        if (stateListAnimator != null) {
14730            stateListAnimator.setTarget(this);
14731            if (isAttachedToWindow()) {
14732                stateListAnimator.setState(getDrawableState());
14733            }
14734        }
14735    }
14736
14737    /**
14738     * Returns whether the Outline should be used to clip the contents of the View.
14739     * <p>
14740     * Note that this flag will only be respected if the View's Outline returns true from
14741     * {@link Outline#canClip()}.
14742     *
14743     * @see #setOutlineProvider(ViewOutlineProvider)
14744     * @see #setClipToOutline(boolean)
14745     */
14746    public final boolean getClipToOutline() {
14747        return mRenderNode.getClipToOutline();
14748    }
14749
14750    /**
14751     * Sets whether the View's Outline should be used to clip the contents of the View.
14752     * <p>
14753     * Only a single non-rectangular clip can be applied on a View at any time.
14754     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14755     * circular reveal} animation take priority over Outline clipping, and
14756     * child Outline clipping takes priority over Outline clipping done by a
14757     * parent.
14758     * <p>
14759     * Note that this flag will only be respected if the View's Outline returns true from
14760     * {@link Outline#canClip()}.
14761     *
14762     * @see #setOutlineProvider(ViewOutlineProvider)
14763     * @see #getClipToOutline()
14764     */
14765    public void setClipToOutline(boolean clipToOutline) {
14766        damageInParent();
14767        if (getClipToOutline() != clipToOutline) {
14768            mRenderNode.setClipToOutline(clipToOutline);
14769        }
14770    }
14771
14772    // correspond to the enum values of View_outlineProvider
14773    private static final int PROVIDER_BACKGROUND = 0;
14774    private static final int PROVIDER_NONE = 1;
14775    private static final int PROVIDER_BOUNDS = 2;
14776    private static final int PROVIDER_PADDED_BOUNDS = 3;
14777    private void setOutlineProviderFromAttribute(int providerInt) {
14778        switch (providerInt) {
14779            case PROVIDER_BACKGROUND:
14780                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14781                break;
14782            case PROVIDER_NONE:
14783                setOutlineProvider(null);
14784                break;
14785            case PROVIDER_BOUNDS:
14786                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14787                break;
14788            case PROVIDER_PADDED_BOUNDS:
14789                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14790                break;
14791        }
14792    }
14793
14794    /**
14795     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14796     * the shape of the shadow it casts, and enables outline clipping.
14797     * <p>
14798     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14799     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14800     * outline provider with this method allows this behavior to be overridden.
14801     * <p>
14802     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14803     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14804     * <p>
14805     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14806     *
14807     * @see #setClipToOutline(boolean)
14808     * @see #getClipToOutline()
14809     * @see #getOutlineProvider()
14810     */
14811    public void setOutlineProvider(ViewOutlineProvider provider) {
14812        mOutlineProvider = provider;
14813        invalidateOutline();
14814    }
14815
14816    /**
14817     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14818     * that defines the shape of the shadow it casts, and enables outline clipping.
14819     *
14820     * @see #setOutlineProvider(ViewOutlineProvider)
14821     */
14822    public ViewOutlineProvider getOutlineProvider() {
14823        return mOutlineProvider;
14824    }
14825
14826    /**
14827     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14828     *
14829     * @see #setOutlineProvider(ViewOutlineProvider)
14830     */
14831    public void invalidateOutline() {
14832        rebuildOutline();
14833
14834        notifySubtreeAccessibilityStateChangedIfNeeded();
14835        invalidateViewProperty(false, false);
14836    }
14837
14838    /**
14839     * Internal version of {@link #invalidateOutline()} which invalidates the
14840     * outline without invalidating the view itself. This is intended to be called from
14841     * within methods in the View class itself which are the result of the view being
14842     * invalidated already. For example, when we are drawing the background of a View,
14843     * we invalidate the outline in case it changed in the meantime, but we do not
14844     * need to invalidate the view because we're already drawing the background as part
14845     * of drawing the view in response to an earlier invalidation of the view.
14846     */
14847    private void rebuildOutline() {
14848        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14849        if (mAttachInfo == null) return;
14850
14851        if (mOutlineProvider == null) {
14852            // no provider, remove outline
14853            mRenderNode.setOutline(null);
14854        } else {
14855            final Outline outline = mAttachInfo.mTmpOutline;
14856            outline.setEmpty();
14857            outline.setAlpha(1.0f);
14858
14859            mOutlineProvider.getOutline(this, outline);
14860            mRenderNode.setOutline(outline);
14861        }
14862    }
14863
14864    /**
14865     * HierarchyViewer only
14866     *
14867     * @hide
14868     */
14869    @ViewDebug.ExportedProperty(category = "drawing")
14870    public boolean hasShadow() {
14871        return mRenderNode.hasShadow();
14872    }
14873
14874
14875    /** @hide */
14876    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14877        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14878        invalidateViewProperty(false, false);
14879    }
14880
14881    /**
14882     * Hit rectangle in parent's coordinates
14883     *
14884     * @param outRect The hit rectangle of the view.
14885     */
14886    public void getHitRect(Rect outRect) {
14887        if (hasIdentityMatrix() || mAttachInfo == null) {
14888            outRect.set(mLeft, mTop, mRight, mBottom);
14889        } else {
14890            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14891            tmpRect.set(0, 0, getWidth(), getHeight());
14892            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14893            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14894                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14895        }
14896    }
14897
14898    /**
14899     * Determines whether the given point, in local coordinates is inside the view.
14900     */
14901    /*package*/ final boolean pointInView(float localX, float localY) {
14902        return pointInView(localX, localY, 0);
14903    }
14904
14905    /**
14906     * Utility method to determine whether the given point, in local coordinates,
14907     * is inside the view, where the area of the view is expanded by the slop factor.
14908     * This method is called while processing touch-move events to determine if the event
14909     * is still within the view.
14910     *
14911     * @hide
14912     */
14913    public boolean pointInView(float localX, float localY, float slop) {
14914        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14915                localY < ((mBottom - mTop) + slop);
14916    }
14917
14918    /**
14919     * When a view has focus and the user navigates away from it, the next view is searched for
14920     * starting from the rectangle filled in by this method.
14921     *
14922     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14923     * of the view.  However, if your view maintains some idea of internal selection,
14924     * such as a cursor, or a selected row or column, you should override this method and
14925     * fill in a more specific rectangle.
14926     *
14927     * @param r The rectangle to fill in, in this view's coordinates.
14928     */
14929    public void getFocusedRect(Rect r) {
14930        getDrawingRect(r);
14931    }
14932
14933    /**
14934     * If some part of this view is not clipped by any of its parents, then
14935     * return that area in r in global (root) coordinates. To convert r to local
14936     * coordinates (without taking possible View rotations into account), offset
14937     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14938     * If the view is completely clipped or translated out, return false.
14939     *
14940     * @param r If true is returned, r holds the global coordinates of the
14941     *        visible portion of this view.
14942     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14943     *        between this view and its root. globalOffet may be null.
14944     * @return true if r is non-empty (i.e. part of the view is visible at the
14945     *         root level.
14946     */
14947    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14948        int width = mRight - mLeft;
14949        int height = mBottom - mTop;
14950        if (width > 0 && height > 0) {
14951            r.set(0, 0, width, height);
14952            if (globalOffset != null) {
14953                globalOffset.set(-mScrollX, -mScrollY);
14954            }
14955            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14956        }
14957        return false;
14958    }
14959
14960    public final boolean getGlobalVisibleRect(Rect r) {
14961        return getGlobalVisibleRect(r, null);
14962    }
14963
14964    public final boolean getLocalVisibleRect(Rect r) {
14965        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14966        if (getGlobalVisibleRect(r, offset)) {
14967            r.offset(-offset.x, -offset.y); // make r local
14968            return true;
14969        }
14970        return false;
14971    }
14972
14973    /**
14974     * Offset this view's vertical location by the specified number of pixels.
14975     *
14976     * @param offset the number of pixels to offset the view by
14977     */
14978    public void offsetTopAndBottom(int offset) {
14979        if (offset != 0) {
14980            final boolean matrixIsIdentity = hasIdentityMatrix();
14981            if (matrixIsIdentity) {
14982                if (isHardwareAccelerated()) {
14983                    invalidateViewProperty(false, false);
14984                } else {
14985                    final ViewParent p = mParent;
14986                    if (p != null && mAttachInfo != null) {
14987                        final Rect r = mAttachInfo.mTmpInvalRect;
14988                        int minTop;
14989                        int maxBottom;
14990                        int yLoc;
14991                        if (offset < 0) {
14992                            minTop = mTop + offset;
14993                            maxBottom = mBottom;
14994                            yLoc = offset;
14995                        } else {
14996                            minTop = mTop;
14997                            maxBottom = mBottom + offset;
14998                            yLoc = 0;
14999                        }
15000                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
15001                        p.invalidateChild(this, r);
15002                    }
15003                }
15004            } else {
15005                invalidateViewProperty(false, false);
15006            }
15007
15008            mTop += offset;
15009            mBottom += offset;
15010            mRenderNode.offsetTopAndBottom(offset);
15011            if (isHardwareAccelerated()) {
15012                invalidateViewProperty(false, false);
15013                invalidateParentIfNeededAndWasQuickRejected();
15014            } else {
15015                if (!matrixIsIdentity) {
15016                    invalidateViewProperty(false, true);
15017                }
15018                invalidateParentIfNeeded();
15019            }
15020            notifySubtreeAccessibilityStateChangedIfNeeded();
15021        }
15022    }
15023
15024    /**
15025     * Offset this view's horizontal location by the specified amount of pixels.
15026     *
15027     * @param offset the number of pixels to offset the view by
15028     */
15029    public void offsetLeftAndRight(int offset) {
15030        if (offset != 0) {
15031            final boolean matrixIsIdentity = hasIdentityMatrix();
15032            if (matrixIsIdentity) {
15033                if (isHardwareAccelerated()) {
15034                    invalidateViewProperty(false, false);
15035                } else {
15036                    final ViewParent p = mParent;
15037                    if (p != null && mAttachInfo != null) {
15038                        final Rect r = mAttachInfo.mTmpInvalRect;
15039                        int minLeft;
15040                        int maxRight;
15041                        if (offset < 0) {
15042                            minLeft = mLeft + offset;
15043                            maxRight = mRight;
15044                        } else {
15045                            minLeft = mLeft;
15046                            maxRight = mRight + offset;
15047                        }
15048                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
15049                        p.invalidateChild(this, r);
15050                    }
15051                }
15052            } else {
15053                invalidateViewProperty(false, false);
15054            }
15055
15056            mLeft += offset;
15057            mRight += offset;
15058            mRenderNode.offsetLeftAndRight(offset);
15059            if (isHardwareAccelerated()) {
15060                invalidateViewProperty(false, false);
15061                invalidateParentIfNeededAndWasQuickRejected();
15062            } else {
15063                if (!matrixIsIdentity) {
15064                    invalidateViewProperty(false, true);
15065                }
15066                invalidateParentIfNeeded();
15067            }
15068            notifySubtreeAccessibilityStateChangedIfNeeded();
15069        }
15070    }
15071
15072    /**
15073     * Get the LayoutParams associated with this view. All views should have
15074     * layout parameters. These supply parameters to the <i>parent</i> of this
15075     * view specifying how it should be arranged. There are many subclasses of
15076     * ViewGroup.LayoutParams, and these correspond to the different subclasses
15077     * of ViewGroup that are responsible for arranging their children.
15078     *
15079     * This method may return null if this View is not attached to a parent
15080     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
15081     * was not invoked successfully. When a View is attached to a parent
15082     * ViewGroup, this method must not return null.
15083     *
15084     * @return The LayoutParams associated with this view, or null if no
15085     *         parameters have been set yet
15086     */
15087    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
15088    public ViewGroup.LayoutParams getLayoutParams() {
15089        return mLayoutParams;
15090    }
15091
15092    /**
15093     * Set the layout parameters associated with this view. These supply
15094     * parameters to the <i>parent</i> of this view specifying how it should be
15095     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
15096     * correspond to the different subclasses of ViewGroup that are responsible
15097     * for arranging their children.
15098     *
15099     * @param params The layout parameters for this view, cannot be null
15100     */
15101    public void setLayoutParams(ViewGroup.LayoutParams params) {
15102        if (params == null) {
15103            throw new NullPointerException("Layout parameters cannot be null");
15104        }
15105        mLayoutParams = params;
15106        resolveLayoutParams();
15107        if (mParent instanceof ViewGroup) {
15108            ((ViewGroup) mParent).onSetLayoutParams(this, params);
15109        }
15110        requestLayout();
15111    }
15112
15113    /**
15114     * Resolve the layout parameters depending on the resolved layout direction
15115     *
15116     * @hide
15117     */
15118    public void resolveLayoutParams() {
15119        if (mLayoutParams != null) {
15120            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
15121        }
15122    }
15123
15124    /**
15125     * Set the scrolled position of your view. This will cause a call to
15126     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15127     * invalidated.
15128     * @param x the x position to scroll to
15129     * @param y the y position to scroll to
15130     */
15131    public void scrollTo(int x, int y) {
15132        if (mScrollX != x || mScrollY != y) {
15133            int oldX = mScrollX;
15134            int oldY = mScrollY;
15135            mScrollX = x;
15136            mScrollY = y;
15137            invalidateParentCaches();
15138            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
15139            if (!awakenScrollBars()) {
15140                postInvalidateOnAnimation();
15141            }
15142        }
15143    }
15144
15145    /**
15146     * Move the scrolled position of your view. This will cause a call to
15147     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15148     * invalidated.
15149     * @param x the amount of pixels to scroll by horizontally
15150     * @param y the amount of pixels to scroll by vertically
15151     */
15152    public void scrollBy(int x, int y) {
15153        scrollTo(mScrollX + x, mScrollY + y);
15154    }
15155
15156    /**
15157     * <p>Trigger the scrollbars to draw. When invoked this method starts an
15158     * animation to fade the scrollbars out after a default delay. If a subclass
15159     * provides animated scrolling, the start delay should equal the duration
15160     * of the scrolling animation.</p>
15161     *
15162     * <p>The animation starts only if at least one of the scrollbars is
15163     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
15164     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15165     * this method returns true, and false otherwise. If the animation is
15166     * started, this method calls {@link #invalidate()}; in that case the
15167     * caller should not call {@link #invalidate()}.</p>
15168     *
15169     * <p>This method should be invoked every time a subclass directly updates
15170     * the scroll parameters.</p>
15171     *
15172     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
15173     * and {@link #scrollTo(int, int)}.</p>
15174     *
15175     * @return true if the animation is played, false otherwise
15176     *
15177     * @see #awakenScrollBars(int)
15178     * @see #scrollBy(int, int)
15179     * @see #scrollTo(int, int)
15180     * @see #isHorizontalScrollBarEnabled()
15181     * @see #isVerticalScrollBarEnabled()
15182     * @see #setHorizontalScrollBarEnabled(boolean)
15183     * @see #setVerticalScrollBarEnabled(boolean)
15184     */
15185    protected boolean awakenScrollBars() {
15186        return mScrollCache != null &&
15187                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
15188    }
15189
15190    /**
15191     * Trigger the scrollbars to draw.
15192     * This method differs from awakenScrollBars() only in its default duration.
15193     * initialAwakenScrollBars() will show the scroll bars for longer than
15194     * usual to give the user more of a chance to notice them.
15195     *
15196     * @return true if the animation is played, false otherwise.
15197     */
15198    private boolean initialAwakenScrollBars() {
15199        return mScrollCache != null &&
15200                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
15201    }
15202
15203    /**
15204     * <p>
15205     * Trigger the scrollbars to draw. When invoked this method starts an
15206     * animation to fade the scrollbars out after a fixed delay. If a subclass
15207     * provides animated scrolling, the start delay should equal the duration of
15208     * the scrolling animation.
15209     * </p>
15210     *
15211     * <p>
15212     * The animation starts only if at least one of the scrollbars is enabled,
15213     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15214     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15215     * this method returns true, and false otherwise. If the animation is
15216     * started, this method calls {@link #invalidate()}; in that case the caller
15217     * should not call {@link #invalidate()}.
15218     * </p>
15219     *
15220     * <p>
15221     * This method should be invoked every time a subclass directly updates the
15222     * scroll parameters.
15223     * </p>
15224     *
15225     * @param startDelay the delay, in milliseconds, after which the animation
15226     *        should start; when the delay is 0, the animation starts
15227     *        immediately
15228     * @return true if the animation is played, false otherwise
15229     *
15230     * @see #scrollBy(int, int)
15231     * @see #scrollTo(int, int)
15232     * @see #isHorizontalScrollBarEnabled()
15233     * @see #isVerticalScrollBarEnabled()
15234     * @see #setHorizontalScrollBarEnabled(boolean)
15235     * @see #setVerticalScrollBarEnabled(boolean)
15236     */
15237    protected boolean awakenScrollBars(int startDelay) {
15238        return awakenScrollBars(startDelay, true);
15239    }
15240
15241    /**
15242     * <p>
15243     * Trigger the scrollbars to draw. When invoked this method starts an
15244     * animation to fade the scrollbars out after a fixed delay. If a subclass
15245     * provides animated scrolling, the start delay should equal the duration of
15246     * the scrolling animation.
15247     * </p>
15248     *
15249     * <p>
15250     * The animation starts only if at least one of the scrollbars is enabled,
15251     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15252     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15253     * this method returns true, and false otherwise. If the animation is
15254     * started, this method calls {@link #invalidate()} if the invalidate parameter
15255     * is set to true; in that case the caller
15256     * should not call {@link #invalidate()}.
15257     * </p>
15258     *
15259     * <p>
15260     * This method should be invoked every time a subclass directly updates the
15261     * scroll parameters.
15262     * </p>
15263     *
15264     * @param startDelay the delay, in milliseconds, after which the animation
15265     *        should start; when the delay is 0, the animation starts
15266     *        immediately
15267     *
15268     * @param invalidate Whether this method should call invalidate
15269     *
15270     * @return true if the animation is played, false otherwise
15271     *
15272     * @see #scrollBy(int, int)
15273     * @see #scrollTo(int, int)
15274     * @see #isHorizontalScrollBarEnabled()
15275     * @see #isVerticalScrollBarEnabled()
15276     * @see #setHorizontalScrollBarEnabled(boolean)
15277     * @see #setVerticalScrollBarEnabled(boolean)
15278     */
15279    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
15280        final ScrollabilityCache scrollCache = mScrollCache;
15281
15282        if (scrollCache == null || !scrollCache.fadeScrollBars) {
15283            return false;
15284        }
15285
15286        if (scrollCache.scrollBar == null) {
15287            scrollCache.scrollBar = new ScrollBarDrawable();
15288            scrollCache.scrollBar.setState(getDrawableState());
15289            scrollCache.scrollBar.setCallback(this);
15290        }
15291
15292        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
15293
15294            if (invalidate) {
15295                // Invalidate to show the scrollbars
15296                postInvalidateOnAnimation();
15297            }
15298
15299            if (scrollCache.state == ScrollabilityCache.OFF) {
15300                // FIXME: this is copied from WindowManagerService.
15301                // We should get this value from the system when it
15302                // is possible to do so.
15303                final int KEY_REPEAT_FIRST_DELAY = 750;
15304                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15305            }
15306
15307            // Tell mScrollCache when we should start fading. This may
15308            // extend the fade start time if one was already scheduled
15309            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15310            scrollCache.fadeStartTime = fadeStartTime;
15311            scrollCache.state = ScrollabilityCache.ON;
15312
15313            // Schedule our fader to run, unscheduling any old ones first
15314            if (mAttachInfo != null) {
15315                mAttachInfo.mHandler.removeCallbacks(scrollCache);
15316                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15317            }
15318
15319            return true;
15320        }
15321
15322        return false;
15323    }
15324
15325    /**
15326     * Do not invalidate views which are not visible and which are not running an animation. They
15327     * will not get drawn and they should not set dirty flags as if they will be drawn
15328     */
15329    private boolean skipInvalidate() {
15330        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15331                (!(mParent instanceof ViewGroup) ||
15332                        !((ViewGroup) mParent).isViewTransitioning(this));
15333    }
15334
15335    /**
15336     * Mark the area defined by dirty as needing to be drawn. If the view is
15337     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15338     * point in the future.
15339     * <p>
15340     * This must be called from a UI thread. To call from a non-UI thread, call
15341     * {@link #postInvalidate()}.
15342     * <p>
15343     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15344     * {@code dirty}.
15345     *
15346     * @param dirty the rectangle representing the bounds of the dirty region
15347     */
15348    public void invalidate(Rect dirty) {
15349        final int scrollX = mScrollX;
15350        final int scrollY = mScrollY;
15351        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15352                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15353    }
15354
15355    /**
15356     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15357     * coordinates of the dirty rect are relative to the view. If the view is
15358     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15359     * point in the future.
15360     * <p>
15361     * This must be called from a UI thread. To call from a non-UI thread, call
15362     * {@link #postInvalidate()}.
15363     *
15364     * @param l the left position of the dirty region
15365     * @param t the top position of the dirty region
15366     * @param r the right position of the dirty region
15367     * @param b the bottom position of the dirty region
15368     */
15369    public void invalidate(int l, int t, int r, int b) {
15370        final int scrollX = mScrollX;
15371        final int scrollY = mScrollY;
15372        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15373    }
15374
15375    /**
15376     * Invalidate the whole view. If the view is visible,
15377     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15378     * the future.
15379     * <p>
15380     * This must be called from a UI thread. To call from a non-UI thread, call
15381     * {@link #postInvalidate()}.
15382     */
15383    public void invalidate() {
15384        invalidate(true);
15385    }
15386
15387    /**
15388     * This is where the invalidate() work actually happens. A full invalidate()
15389     * causes the drawing cache to be invalidated, but this function can be
15390     * called with invalidateCache set to false to skip that invalidation step
15391     * for cases that do not need it (for example, a component that remains at
15392     * the same dimensions with the same content).
15393     *
15394     * @param invalidateCache Whether the drawing cache for this view should be
15395     *            invalidated as well. This is usually true for a full
15396     *            invalidate, but may be set to false if the View's contents or
15397     *            dimensions have not changed.
15398     * @hide
15399     */
15400    public void invalidate(boolean invalidateCache) {
15401        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15402    }
15403
15404    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15405            boolean fullInvalidate) {
15406        if (mGhostView != null) {
15407            mGhostView.invalidate(true);
15408            return;
15409        }
15410
15411        if (skipInvalidate()) {
15412            return;
15413        }
15414
15415        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15416                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15417                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15418                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15419            if (fullInvalidate) {
15420                mLastIsOpaque = isOpaque();
15421                mPrivateFlags &= ~PFLAG_DRAWN;
15422            }
15423
15424            mPrivateFlags |= PFLAG_DIRTY;
15425
15426            if (invalidateCache) {
15427                mPrivateFlags |= PFLAG_INVALIDATED;
15428                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15429            }
15430
15431            // Propagate the damage rectangle to the parent view.
15432            final AttachInfo ai = mAttachInfo;
15433            final ViewParent p = mParent;
15434            if (p != null && ai != null && l < r && t < b) {
15435                final Rect damage = ai.mTmpInvalRect;
15436                damage.set(l, t, r, b);
15437                p.invalidateChild(this, damage);
15438            }
15439
15440            // Damage the entire projection receiver, if necessary.
15441            if (mBackground != null && mBackground.isProjected()) {
15442                final View receiver = getProjectionReceiver();
15443                if (receiver != null) {
15444                    receiver.damageInParent();
15445                }
15446            }
15447        }
15448    }
15449
15450    /**
15451     * @return this view's projection receiver, or {@code null} if none exists
15452     */
15453    private View getProjectionReceiver() {
15454        ViewParent p = getParent();
15455        while (p != null && p instanceof View) {
15456            final View v = (View) p;
15457            if (v.isProjectionReceiver()) {
15458                return v;
15459            }
15460            p = p.getParent();
15461        }
15462
15463        return null;
15464    }
15465
15466    /**
15467     * @return whether the view is a projection receiver
15468     */
15469    private boolean isProjectionReceiver() {
15470        return mBackground != null;
15471    }
15472
15473    /**
15474     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15475     * set any flags or handle all of the cases handled by the default invalidation methods.
15476     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15477     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15478     * walk up the hierarchy, transforming the dirty rect as necessary.
15479     *
15480     * The method also handles normal invalidation logic if display list properties are not
15481     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15482     * backup approach, to handle these cases used in the various property-setting methods.
15483     *
15484     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15485     * are not being used in this view
15486     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15487     * list properties are not being used in this view
15488     */
15489    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15490        if (!isHardwareAccelerated()
15491                || !mRenderNode.isValid()
15492                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15493            if (invalidateParent) {
15494                invalidateParentCaches();
15495            }
15496            if (forceRedraw) {
15497                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15498            }
15499            invalidate(false);
15500        } else {
15501            damageInParent();
15502        }
15503    }
15504
15505    /**
15506     * Tells the parent view to damage this view's bounds.
15507     *
15508     * @hide
15509     */
15510    protected void damageInParent() {
15511        if (mParent != null && mAttachInfo != null) {
15512            mParent.onDescendantInvalidated(this, this);
15513        }
15514    }
15515
15516    /**
15517     * Utility method to transform a given Rect by the current matrix of this view.
15518     */
15519    void transformRect(final Rect rect) {
15520        if (!getMatrix().isIdentity()) {
15521            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15522            boundingRect.set(rect);
15523            getMatrix().mapRect(boundingRect);
15524            rect.set((int) Math.floor(boundingRect.left),
15525                    (int) Math.floor(boundingRect.top),
15526                    (int) Math.ceil(boundingRect.right),
15527                    (int) Math.ceil(boundingRect.bottom));
15528        }
15529    }
15530
15531    /**
15532     * Used to indicate that the parent of this view should clear its caches. This functionality
15533     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15534     * which is necessary when various parent-managed properties of the view change, such as
15535     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15536     * clears the parent caches and does not causes an invalidate event.
15537     *
15538     * @hide
15539     */
15540    protected void invalidateParentCaches() {
15541        if (mParent instanceof View) {
15542            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15543        }
15544    }
15545
15546    /**
15547     * Used to indicate that the parent of this view should be invalidated. This functionality
15548     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15549     * which is necessary when various parent-managed properties of the view change, such as
15550     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15551     * an invalidation event to the parent.
15552     *
15553     * @hide
15554     */
15555    protected void invalidateParentIfNeeded() {
15556        if (isHardwareAccelerated() && mParent instanceof View) {
15557            ((View) mParent).invalidate(true);
15558        }
15559    }
15560
15561    /**
15562     * @hide
15563     */
15564    protected void invalidateParentIfNeededAndWasQuickRejected() {
15565        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15566            // View was rejected last time it was drawn by its parent; this may have changed
15567            invalidateParentIfNeeded();
15568        }
15569    }
15570
15571    /**
15572     * Indicates whether this View is opaque. An opaque View guarantees that it will
15573     * draw all the pixels overlapping its bounds using a fully opaque color.
15574     *
15575     * Subclasses of View should override this method whenever possible to indicate
15576     * whether an instance is opaque. Opaque Views are treated in a special way by
15577     * the View hierarchy, possibly allowing it to perform optimizations during
15578     * invalidate/draw passes.
15579     *
15580     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15581     */
15582    @ViewDebug.ExportedProperty(category = "drawing")
15583    public boolean isOpaque() {
15584        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15585                getFinalAlpha() >= 1.0f;
15586    }
15587
15588    /**
15589     * @hide
15590     */
15591    protected void computeOpaqueFlags() {
15592        // Opaque if:
15593        //   - Has a background
15594        //   - Background is opaque
15595        //   - Doesn't have scrollbars or scrollbars overlay
15596
15597        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15598            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15599        } else {
15600            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15601        }
15602
15603        final int flags = mViewFlags;
15604        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15605                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15606                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15607            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15608        } else {
15609            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15610        }
15611    }
15612
15613    /**
15614     * @hide
15615     */
15616    protected boolean hasOpaqueScrollbars() {
15617        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15618    }
15619
15620    /**
15621     * @return A handler associated with the thread running the View. This
15622     * handler can be used to pump events in the UI events queue.
15623     */
15624    public Handler getHandler() {
15625        final AttachInfo attachInfo = mAttachInfo;
15626        if (attachInfo != null) {
15627            return attachInfo.mHandler;
15628        }
15629        return null;
15630    }
15631
15632    /**
15633     * Returns the queue of runnable for this view.
15634     *
15635     * @return the queue of runnables for this view
15636     */
15637    private HandlerActionQueue getRunQueue() {
15638        if (mRunQueue == null) {
15639            mRunQueue = new HandlerActionQueue();
15640        }
15641        return mRunQueue;
15642    }
15643
15644    /**
15645     * Gets the view root associated with the View.
15646     * @return The view root, or null if none.
15647     * @hide
15648     */
15649    public ViewRootImpl getViewRootImpl() {
15650        if (mAttachInfo != null) {
15651            return mAttachInfo.mViewRootImpl;
15652        }
15653        return null;
15654    }
15655
15656    /**
15657     * @hide
15658     */
15659    public ThreadedRenderer getThreadedRenderer() {
15660        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15661    }
15662
15663    /**
15664     * <p>Causes the Runnable to be added to the message queue.
15665     * The runnable will be run on the user interface thread.</p>
15666     *
15667     * @param action The Runnable that will be executed.
15668     *
15669     * @return Returns true if the Runnable was successfully placed in to the
15670     *         message queue.  Returns false on failure, usually because the
15671     *         looper processing the message queue is exiting.
15672     *
15673     * @see #postDelayed
15674     * @see #removeCallbacks
15675     */
15676    public boolean post(Runnable action) {
15677        final AttachInfo attachInfo = mAttachInfo;
15678        if (attachInfo != null) {
15679            return attachInfo.mHandler.post(action);
15680        }
15681
15682        // Postpone the runnable until we know on which thread it needs to run.
15683        // Assume that the runnable will be successfully placed after attach.
15684        getRunQueue().post(action);
15685        return true;
15686    }
15687
15688    /**
15689     * <p>Causes the Runnable to be added to the message queue, to be run
15690     * after the specified amount of time elapses.
15691     * The runnable will be run on the user interface thread.</p>
15692     *
15693     * @param action The Runnable that will be executed.
15694     * @param delayMillis The delay (in milliseconds) until the Runnable
15695     *        will be executed.
15696     *
15697     * @return true if the Runnable was successfully placed in to the
15698     *         message queue.  Returns false on failure, usually because the
15699     *         looper processing the message queue is exiting.  Note that a
15700     *         result of true does not mean the Runnable will be processed --
15701     *         if the looper is quit before the delivery time of the message
15702     *         occurs then the message will be dropped.
15703     *
15704     * @see #post
15705     * @see #removeCallbacks
15706     */
15707    public boolean postDelayed(Runnable action, long delayMillis) {
15708        final AttachInfo attachInfo = mAttachInfo;
15709        if (attachInfo != null) {
15710            return attachInfo.mHandler.postDelayed(action, delayMillis);
15711        }
15712
15713        // Postpone the runnable until we know on which thread it needs to run.
15714        // Assume that the runnable will be successfully placed after attach.
15715        getRunQueue().postDelayed(action, delayMillis);
15716        return true;
15717    }
15718
15719    /**
15720     * <p>Causes the Runnable to execute on the next animation time step.
15721     * The runnable will be run on the user interface thread.</p>
15722     *
15723     * @param action The Runnable that will be executed.
15724     *
15725     * @see #postOnAnimationDelayed
15726     * @see #removeCallbacks
15727     */
15728    public void postOnAnimation(Runnable action) {
15729        final AttachInfo attachInfo = mAttachInfo;
15730        if (attachInfo != null) {
15731            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15732                    Choreographer.CALLBACK_ANIMATION, action, null);
15733        } else {
15734            // Postpone the runnable until we know
15735            // on which thread it needs to run.
15736            getRunQueue().post(action);
15737        }
15738    }
15739
15740    /**
15741     * <p>Causes the Runnable to execute on the next animation time step,
15742     * after the specified amount of time elapses.
15743     * The runnable will be run on the user interface thread.</p>
15744     *
15745     * @param action The Runnable that will be executed.
15746     * @param delayMillis The delay (in milliseconds) until the Runnable
15747     *        will be executed.
15748     *
15749     * @see #postOnAnimation
15750     * @see #removeCallbacks
15751     */
15752    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15753        final AttachInfo attachInfo = mAttachInfo;
15754        if (attachInfo != null) {
15755            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15756                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15757        } else {
15758            // Postpone the runnable until we know
15759            // on which thread it needs to run.
15760            getRunQueue().postDelayed(action, delayMillis);
15761        }
15762    }
15763
15764    /**
15765     * <p>Removes the specified Runnable from the message queue.</p>
15766     *
15767     * @param action The Runnable to remove from the message handling queue
15768     *
15769     * @return true if this view could ask the Handler to remove the Runnable,
15770     *         false otherwise. When the returned value is true, the Runnable
15771     *         may or may not have been actually removed from the message queue
15772     *         (for instance, if the Runnable was not in the queue already.)
15773     *
15774     * @see #post
15775     * @see #postDelayed
15776     * @see #postOnAnimation
15777     * @see #postOnAnimationDelayed
15778     */
15779    public boolean removeCallbacks(Runnable action) {
15780        if (action != null) {
15781            final AttachInfo attachInfo = mAttachInfo;
15782            if (attachInfo != null) {
15783                attachInfo.mHandler.removeCallbacks(action);
15784                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15785                        Choreographer.CALLBACK_ANIMATION, action, null);
15786            }
15787            getRunQueue().removeCallbacks(action);
15788        }
15789        return true;
15790    }
15791
15792    /**
15793     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15794     * Use this to invalidate the View from a non-UI thread.</p>
15795     *
15796     * <p>This method can be invoked from outside of the UI thread
15797     * only when this View is attached to a window.</p>
15798     *
15799     * @see #invalidate()
15800     * @see #postInvalidateDelayed(long)
15801     */
15802    public void postInvalidate() {
15803        postInvalidateDelayed(0);
15804    }
15805
15806    /**
15807     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15808     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15809     *
15810     * <p>This method can be invoked from outside of the UI thread
15811     * only when this View is attached to a window.</p>
15812     *
15813     * @param left The left coordinate of the rectangle to invalidate.
15814     * @param top The top coordinate of the rectangle to invalidate.
15815     * @param right The right coordinate of the rectangle to invalidate.
15816     * @param bottom The bottom coordinate of the rectangle to invalidate.
15817     *
15818     * @see #invalidate(int, int, int, int)
15819     * @see #invalidate(Rect)
15820     * @see #postInvalidateDelayed(long, int, int, int, int)
15821     */
15822    public void postInvalidate(int left, int top, int right, int bottom) {
15823        postInvalidateDelayed(0, left, top, right, bottom);
15824    }
15825
15826    /**
15827     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15828     * loop. Waits for the specified amount of time.</p>
15829     *
15830     * <p>This method can be invoked from outside of the UI thread
15831     * only when this View is attached to a window.</p>
15832     *
15833     * @param delayMilliseconds the duration in milliseconds to delay the
15834     *         invalidation by
15835     *
15836     * @see #invalidate()
15837     * @see #postInvalidate()
15838     */
15839    public void postInvalidateDelayed(long delayMilliseconds) {
15840        // We try only with the AttachInfo because there's no point in invalidating
15841        // if we are not attached to our window
15842        final AttachInfo attachInfo = mAttachInfo;
15843        if (attachInfo != null) {
15844            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15845        }
15846    }
15847
15848    /**
15849     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15850     * through the event loop. Waits for the specified amount of time.</p>
15851     *
15852     * <p>This method can be invoked from outside of the UI thread
15853     * only when this View is attached to a window.</p>
15854     *
15855     * @param delayMilliseconds the duration in milliseconds to delay the
15856     *         invalidation by
15857     * @param left The left coordinate of the rectangle to invalidate.
15858     * @param top The top coordinate of the rectangle to invalidate.
15859     * @param right The right coordinate of the rectangle to invalidate.
15860     * @param bottom The bottom coordinate of the rectangle to invalidate.
15861     *
15862     * @see #invalidate(int, int, int, int)
15863     * @see #invalidate(Rect)
15864     * @see #postInvalidate(int, int, int, int)
15865     */
15866    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15867            int right, int bottom) {
15868
15869        // We try only with the AttachInfo because there's no point in invalidating
15870        // if we are not attached to our window
15871        final AttachInfo attachInfo = mAttachInfo;
15872        if (attachInfo != null) {
15873            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15874            info.target = this;
15875            info.left = left;
15876            info.top = top;
15877            info.right = right;
15878            info.bottom = bottom;
15879
15880            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15881        }
15882    }
15883
15884    /**
15885     * <p>Cause an invalidate to happen on the next animation time step, typically the
15886     * next display frame.</p>
15887     *
15888     * <p>This method can be invoked from outside of the UI thread
15889     * only when this View is attached to a window.</p>
15890     *
15891     * @see #invalidate()
15892     */
15893    public void postInvalidateOnAnimation() {
15894        // We try only with the AttachInfo because there's no point in invalidating
15895        // if we are not attached to our window
15896        final AttachInfo attachInfo = mAttachInfo;
15897        if (attachInfo != null) {
15898            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15899        }
15900    }
15901
15902    /**
15903     * <p>Cause an invalidate of the specified area to happen on the next animation
15904     * time step, typically the next display frame.</p>
15905     *
15906     * <p>This method can be invoked from outside of the UI thread
15907     * only when this View is attached to a window.</p>
15908     *
15909     * @param left The left coordinate of the rectangle to invalidate.
15910     * @param top The top coordinate of the rectangle to invalidate.
15911     * @param right The right coordinate of the rectangle to invalidate.
15912     * @param bottom The bottom coordinate of the rectangle to invalidate.
15913     *
15914     * @see #invalidate(int, int, int, int)
15915     * @see #invalidate(Rect)
15916     */
15917    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15918        // We try only with the AttachInfo because there's no point in invalidating
15919        // if we are not attached to our window
15920        final AttachInfo attachInfo = mAttachInfo;
15921        if (attachInfo != null) {
15922            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15923            info.target = this;
15924            info.left = left;
15925            info.top = top;
15926            info.right = right;
15927            info.bottom = bottom;
15928
15929            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15930        }
15931    }
15932
15933    /**
15934     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15935     * This event is sent at most once every
15936     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15937     */
15938    private void postSendViewScrolledAccessibilityEventCallback() {
15939        if (mSendViewScrolledAccessibilityEvent == null) {
15940            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15941        }
15942        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15943            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15944            postDelayed(mSendViewScrolledAccessibilityEvent,
15945                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15946        }
15947    }
15948
15949    /**
15950     * Called by a parent to request that a child update its values for mScrollX
15951     * and mScrollY if necessary. This will typically be done if the child is
15952     * animating a scroll using a {@link android.widget.Scroller Scroller}
15953     * object.
15954     */
15955    public void computeScroll() {
15956    }
15957
15958    /**
15959     * <p>Indicate whether the horizontal edges are faded when the view is
15960     * scrolled horizontally.</p>
15961     *
15962     * @return true if the horizontal edges should are faded on scroll, false
15963     *         otherwise
15964     *
15965     * @see #setHorizontalFadingEdgeEnabled(boolean)
15966     *
15967     * @attr ref android.R.styleable#View_requiresFadingEdge
15968     */
15969    public boolean isHorizontalFadingEdgeEnabled() {
15970        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15971    }
15972
15973    /**
15974     * <p>Define whether the horizontal edges should be faded when this view
15975     * is scrolled horizontally.</p>
15976     *
15977     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15978     *                                    be faded when the view is scrolled
15979     *                                    horizontally
15980     *
15981     * @see #isHorizontalFadingEdgeEnabled()
15982     *
15983     * @attr ref android.R.styleable#View_requiresFadingEdge
15984     */
15985    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15986        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15987            if (horizontalFadingEdgeEnabled) {
15988                initScrollCache();
15989            }
15990
15991            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15992        }
15993    }
15994
15995    /**
15996     * <p>Indicate whether the vertical edges are faded when the view is
15997     * scrolled horizontally.</p>
15998     *
15999     * @return true if the vertical edges should are faded on scroll, false
16000     *         otherwise
16001     *
16002     * @see #setVerticalFadingEdgeEnabled(boolean)
16003     *
16004     * @attr ref android.R.styleable#View_requiresFadingEdge
16005     */
16006    public boolean isVerticalFadingEdgeEnabled() {
16007        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
16008    }
16009
16010    /**
16011     * <p>Define whether the vertical edges should be faded when this view
16012     * is scrolled vertically.</p>
16013     *
16014     * @param verticalFadingEdgeEnabled true if the vertical edges should
16015     *                                  be faded when the view is scrolled
16016     *                                  vertically
16017     *
16018     * @see #isVerticalFadingEdgeEnabled()
16019     *
16020     * @attr ref android.R.styleable#View_requiresFadingEdge
16021     */
16022    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
16023        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
16024            if (verticalFadingEdgeEnabled) {
16025                initScrollCache();
16026            }
16027
16028            mViewFlags ^= FADING_EDGE_VERTICAL;
16029        }
16030    }
16031
16032    /**
16033     * Returns the strength, or intensity, of the top faded edge. The strength is
16034     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16035     * returns 0.0 or 1.0 but no value in between.
16036     *
16037     * Subclasses should override this method to provide a smoother fade transition
16038     * when scrolling occurs.
16039     *
16040     * @return the intensity of the top fade as a float between 0.0f and 1.0f
16041     */
16042    protected float getTopFadingEdgeStrength() {
16043        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
16044    }
16045
16046    /**
16047     * Returns the strength, or intensity, of the bottom faded edge. The strength is
16048     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16049     * returns 0.0 or 1.0 but no value in between.
16050     *
16051     * Subclasses should override this method to provide a smoother fade transition
16052     * when scrolling occurs.
16053     *
16054     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
16055     */
16056    protected float getBottomFadingEdgeStrength() {
16057        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
16058                computeVerticalScrollRange() ? 1.0f : 0.0f;
16059    }
16060
16061    /**
16062     * Returns the strength, or intensity, of the left faded edge. The strength is
16063     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16064     * returns 0.0 or 1.0 but no value in between.
16065     *
16066     * Subclasses should override this method to provide a smoother fade transition
16067     * when scrolling occurs.
16068     *
16069     * @return the intensity of the left fade as a float between 0.0f and 1.0f
16070     */
16071    protected float getLeftFadingEdgeStrength() {
16072        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
16073    }
16074
16075    /**
16076     * Returns the strength, or intensity, of the right faded edge. The strength is
16077     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16078     * returns 0.0 or 1.0 but no value in between.
16079     *
16080     * Subclasses should override this method to provide a smoother fade transition
16081     * when scrolling occurs.
16082     *
16083     * @return the intensity of the right fade as a float between 0.0f and 1.0f
16084     */
16085    protected float getRightFadingEdgeStrength() {
16086        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
16087                computeHorizontalScrollRange() ? 1.0f : 0.0f;
16088    }
16089
16090    /**
16091     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
16092     * scrollbar is not drawn by default.</p>
16093     *
16094     * @return true if the horizontal scrollbar should be painted, false
16095     *         otherwise
16096     *
16097     * @see #setHorizontalScrollBarEnabled(boolean)
16098     */
16099    public boolean isHorizontalScrollBarEnabled() {
16100        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
16101    }
16102
16103    /**
16104     * <p>Define whether the horizontal scrollbar should be drawn or not. The
16105     * scrollbar is not drawn by default.</p>
16106     *
16107     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
16108     *                                   be painted
16109     *
16110     * @see #isHorizontalScrollBarEnabled()
16111     */
16112    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
16113        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
16114            mViewFlags ^= SCROLLBARS_HORIZONTAL;
16115            computeOpaqueFlags();
16116            resolvePadding();
16117        }
16118    }
16119
16120    /**
16121     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
16122     * scrollbar is not drawn by default.</p>
16123     *
16124     * @return true if the vertical scrollbar should be painted, false
16125     *         otherwise
16126     *
16127     * @see #setVerticalScrollBarEnabled(boolean)
16128     */
16129    public boolean isVerticalScrollBarEnabled() {
16130        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
16131    }
16132
16133    /**
16134     * <p>Define whether the vertical scrollbar should be drawn or not. The
16135     * scrollbar is not drawn by default.</p>
16136     *
16137     * @param verticalScrollBarEnabled true if the vertical scrollbar should
16138     *                                 be painted
16139     *
16140     * @see #isVerticalScrollBarEnabled()
16141     */
16142    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
16143        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
16144            mViewFlags ^= SCROLLBARS_VERTICAL;
16145            computeOpaqueFlags();
16146            resolvePadding();
16147        }
16148    }
16149
16150    /**
16151     * @hide
16152     */
16153    protected void recomputePadding() {
16154        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16155    }
16156
16157    /**
16158     * Define whether scrollbars will fade when the view is not scrolling.
16159     *
16160     * @param fadeScrollbars whether to enable fading
16161     *
16162     * @attr ref android.R.styleable#View_fadeScrollbars
16163     */
16164    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
16165        initScrollCache();
16166        final ScrollabilityCache scrollabilityCache = mScrollCache;
16167        scrollabilityCache.fadeScrollBars = fadeScrollbars;
16168        if (fadeScrollbars) {
16169            scrollabilityCache.state = ScrollabilityCache.OFF;
16170        } else {
16171            scrollabilityCache.state = ScrollabilityCache.ON;
16172        }
16173    }
16174
16175    /**
16176     *
16177     * Returns true if scrollbars will fade when this view is not scrolling
16178     *
16179     * @return true if scrollbar fading is enabled
16180     *
16181     * @attr ref android.R.styleable#View_fadeScrollbars
16182     */
16183    public boolean isScrollbarFadingEnabled() {
16184        return mScrollCache != null && mScrollCache.fadeScrollBars;
16185    }
16186
16187    /**
16188     *
16189     * Returns the delay before scrollbars fade.
16190     *
16191     * @return the delay before scrollbars fade
16192     *
16193     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16194     */
16195    public int getScrollBarDefaultDelayBeforeFade() {
16196        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
16197                mScrollCache.scrollBarDefaultDelayBeforeFade;
16198    }
16199
16200    /**
16201     * Define the delay before scrollbars fade.
16202     *
16203     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
16204     *
16205     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16206     */
16207    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
16208        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
16209    }
16210
16211    /**
16212     *
16213     * Returns the scrollbar fade duration.
16214     *
16215     * @return the scrollbar fade duration, in milliseconds
16216     *
16217     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16218     */
16219    public int getScrollBarFadeDuration() {
16220        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
16221                mScrollCache.scrollBarFadeDuration;
16222    }
16223
16224    /**
16225     * Define the scrollbar fade duration.
16226     *
16227     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
16228     *
16229     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16230     */
16231    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
16232        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
16233    }
16234
16235    /**
16236     *
16237     * Returns the scrollbar size.
16238     *
16239     * @return the scrollbar size
16240     *
16241     * @attr ref android.R.styleable#View_scrollbarSize
16242     */
16243    public int getScrollBarSize() {
16244        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
16245                mScrollCache.scrollBarSize;
16246    }
16247
16248    /**
16249     * Define the scrollbar size.
16250     *
16251     * @param scrollBarSize - the scrollbar size
16252     *
16253     * @attr ref android.R.styleable#View_scrollbarSize
16254     */
16255    public void setScrollBarSize(int scrollBarSize) {
16256        getScrollCache().scrollBarSize = scrollBarSize;
16257    }
16258
16259    /**
16260     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
16261     * inset. When inset, they add to the padding of the view. And the scrollbars
16262     * can be drawn inside the padding area or on the edge of the view. For example,
16263     * if a view has a background drawable and you want to draw the scrollbars
16264     * inside the padding specified by the drawable, you can use
16265     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
16266     * appear at the edge of the view, ignoring the padding, then you can use
16267     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
16268     * @param style the style of the scrollbars. Should be one of
16269     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
16270     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
16271     * @see #SCROLLBARS_INSIDE_OVERLAY
16272     * @see #SCROLLBARS_INSIDE_INSET
16273     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16274     * @see #SCROLLBARS_OUTSIDE_INSET
16275     *
16276     * @attr ref android.R.styleable#View_scrollbarStyle
16277     */
16278    public void setScrollBarStyle(@ScrollBarStyle int style) {
16279        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
16280            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
16281            computeOpaqueFlags();
16282            resolvePadding();
16283        }
16284    }
16285
16286    /**
16287     * <p>Returns the current scrollbar style.</p>
16288     * @return the current scrollbar style
16289     * @see #SCROLLBARS_INSIDE_OVERLAY
16290     * @see #SCROLLBARS_INSIDE_INSET
16291     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16292     * @see #SCROLLBARS_OUTSIDE_INSET
16293     *
16294     * @attr ref android.R.styleable#View_scrollbarStyle
16295     */
16296    @ViewDebug.ExportedProperty(mapping = {
16297            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
16298            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
16299            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
16300            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
16301    })
16302    @ScrollBarStyle
16303    public int getScrollBarStyle() {
16304        return mViewFlags & SCROLLBARS_STYLE_MASK;
16305    }
16306
16307    /**
16308     * <p>Compute the horizontal range that the horizontal scrollbar
16309     * represents.</p>
16310     *
16311     * <p>The range is expressed in arbitrary units that must be the same as the
16312     * units used by {@link #computeHorizontalScrollExtent()} and
16313     * {@link #computeHorizontalScrollOffset()}.</p>
16314     *
16315     * <p>The default range is the drawing width of this view.</p>
16316     *
16317     * @return the total horizontal range represented by the horizontal
16318     *         scrollbar
16319     *
16320     * @see #computeHorizontalScrollExtent()
16321     * @see #computeHorizontalScrollOffset()
16322     * @see android.widget.ScrollBarDrawable
16323     */
16324    protected int computeHorizontalScrollRange() {
16325        return getWidth();
16326    }
16327
16328    /**
16329     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16330     * within the horizontal range. This value is used to compute the position
16331     * of the thumb within the scrollbar's track.</p>
16332     *
16333     * <p>The range is expressed in arbitrary units that must be the same as the
16334     * units used by {@link #computeHorizontalScrollRange()} and
16335     * {@link #computeHorizontalScrollExtent()}.</p>
16336     *
16337     * <p>The default offset is the scroll offset of this view.</p>
16338     *
16339     * @return the horizontal offset of the scrollbar's thumb
16340     *
16341     * @see #computeHorizontalScrollRange()
16342     * @see #computeHorizontalScrollExtent()
16343     * @see android.widget.ScrollBarDrawable
16344     */
16345    protected int computeHorizontalScrollOffset() {
16346        return mScrollX;
16347    }
16348
16349    /**
16350     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16351     * within the horizontal range. This value is used to compute the length
16352     * of the thumb within the scrollbar's track.</p>
16353     *
16354     * <p>The range is expressed in arbitrary units that must be the same as the
16355     * units used by {@link #computeHorizontalScrollRange()} and
16356     * {@link #computeHorizontalScrollOffset()}.</p>
16357     *
16358     * <p>The default extent is the drawing width of this view.</p>
16359     *
16360     * @return the horizontal extent of the scrollbar's thumb
16361     *
16362     * @see #computeHorizontalScrollRange()
16363     * @see #computeHorizontalScrollOffset()
16364     * @see android.widget.ScrollBarDrawable
16365     */
16366    protected int computeHorizontalScrollExtent() {
16367        return getWidth();
16368    }
16369
16370    /**
16371     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16372     *
16373     * <p>The range is expressed in arbitrary units that must be the same as the
16374     * units used by {@link #computeVerticalScrollExtent()} and
16375     * {@link #computeVerticalScrollOffset()}.</p>
16376     *
16377     * @return the total vertical range represented by the vertical scrollbar
16378     *
16379     * <p>The default range is the drawing height of this view.</p>
16380     *
16381     * @see #computeVerticalScrollExtent()
16382     * @see #computeVerticalScrollOffset()
16383     * @see android.widget.ScrollBarDrawable
16384     */
16385    protected int computeVerticalScrollRange() {
16386        return getHeight();
16387    }
16388
16389    /**
16390     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16391     * within the horizontal range. This value is used to compute the position
16392     * of the thumb within the scrollbar's track.</p>
16393     *
16394     * <p>The range is expressed in arbitrary units that must be the same as the
16395     * units used by {@link #computeVerticalScrollRange()} and
16396     * {@link #computeVerticalScrollExtent()}.</p>
16397     *
16398     * <p>The default offset is the scroll offset of this view.</p>
16399     *
16400     * @return the vertical offset of the scrollbar's thumb
16401     *
16402     * @see #computeVerticalScrollRange()
16403     * @see #computeVerticalScrollExtent()
16404     * @see android.widget.ScrollBarDrawable
16405     */
16406    protected int computeVerticalScrollOffset() {
16407        return mScrollY;
16408    }
16409
16410    /**
16411     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16412     * within the vertical range. This value is used to compute the length
16413     * of the thumb within the scrollbar's track.</p>
16414     *
16415     * <p>The range is expressed in arbitrary units that must be the same as the
16416     * units used by {@link #computeVerticalScrollRange()} and
16417     * {@link #computeVerticalScrollOffset()}.</p>
16418     *
16419     * <p>The default extent is the drawing height of this view.</p>
16420     *
16421     * @return the vertical extent of the scrollbar's thumb
16422     *
16423     * @see #computeVerticalScrollRange()
16424     * @see #computeVerticalScrollOffset()
16425     * @see android.widget.ScrollBarDrawable
16426     */
16427    protected int computeVerticalScrollExtent() {
16428        return getHeight();
16429    }
16430
16431    /**
16432     * Check if this view can be scrolled horizontally in a certain direction.
16433     *
16434     * @param direction Negative to check scrolling left, positive to check scrolling right.
16435     * @return true if this view can be scrolled in the specified direction, false otherwise.
16436     */
16437    public boolean canScrollHorizontally(int direction) {
16438        final int offset = computeHorizontalScrollOffset();
16439        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16440        if (range == 0) return false;
16441        if (direction < 0) {
16442            return offset > 0;
16443        } else {
16444            return offset < range - 1;
16445        }
16446    }
16447
16448    /**
16449     * Check if this view can be scrolled vertically in a certain direction.
16450     *
16451     * @param direction Negative to check scrolling up, positive to check scrolling down.
16452     * @return true if this view can be scrolled in the specified direction, false otherwise.
16453     */
16454    public boolean canScrollVertically(int direction) {
16455        final int offset = computeVerticalScrollOffset();
16456        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16457        if (range == 0) return false;
16458        if (direction < 0) {
16459            return offset > 0;
16460        } else {
16461            return offset < range - 1;
16462        }
16463    }
16464
16465    void getScrollIndicatorBounds(@NonNull Rect out) {
16466        out.left = mScrollX;
16467        out.right = mScrollX + mRight - mLeft;
16468        out.top = mScrollY;
16469        out.bottom = mScrollY + mBottom - mTop;
16470    }
16471
16472    private void onDrawScrollIndicators(Canvas c) {
16473        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16474            // No scroll indicators enabled.
16475            return;
16476        }
16477
16478        final Drawable dr = mScrollIndicatorDrawable;
16479        if (dr == null) {
16480            // Scroll indicators aren't supported here.
16481            return;
16482        }
16483
16484        final int h = dr.getIntrinsicHeight();
16485        final int w = dr.getIntrinsicWidth();
16486        final Rect rect = mAttachInfo.mTmpInvalRect;
16487        getScrollIndicatorBounds(rect);
16488
16489        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16490            final boolean canScrollUp = canScrollVertically(-1);
16491            if (canScrollUp) {
16492                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16493                dr.draw(c);
16494            }
16495        }
16496
16497        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16498            final boolean canScrollDown = canScrollVertically(1);
16499            if (canScrollDown) {
16500                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16501                dr.draw(c);
16502            }
16503        }
16504
16505        final int leftRtl;
16506        final int rightRtl;
16507        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16508            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16509            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16510        } else {
16511            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16512            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16513        }
16514
16515        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16516        if ((mPrivateFlags3 & leftMask) != 0) {
16517            final boolean canScrollLeft = canScrollHorizontally(-1);
16518            if (canScrollLeft) {
16519                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16520                dr.draw(c);
16521            }
16522        }
16523
16524        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16525        if ((mPrivateFlags3 & rightMask) != 0) {
16526            final boolean canScrollRight = canScrollHorizontally(1);
16527            if (canScrollRight) {
16528                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16529                dr.draw(c);
16530            }
16531        }
16532    }
16533
16534    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16535            @Nullable Rect touchBounds) {
16536        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16537        if (bounds == null) {
16538            return;
16539        }
16540        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16541        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16542                && !isVerticalScrollBarHidden();
16543        final int size = getHorizontalScrollbarHeight();
16544        final int verticalScrollBarGap = drawVerticalScrollBar ?
16545                getVerticalScrollbarWidth() : 0;
16546        final int width = mRight - mLeft;
16547        final int height = mBottom - mTop;
16548        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16549        bounds.left = mScrollX + (mPaddingLeft & inside);
16550        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16551        bounds.bottom = bounds.top + size;
16552
16553        if (touchBounds == null) {
16554            return;
16555        }
16556        if (touchBounds != bounds) {
16557            touchBounds.set(bounds);
16558        }
16559        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16560        if (touchBounds.height() < minTouchTarget) {
16561            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16562            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16563            touchBounds.top = touchBounds.bottom - minTouchTarget;
16564        }
16565        if (touchBounds.width() < minTouchTarget) {
16566            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16567            touchBounds.left -= adjust;
16568            touchBounds.right = touchBounds.left + minTouchTarget;
16569        }
16570    }
16571
16572    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16573        if (mRoundScrollbarRenderer == null) {
16574            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16575        } else {
16576            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16577        }
16578    }
16579
16580    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16581        final int width = mRight - mLeft;
16582        final int height = mBottom - mTop;
16583        // Do not take padding into account as we always want the scrollbars
16584        // to hug the screen for round wearable devices.
16585        bounds.left = mScrollX;
16586        bounds.top = mScrollY;
16587        bounds.right = bounds.left + width;
16588        bounds.bottom = mScrollY + height;
16589    }
16590
16591    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16592            @Nullable Rect touchBounds) {
16593        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16594        if (bounds == null) {
16595            return;
16596        }
16597        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16598        final int size = getVerticalScrollbarWidth();
16599        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16600        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16601            verticalScrollbarPosition = isLayoutRtl() ?
16602                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16603        }
16604        final int width = mRight - mLeft;
16605        final int height = mBottom - mTop;
16606        switch (verticalScrollbarPosition) {
16607            default:
16608            case SCROLLBAR_POSITION_RIGHT:
16609                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16610                break;
16611            case SCROLLBAR_POSITION_LEFT:
16612                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16613                break;
16614        }
16615        bounds.top = mScrollY + (mPaddingTop & inside);
16616        bounds.right = bounds.left + size;
16617        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16618
16619        if (touchBounds == null) {
16620            return;
16621        }
16622        if (touchBounds != bounds) {
16623            touchBounds.set(bounds);
16624        }
16625        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16626        if (touchBounds.width() < minTouchTarget) {
16627            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16628            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16629                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16630                touchBounds.left = touchBounds.right - minTouchTarget;
16631            } else {
16632                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16633                touchBounds.right = touchBounds.left + minTouchTarget;
16634            }
16635        }
16636        if (touchBounds.height() < minTouchTarget) {
16637            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16638            touchBounds.top -= adjust;
16639            touchBounds.bottom = touchBounds.top + minTouchTarget;
16640        }
16641    }
16642
16643    /**
16644     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16645     * scrollbars are painted only if they have been awakened first.</p>
16646     *
16647     * @param canvas the canvas on which to draw the scrollbars
16648     *
16649     * @see #awakenScrollBars(int)
16650     */
16651    protected final void onDrawScrollBars(Canvas canvas) {
16652        // scrollbars are drawn only when the animation is running
16653        final ScrollabilityCache cache = mScrollCache;
16654
16655        if (cache != null) {
16656
16657            int state = cache.state;
16658
16659            if (state == ScrollabilityCache.OFF) {
16660                return;
16661            }
16662
16663            boolean invalidate = false;
16664
16665            if (state == ScrollabilityCache.FADING) {
16666                // We're fading -- get our fade interpolation
16667                if (cache.interpolatorValues == null) {
16668                    cache.interpolatorValues = new float[1];
16669                }
16670
16671                float[] values = cache.interpolatorValues;
16672
16673                // Stops the animation if we're done
16674                if (cache.scrollBarInterpolator.timeToValues(values) ==
16675                        Interpolator.Result.FREEZE_END) {
16676                    cache.state = ScrollabilityCache.OFF;
16677                } else {
16678                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16679                }
16680
16681                // This will make the scroll bars inval themselves after
16682                // drawing. We only want this when we're fading so that
16683                // we prevent excessive redraws
16684                invalidate = true;
16685            } else {
16686                // We're just on -- but we may have been fading before so
16687                // reset alpha
16688                cache.scrollBar.mutate().setAlpha(255);
16689            }
16690
16691            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16692            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16693                    && !isVerticalScrollBarHidden();
16694
16695            // Fork out the scroll bar drawing for round wearable devices.
16696            if (mRoundScrollbarRenderer != null) {
16697                if (drawVerticalScrollBar) {
16698                    final Rect bounds = cache.mScrollBarBounds;
16699                    getVerticalScrollBarBounds(bounds, null);
16700                    mRoundScrollbarRenderer.drawRoundScrollbars(
16701                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16702                    if (invalidate) {
16703                        invalidate();
16704                    }
16705                }
16706                // Do not draw horizontal scroll bars for round wearable devices.
16707            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16708                final ScrollBarDrawable scrollBar = cache.scrollBar;
16709
16710                if (drawHorizontalScrollBar) {
16711                    scrollBar.setParameters(computeHorizontalScrollRange(),
16712                            computeHorizontalScrollOffset(),
16713                            computeHorizontalScrollExtent(), false);
16714                    final Rect bounds = cache.mScrollBarBounds;
16715                    getHorizontalScrollBarBounds(bounds, null);
16716                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16717                            bounds.right, bounds.bottom);
16718                    if (invalidate) {
16719                        invalidate(bounds);
16720                    }
16721                }
16722
16723                if (drawVerticalScrollBar) {
16724                    scrollBar.setParameters(computeVerticalScrollRange(),
16725                            computeVerticalScrollOffset(),
16726                            computeVerticalScrollExtent(), true);
16727                    final Rect bounds = cache.mScrollBarBounds;
16728                    getVerticalScrollBarBounds(bounds, null);
16729                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16730                            bounds.right, bounds.bottom);
16731                    if (invalidate) {
16732                        invalidate(bounds);
16733                    }
16734                }
16735            }
16736        }
16737    }
16738
16739    /**
16740     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16741     * FastScroller is visible.
16742     * @return whether to temporarily hide the vertical scrollbar
16743     * @hide
16744     */
16745    protected boolean isVerticalScrollBarHidden() {
16746        return false;
16747    }
16748
16749    /**
16750     * <p>Draw the horizontal scrollbar if
16751     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16752     *
16753     * @param canvas the canvas on which to draw the scrollbar
16754     * @param scrollBar the scrollbar's drawable
16755     *
16756     * @see #isHorizontalScrollBarEnabled()
16757     * @see #computeHorizontalScrollRange()
16758     * @see #computeHorizontalScrollExtent()
16759     * @see #computeHorizontalScrollOffset()
16760     * @see android.widget.ScrollBarDrawable
16761     * @hide
16762     */
16763    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16764            int l, int t, int r, int b) {
16765        scrollBar.setBounds(l, t, r, b);
16766        scrollBar.draw(canvas);
16767    }
16768
16769    /**
16770     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16771     * returns true.</p>
16772     *
16773     * @param canvas the canvas on which to draw the scrollbar
16774     * @param scrollBar the scrollbar's drawable
16775     *
16776     * @see #isVerticalScrollBarEnabled()
16777     * @see #computeVerticalScrollRange()
16778     * @see #computeVerticalScrollExtent()
16779     * @see #computeVerticalScrollOffset()
16780     * @see android.widget.ScrollBarDrawable
16781     * @hide
16782     */
16783    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16784            int l, int t, int r, int b) {
16785        scrollBar.setBounds(l, t, r, b);
16786        scrollBar.draw(canvas);
16787    }
16788
16789    /**
16790     * Implement this to do your drawing.
16791     *
16792     * @param canvas the canvas on which the background will be drawn
16793     */
16794    protected void onDraw(Canvas canvas) {
16795    }
16796
16797    /*
16798     * Caller is responsible for calling requestLayout if necessary.
16799     * (This allows addViewInLayout to not request a new layout.)
16800     */
16801    void assignParent(ViewParent parent) {
16802        if (mParent == null) {
16803            mParent = parent;
16804        } else if (parent == null) {
16805            mParent = null;
16806        } else {
16807            throw new RuntimeException("view " + this + " being added, but"
16808                    + " it already has a parent");
16809        }
16810    }
16811
16812    /**
16813     * This is called when the view is attached to a window.  At this point it
16814     * has a Surface and will start drawing.  Note that this function is
16815     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16816     * however it may be called any time before the first onDraw -- including
16817     * before or after {@link #onMeasure(int, int)}.
16818     *
16819     * @see #onDetachedFromWindow()
16820     */
16821    @CallSuper
16822    protected void onAttachedToWindow() {
16823        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16824            mParent.requestTransparentRegion(this);
16825        }
16826
16827        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16828
16829        jumpDrawablesToCurrentState();
16830
16831        resetSubtreeAccessibilityStateChanged();
16832
16833        // rebuild, since Outline not maintained while View is detached
16834        rebuildOutline();
16835
16836        if (isFocused()) {
16837            InputMethodManager imm = InputMethodManager.peekInstance();
16838            if (imm != null) {
16839                imm.focusIn(this);
16840            }
16841        }
16842    }
16843
16844    /**
16845     * Resolve all RTL related properties.
16846     *
16847     * @return true if resolution of RTL properties has been done
16848     *
16849     * @hide
16850     */
16851    public boolean resolveRtlPropertiesIfNeeded() {
16852        if (!needRtlPropertiesResolution()) return false;
16853
16854        // Order is important here: LayoutDirection MUST be resolved first
16855        if (!isLayoutDirectionResolved()) {
16856            resolveLayoutDirection();
16857            resolveLayoutParams();
16858        }
16859        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16860        if (!isTextDirectionResolved()) {
16861            resolveTextDirection();
16862        }
16863        if (!isTextAlignmentResolved()) {
16864            resolveTextAlignment();
16865        }
16866        // Should resolve Drawables before Padding because we need the layout direction of the
16867        // Drawable to correctly resolve Padding.
16868        if (!areDrawablesResolved()) {
16869            resolveDrawables();
16870        }
16871        if (!isPaddingResolved()) {
16872            resolvePadding();
16873        }
16874        onRtlPropertiesChanged(getLayoutDirection());
16875        return true;
16876    }
16877
16878    /**
16879     * Reset resolution of all RTL related properties.
16880     *
16881     * @hide
16882     */
16883    public void resetRtlProperties() {
16884        resetResolvedLayoutDirection();
16885        resetResolvedTextDirection();
16886        resetResolvedTextAlignment();
16887        resetResolvedPadding();
16888        resetResolvedDrawables();
16889    }
16890
16891    /**
16892     * @see #onScreenStateChanged(int)
16893     */
16894    void dispatchScreenStateChanged(int screenState) {
16895        onScreenStateChanged(screenState);
16896    }
16897
16898    /**
16899     * This method is called whenever the state of the screen this view is
16900     * attached to changes. A state change will usually occurs when the screen
16901     * turns on or off (whether it happens automatically or the user does it
16902     * manually.)
16903     *
16904     * @param screenState The new state of the screen. Can be either
16905     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16906     */
16907    public void onScreenStateChanged(int screenState) {
16908    }
16909
16910    /**
16911     * @see #onMovedToDisplay(int, Configuration)
16912     */
16913    void dispatchMovedToDisplay(Display display, Configuration config) {
16914        mAttachInfo.mDisplay = display;
16915        mAttachInfo.mDisplayState = display.getState();
16916        onMovedToDisplay(display.getDisplayId(), config);
16917    }
16918
16919    /**
16920     * Called by the system when the hosting activity is moved from one display to another without
16921     * recreation. This means that the activity is declared to handle all changes to configuration
16922     * that happened when it was switched to another display, so it wasn't destroyed and created
16923     * again.
16924     *
16925     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16926     * applied configuration actually changed. It is up to app developer to choose whether to handle
16927     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16928     * call.
16929     *
16930     * <p>Use this callback to track changes to the displays if some functionality relies on an
16931     * association with some display properties.
16932     *
16933     * @param displayId The id of the display to which the view was moved.
16934     * @param config Configuration of the resources on new display after move.
16935     *
16936     * @see #onConfigurationChanged(Configuration)
16937     * @hide
16938     */
16939    public void onMovedToDisplay(int displayId, Configuration config) {
16940    }
16941
16942    /**
16943     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16944     */
16945    private boolean hasRtlSupport() {
16946        return mContext.getApplicationInfo().hasRtlSupport();
16947    }
16948
16949    /**
16950     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16951     * RTL not supported)
16952     */
16953    private boolean isRtlCompatibilityMode() {
16954        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16955        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16956    }
16957
16958    /**
16959     * @return true if RTL properties need resolution.
16960     *
16961     */
16962    private boolean needRtlPropertiesResolution() {
16963        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16964    }
16965
16966    /**
16967     * Called when any RTL property (layout direction or text direction or text alignment) has
16968     * been changed.
16969     *
16970     * Subclasses need to override this method to take care of cached information that depends on the
16971     * resolved layout direction, or to inform child views that inherit their layout direction.
16972     *
16973     * The default implementation does nothing.
16974     *
16975     * @param layoutDirection the direction of the layout
16976     *
16977     * @see #LAYOUT_DIRECTION_LTR
16978     * @see #LAYOUT_DIRECTION_RTL
16979     */
16980    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16981    }
16982
16983    /**
16984     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16985     * that the parent directionality can and will be resolved before its children.
16986     *
16987     * @return true if resolution has been done, false otherwise.
16988     *
16989     * @hide
16990     */
16991    public boolean resolveLayoutDirection() {
16992        // Clear any previous layout direction resolution
16993        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16994
16995        if (hasRtlSupport()) {
16996            // Set resolved depending on layout direction
16997            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16998                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16999                case LAYOUT_DIRECTION_INHERIT:
17000                    // We cannot resolve yet. LTR is by default and let the resolution happen again
17001                    // later to get the correct resolved value
17002                    if (!canResolveLayoutDirection()) return false;
17003
17004                    // Parent has not yet resolved, LTR is still the default
17005                    try {
17006                        if (!mParent.isLayoutDirectionResolved()) return false;
17007
17008                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
17009                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17010                        }
17011                    } catch (AbstractMethodError e) {
17012                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17013                                " does not fully implement ViewParent", e);
17014                    }
17015                    break;
17016                case LAYOUT_DIRECTION_RTL:
17017                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17018                    break;
17019                case LAYOUT_DIRECTION_LOCALE:
17020                    if((LAYOUT_DIRECTION_RTL ==
17021                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
17022                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17023                    }
17024                    break;
17025                default:
17026                    // Nothing to do, LTR by default
17027            }
17028        }
17029
17030        // Set to resolved
17031        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17032        return true;
17033    }
17034
17035    /**
17036     * Check if layout direction resolution can be done.
17037     *
17038     * @return true if layout direction resolution can be done otherwise return false.
17039     */
17040    public boolean canResolveLayoutDirection() {
17041        switch (getRawLayoutDirection()) {
17042            case LAYOUT_DIRECTION_INHERIT:
17043                if (mParent != null) {
17044                    try {
17045                        return mParent.canResolveLayoutDirection();
17046                    } catch (AbstractMethodError e) {
17047                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17048                                " does not fully implement ViewParent", e);
17049                    }
17050                }
17051                return false;
17052
17053            default:
17054                return true;
17055        }
17056    }
17057
17058    /**
17059     * Reset the resolved layout direction. Layout direction will be resolved during a call to
17060     * {@link #onMeasure(int, int)}.
17061     *
17062     * @hide
17063     */
17064    public void resetResolvedLayoutDirection() {
17065        // Reset the current resolved bits
17066        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17067    }
17068
17069    /**
17070     * @return true if the layout direction is inherited.
17071     *
17072     * @hide
17073     */
17074    public boolean isLayoutDirectionInherited() {
17075        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
17076    }
17077
17078    /**
17079     * @return true if layout direction has been resolved.
17080     */
17081    public boolean isLayoutDirectionResolved() {
17082        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17083    }
17084
17085    /**
17086     * Return if padding has been resolved
17087     *
17088     * @hide
17089     */
17090    boolean isPaddingResolved() {
17091        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
17092    }
17093
17094    /**
17095     * Resolves padding depending on layout direction, if applicable, and
17096     * recomputes internal padding values to adjust for scroll bars.
17097     *
17098     * @hide
17099     */
17100    public void resolvePadding() {
17101        final int resolvedLayoutDirection = getLayoutDirection();
17102
17103        if (!isRtlCompatibilityMode()) {
17104            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
17105            // If start / end padding are defined, they will be resolved (hence overriding) to
17106            // left / right or right / left depending on the resolved layout direction.
17107            // If start / end padding are not defined, use the left / right ones.
17108            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
17109                Rect padding = sThreadLocal.get();
17110                if (padding == null) {
17111                    padding = new Rect();
17112                    sThreadLocal.set(padding);
17113                }
17114                mBackground.getPadding(padding);
17115                if (!mLeftPaddingDefined) {
17116                    mUserPaddingLeftInitial = padding.left;
17117                }
17118                if (!mRightPaddingDefined) {
17119                    mUserPaddingRightInitial = padding.right;
17120                }
17121            }
17122            switch (resolvedLayoutDirection) {
17123                case LAYOUT_DIRECTION_RTL:
17124                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17125                        mUserPaddingRight = mUserPaddingStart;
17126                    } else {
17127                        mUserPaddingRight = mUserPaddingRightInitial;
17128                    }
17129                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17130                        mUserPaddingLeft = mUserPaddingEnd;
17131                    } else {
17132                        mUserPaddingLeft = mUserPaddingLeftInitial;
17133                    }
17134                    break;
17135                case LAYOUT_DIRECTION_LTR:
17136                default:
17137                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17138                        mUserPaddingLeft = mUserPaddingStart;
17139                    } else {
17140                        mUserPaddingLeft = mUserPaddingLeftInitial;
17141                    }
17142                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17143                        mUserPaddingRight = mUserPaddingEnd;
17144                    } else {
17145                        mUserPaddingRight = mUserPaddingRightInitial;
17146                    }
17147            }
17148
17149            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
17150        }
17151
17152        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17153        onRtlPropertiesChanged(resolvedLayoutDirection);
17154
17155        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
17156    }
17157
17158    /**
17159     * Reset the resolved layout direction.
17160     *
17161     * @hide
17162     */
17163    public void resetResolvedPadding() {
17164        resetResolvedPaddingInternal();
17165    }
17166
17167    /**
17168     * Used when we only want to reset *this* view's padding and not trigger overrides
17169     * in ViewGroup that reset children too.
17170     */
17171    void resetResolvedPaddingInternal() {
17172        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
17173    }
17174
17175    /**
17176     * This is called when the view is detached from a window.  At this point it
17177     * no longer has a surface for drawing.
17178     *
17179     * @see #onAttachedToWindow()
17180     */
17181    @CallSuper
17182    protected void onDetachedFromWindow() {
17183    }
17184
17185    /**
17186     * This is a framework-internal mirror of onDetachedFromWindow() that's called
17187     * after onDetachedFromWindow().
17188     *
17189     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
17190     * The super method should be called at the end of the overridden method to ensure
17191     * subclasses are destroyed first
17192     *
17193     * @hide
17194     */
17195    @CallSuper
17196    protected void onDetachedFromWindowInternal() {
17197        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
17198        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17199        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
17200
17201        removeUnsetPressCallback();
17202        removeLongPressCallback();
17203        removePerformClickCallback();
17204        removeSendViewScrolledAccessibilityEventCallback();
17205        stopNestedScroll();
17206
17207        // Anything that started animating right before detach should already
17208        // be in its final state when re-attached.
17209        jumpDrawablesToCurrentState();
17210
17211        destroyDrawingCache();
17212
17213        cleanupDraw();
17214        mCurrentAnimation = null;
17215
17216        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
17217            hideTooltip();
17218        }
17219    }
17220
17221    private void cleanupDraw() {
17222        resetDisplayList();
17223        if (mAttachInfo != null) {
17224            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
17225        }
17226    }
17227
17228    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
17229    }
17230
17231    /**
17232     * @return The number of times this view has been attached to a window
17233     */
17234    protected int getWindowAttachCount() {
17235        return mWindowAttachCount;
17236    }
17237
17238    /**
17239     * Retrieve a unique token identifying the window this view is attached to.
17240     * @return Return the window's token for use in
17241     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
17242     */
17243    public IBinder getWindowToken() {
17244        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
17245    }
17246
17247    /**
17248     * Retrieve the {@link WindowId} for the window this view is
17249     * currently attached to.
17250     */
17251    public WindowId getWindowId() {
17252        if (mAttachInfo == null) {
17253            return null;
17254        }
17255        if (mAttachInfo.mWindowId == null) {
17256            try {
17257                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
17258                        mAttachInfo.mWindowToken);
17259                mAttachInfo.mWindowId = new WindowId(
17260                        mAttachInfo.mIWindowId);
17261            } catch (RemoteException e) {
17262            }
17263        }
17264        return mAttachInfo.mWindowId;
17265    }
17266
17267    /**
17268     * Retrieve a unique token identifying the top-level "real" window of
17269     * the window that this view is attached to.  That is, this is like
17270     * {@link #getWindowToken}, except if the window this view in is a panel
17271     * window (attached to another containing window), then the token of
17272     * the containing window is returned instead.
17273     *
17274     * @return Returns the associated window token, either
17275     * {@link #getWindowToken()} or the containing window's token.
17276     */
17277    public IBinder getApplicationWindowToken() {
17278        AttachInfo ai = mAttachInfo;
17279        if (ai != null) {
17280            IBinder appWindowToken = ai.mPanelParentWindowToken;
17281            if (appWindowToken == null) {
17282                appWindowToken = ai.mWindowToken;
17283            }
17284            return appWindowToken;
17285        }
17286        return null;
17287    }
17288
17289    /**
17290     * Gets the logical display to which the view's window has been attached.
17291     *
17292     * @return The logical display, or null if the view is not currently attached to a window.
17293     */
17294    public Display getDisplay() {
17295        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
17296    }
17297
17298    /**
17299     * Retrieve private session object this view hierarchy is using to
17300     * communicate with the window manager.
17301     * @return the session object to communicate with the window manager
17302     */
17303    /*package*/ IWindowSession getWindowSession() {
17304        return mAttachInfo != null ? mAttachInfo.mSession : null;
17305    }
17306
17307    /**
17308     * Return the visibility value of the least visible component passed.
17309     */
17310    int combineVisibility(int vis1, int vis2) {
17311        // This works because VISIBLE < INVISIBLE < GONE.
17312        return Math.max(vis1, vis2);
17313    }
17314
17315    /**
17316     * @param info the {@link android.view.View.AttachInfo} to associated with
17317     *        this view
17318     */
17319    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17320        mAttachInfo = info;
17321        if (mOverlay != null) {
17322            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17323        }
17324        mWindowAttachCount++;
17325        // We will need to evaluate the drawable state at least once.
17326        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17327        if (mFloatingTreeObserver != null) {
17328            info.mTreeObserver.merge(mFloatingTreeObserver);
17329            mFloatingTreeObserver = null;
17330        }
17331
17332        registerPendingFrameMetricsObservers();
17333
17334        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17335            mAttachInfo.mScrollContainers.add(this);
17336            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17337        }
17338        // Transfer all pending runnables.
17339        if (mRunQueue != null) {
17340            mRunQueue.executeActions(info.mHandler);
17341            mRunQueue = null;
17342        }
17343        performCollectViewAttributes(mAttachInfo, visibility);
17344        onAttachedToWindow();
17345
17346        ListenerInfo li = mListenerInfo;
17347        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17348                li != null ? li.mOnAttachStateChangeListeners : null;
17349        if (listeners != null && listeners.size() > 0) {
17350            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17351            // perform the dispatching. The iterator is a safe guard against listeners that
17352            // could mutate the list by calling the various add/remove methods. This prevents
17353            // the array from being modified while we iterate it.
17354            for (OnAttachStateChangeListener listener : listeners) {
17355                listener.onViewAttachedToWindow(this);
17356            }
17357        }
17358
17359        int vis = info.mWindowVisibility;
17360        if (vis != GONE) {
17361            onWindowVisibilityChanged(vis);
17362            if (isShown()) {
17363                // Calling onVisibilityAggregated directly here since the subtree will also
17364                // receive dispatchAttachedToWindow and this same call
17365                onVisibilityAggregated(vis == VISIBLE);
17366            }
17367        }
17368
17369        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17370        // As all views in the subtree will already receive dispatchAttachedToWindow
17371        // traversing the subtree again here is not desired.
17372        onVisibilityChanged(this, visibility);
17373
17374        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17375            // If nobody has evaluated the drawable state yet, then do it now.
17376            refreshDrawableState();
17377        }
17378        needGlobalAttributesUpdate(false);
17379
17380        notifyEnterOrExitForAutoFillIfNeeded(true);
17381    }
17382
17383    void dispatchDetachedFromWindow() {
17384        AttachInfo info = mAttachInfo;
17385        if (info != null) {
17386            int vis = info.mWindowVisibility;
17387            if (vis != GONE) {
17388                onWindowVisibilityChanged(GONE);
17389                if (isShown()) {
17390                    // Invoking onVisibilityAggregated directly here since the subtree
17391                    // will also receive detached from window
17392                    onVisibilityAggregated(false);
17393                }
17394            }
17395        }
17396
17397        onDetachedFromWindow();
17398        onDetachedFromWindowInternal();
17399
17400        InputMethodManager imm = InputMethodManager.peekInstance();
17401        if (imm != null) {
17402            imm.onViewDetachedFromWindow(this);
17403        }
17404
17405        ListenerInfo li = mListenerInfo;
17406        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17407                li != null ? li.mOnAttachStateChangeListeners : null;
17408        if (listeners != null && listeners.size() > 0) {
17409            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17410            // perform the dispatching. The iterator is a safe guard against listeners that
17411            // could mutate the list by calling the various add/remove methods. This prevents
17412            // the array from being modified while we iterate it.
17413            for (OnAttachStateChangeListener listener : listeners) {
17414                listener.onViewDetachedFromWindow(this);
17415            }
17416        }
17417
17418        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17419            mAttachInfo.mScrollContainers.remove(this);
17420            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17421        }
17422
17423        mAttachInfo = null;
17424        if (mOverlay != null) {
17425            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17426        }
17427
17428        notifyEnterOrExitForAutoFillIfNeeded(false);
17429    }
17430
17431    /**
17432     * Cancel any deferred high-level input events that were previously posted to the event queue.
17433     *
17434     * <p>Many views post high-level events such as click handlers to the event queue
17435     * to run deferred in order to preserve a desired user experience - clearing visible
17436     * pressed states before executing, etc. This method will abort any events of this nature
17437     * that are currently in flight.</p>
17438     *
17439     * <p>Custom views that generate their own high-level deferred input events should override
17440     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17441     *
17442     * <p>This will also cancel pending input events for any child views.</p>
17443     *
17444     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17445     * This will not impact newer events posted after this call that may occur as a result of
17446     * lower-level input events still waiting in the queue. If you are trying to prevent
17447     * double-submitted  events for the duration of some sort of asynchronous transaction
17448     * you should also take other steps to protect against unexpected double inputs e.g. calling
17449     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17450     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17451     */
17452    public final void cancelPendingInputEvents() {
17453        dispatchCancelPendingInputEvents();
17454    }
17455
17456    /**
17457     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17458     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17459     */
17460    void dispatchCancelPendingInputEvents() {
17461        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17462        onCancelPendingInputEvents();
17463        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17464            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17465                    " did not call through to super.onCancelPendingInputEvents()");
17466        }
17467    }
17468
17469    /**
17470     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17471     * a parent view.
17472     *
17473     * <p>This method is responsible for removing any pending high-level input events that were
17474     * posted to the event queue to run later. Custom view classes that post their own deferred
17475     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17476     * {@link android.os.Handler} should override this method, call
17477     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17478     * </p>
17479     */
17480    public void onCancelPendingInputEvents() {
17481        removePerformClickCallback();
17482        cancelLongPress();
17483        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17484    }
17485
17486    /**
17487     * Store this view hierarchy's frozen state into the given container.
17488     *
17489     * @param container The SparseArray in which to save the view's state.
17490     *
17491     * @see #restoreHierarchyState(android.util.SparseArray)
17492     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17493     * @see #onSaveInstanceState()
17494     */
17495    public void saveHierarchyState(SparseArray<Parcelable> container) {
17496        dispatchSaveInstanceState(container);
17497    }
17498
17499    /**
17500     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17501     * this view and its children. May be overridden to modify how freezing happens to a
17502     * view's children; for example, some views may want to not store state for their children.
17503     *
17504     * @param container The SparseArray in which to save the view's state.
17505     *
17506     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17507     * @see #saveHierarchyState(android.util.SparseArray)
17508     * @see #onSaveInstanceState()
17509     */
17510    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17511        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17512            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17513            Parcelable state = onSaveInstanceState();
17514            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17515                throw new IllegalStateException(
17516                        "Derived class did not call super.onSaveInstanceState()");
17517            }
17518            if (state != null) {
17519                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17520                // + ": " + state);
17521                container.put(mID, state);
17522            }
17523        }
17524    }
17525
17526    /**
17527     * Hook allowing a view to generate a representation of its internal state
17528     * that can later be used to create a new instance with that same state.
17529     * This state should only contain information that is not persistent or can
17530     * not be reconstructed later. For example, you will never store your
17531     * current position on screen because that will be computed again when a
17532     * new instance of the view is placed in its view hierarchy.
17533     * <p>
17534     * Some examples of things you may store here: the current cursor position
17535     * in a text view (but usually not the text itself since that is stored in a
17536     * content provider or other persistent storage), the currently selected
17537     * item in a list view.
17538     *
17539     * @return Returns a Parcelable object containing the view's current dynamic
17540     *         state, or null if there is nothing interesting to save.
17541     * @see #onRestoreInstanceState(android.os.Parcelable)
17542     * @see #saveHierarchyState(android.util.SparseArray)
17543     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17544     * @see #setSaveEnabled(boolean)
17545     */
17546    @CallSuper
17547    @Nullable protected Parcelable onSaveInstanceState() {
17548        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17549        if (mStartActivityRequestWho != null || isAutofilled()
17550                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17551            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17552
17553            if (mStartActivityRequestWho != null) {
17554                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17555            }
17556
17557            if (isAutofilled()) {
17558                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17559            }
17560
17561            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17562                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17563            }
17564
17565            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17566            state.mIsAutofilled = isAutofilled();
17567            state.mAccessibilityViewId = mAccessibilityViewId;
17568            return state;
17569        }
17570        return BaseSavedState.EMPTY_STATE;
17571    }
17572
17573    /**
17574     * Restore this view hierarchy's frozen state from the given container.
17575     *
17576     * @param container The SparseArray which holds previously frozen states.
17577     *
17578     * @see #saveHierarchyState(android.util.SparseArray)
17579     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17580     * @see #onRestoreInstanceState(android.os.Parcelable)
17581     */
17582    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17583        dispatchRestoreInstanceState(container);
17584    }
17585
17586    /**
17587     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17588     * state for this view and its children. May be overridden to modify how restoring
17589     * happens to a view's children; for example, some views may want to not store state
17590     * for their children.
17591     *
17592     * @param container The SparseArray which holds previously saved state.
17593     *
17594     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17595     * @see #restoreHierarchyState(android.util.SparseArray)
17596     * @see #onRestoreInstanceState(android.os.Parcelable)
17597     */
17598    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17599        if (mID != NO_ID) {
17600            Parcelable state = container.get(mID);
17601            if (state != null) {
17602                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17603                // + ": " + state);
17604                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17605                onRestoreInstanceState(state);
17606                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17607                    throw new IllegalStateException(
17608                            "Derived class did not call super.onRestoreInstanceState()");
17609                }
17610            }
17611        }
17612    }
17613
17614    /**
17615     * Hook allowing a view to re-apply a representation of its internal state that had previously
17616     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17617     * null state.
17618     *
17619     * @param state The frozen state that had previously been returned by
17620     *        {@link #onSaveInstanceState}.
17621     *
17622     * @see #onSaveInstanceState()
17623     * @see #restoreHierarchyState(android.util.SparseArray)
17624     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17625     */
17626    @CallSuper
17627    protected void onRestoreInstanceState(Parcelable state) {
17628        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17629        if (state != null && !(state instanceof AbsSavedState)) {
17630            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17631                    + "received " + state.getClass().toString() + " instead. This usually happens "
17632                    + "when two views of different type have the same id in the same hierarchy. "
17633                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17634                    + "other views do not use the same id.");
17635        }
17636        if (state != null && state instanceof BaseSavedState) {
17637            BaseSavedState baseState = (BaseSavedState) state;
17638
17639            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17640                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17641            }
17642            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17643                setAutofilled(baseState.mIsAutofilled);
17644            }
17645            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17646                mAccessibilityViewId = baseState.mAccessibilityViewId;
17647            }
17648        }
17649    }
17650
17651    /**
17652     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17653     *
17654     * @return the drawing start time in milliseconds
17655     */
17656    public long getDrawingTime() {
17657        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17658    }
17659
17660    /**
17661     * <p>Enables or disables the duplication of the parent's state into this view. When
17662     * duplication is enabled, this view gets its drawable state from its parent rather
17663     * than from its own internal properties.</p>
17664     *
17665     * <p>Note: in the current implementation, setting this property to true after the
17666     * view was added to a ViewGroup might have no effect at all. This property should
17667     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17668     *
17669     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17670     * property is enabled, an exception will be thrown.</p>
17671     *
17672     * <p>Note: if the child view uses and updates additional states which are unknown to the
17673     * parent, these states should not be affected by this method.</p>
17674     *
17675     * @param enabled True to enable duplication of the parent's drawable state, false
17676     *                to disable it.
17677     *
17678     * @see #getDrawableState()
17679     * @see #isDuplicateParentStateEnabled()
17680     */
17681    public void setDuplicateParentStateEnabled(boolean enabled) {
17682        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17683    }
17684
17685    /**
17686     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17687     *
17688     * @return True if this view's drawable state is duplicated from the parent,
17689     *         false otherwise
17690     *
17691     * @see #getDrawableState()
17692     * @see #setDuplicateParentStateEnabled(boolean)
17693     */
17694    public boolean isDuplicateParentStateEnabled() {
17695        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17696    }
17697
17698    /**
17699     * <p>Specifies the type of layer backing this view. The layer can be
17700     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17701     * {@link #LAYER_TYPE_HARDWARE}.</p>
17702     *
17703     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17704     * instance that controls how the layer is composed on screen. The following
17705     * properties of the paint are taken into account when composing the layer:</p>
17706     * <ul>
17707     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17708     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17709     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17710     * </ul>
17711     *
17712     * <p>If this view has an alpha value set to < 1.0 by calling
17713     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17714     * by this view's alpha value.</p>
17715     *
17716     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17717     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17718     * for more information on when and how to use layers.</p>
17719     *
17720     * @param layerType The type of layer to use with this view, must be one of
17721     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17722     *        {@link #LAYER_TYPE_HARDWARE}
17723     * @param paint The paint used to compose the layer. This argument is optional
17724     *        and can be null. It is ignored when the layer type is
17725     *        {@link #LAYER_TYPE_NONE}
17726     *
17727     * @see #getLayerType()
17728     * @see #LAYER_TYPE_NONE
17729     * @see #LAYER_TYPE_SOFTWARE
17730     * @see #LAYER_TYPE_HARDWARE
17731     * @see #setAlpha(float)
17732     *
17733     * @attr ref android.R.styleable#View_layerType
17734     */
17735    public void setLayerType(int layerType, @Nullable Paint paint) {
17736        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17737            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17738                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17739        }
17740
17741        boolean typeChanged = mRenderNode.setLayerType(layerType);
17742
17743        if (!typeChanged) {
17744            setLayerPaint(paint);
17745            return;
17746        }
17747
17748        if (layerType != LAYER_TYPE_SOFTWARE) {
17749            // Destroy any previous software drawing cache if present
17750            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17751            // drawing cache created in View#draw when drawing to a SW canvas.
17752            destroyDrawingCache();
17753        }
17754
17755        mLayerType = layerType;
17756        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17757        mRenderNode.setLayerPaint(mLayerPaint);
17758
17759        // draw() behaves differently if we are on a layer, so we need to
17760        // invalidate() here
17761        invalidateParentCaches();
17762        invalidate(true);
17763    }
17764
17765    /**
17766     * Updates the {@link Paint} object used with the current layer (used only if the current
17767     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17768     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17769     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17770     * ensure that the view gets redrawn immediately.
17771     *
17772     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17773     * instance that controls how the layer is composed on screen. The following
17774     * properties of the paint are taken into account when composing the layer:</p>
17775     * <ul>
17776     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17777     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17778     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17779     * </ul>
17780     *
17781     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17782     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17783     *
17784     * @param paint The paint used to compose the layer. This argument is optional
17785     *        and can be null. It is ignored when the layer type is
17786     *        {@link #LAYER_TYPE_NONE}
17787     *
17788     * @see #setLayerType(int, android.graphics.Paint)
17789     */
17790    public void setLayerPaint(@Nullable Paint paint) {
17791        int layerType = getLayerType();
17792        if (layerType != LAYER_TYPE_NONE) {
17793            mLayerPaint = paint;
17794            if (layerType == LAYER_TYPE_HARDWARE) {
17795                if (mRenderNode.setLayerPaint(paint)) {
17796                    invalidateViewProperty(false, false);
17797                }
17798            } else {
17799                invalidate();
17800            }
17801        }
17802    }
17803
17804    /**
17805     * Indicates what type of layer is currently associated with this view. By default
17806     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17807     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17808     * for more information on the different types of layers.
17809     *
17810     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17811     *         {@link #LAYER_TYPE_HARDWARE}
17812     *
17813     * @see #setLayerType(int, android.graphics.Paint)
17814     * @see #buildLayer()
17815     * @see #LAYER_TYPE_NONE
17816     * @see #LAYER_TYPE_SOFTWARE
17817     * @see #LAYER_TYPE_HARDWARE
17818     */
17819    public int getLayerType() {
17820        return mLayerType;
17821    }
17822
17823    /**
17824     * Forces this view's layer to be created and this view to be rendered
17825     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17826     * invoking this method will have no effect.
17827     *
17828     * This method can for instance be used to render a view into its layer before
17829     * starting an animation. If this view is complex, rendering into the layer
17830     * before starting the animation will avoid skipping frames.
17831     *
17832     * @throws IllegalStateException If this view is not attached to a window
17833     *
17834     * @see #setLayerType(int, android.graphics.Paint)
17835     */
17836    public void buildLayer() {
17837        if (mLayerType == LAYER_TYPE_NONE) return;
17838
17839        final AttachInfo attachInfo = mAttachInfo;
17840        if (attachInfo == null) {
17841            throw new IllegalStateException("This view must be attached to a window first");
17842        }
17843
17844        if (getWidth() == 0 || getHeight() == 0) {
17845            return;
17846        }
17847
17848        switch (mLayerType) {
17849            case LAYER_TYPE_HARDWARE:
17850                updateDisplayListIfDirty();
17851                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17852                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17853                }
17854                break;
17855            case LAYER_TYPE_SOFTWARE:
17856                buildDrawingCache(true);
17857                break;
17858        }
17859    }
17860
17861    /**
17862     * Destroys all hardware rendering resources. This method is invoked
17863     * when the system needs to reclaim resources. Upon execution of this
17864     * method, you should free any OpenGL resources created by the view.
17865     *
17866     * Note: you <strong>must</strong> call
17867     * <code>super.destroyHardwareResources()</code> when overriding
17868     * this method.
17869     *
17870     * @hide
17871     */
17872    @CallSuper
17873    protected void destroyHardwareResources() {
17874        if (mOverlay != null) {
17875            mOverlay.getOverlayView().destroyHardwareResources();
17876        }
17877        if (mGhostView != null) {
17878            mGhostView.destroyHardwareResources();
17879        }
17880    }
17881
17882    /**
17883     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17884     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17885     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17886     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17887     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17888     * null.</p>
17889     *
17890     * <p>Enabling the drawing cache is similar to
17891     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17892     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17893     * drawing cache has no effect on rendering because the system uses a different mechanism
17894     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17895     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17896     * for information on how to enable software and hardware layers.</p>
17897     *
17898     * <p>This API can be used to manually generate
17899     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17900     * {@link #getDrawingCache()}.</p>
17901     *
17902     * @param enabled true to enable the drawing cache, false otherwise
17903     *
17904     * @see #isDrawingCacheEnabled()
17905     * @see #getDrawingCache()
17906     * @see #buildDrawingCache()
17907     * @see #setLayerType(int, android.graphics.Paint)
17908     */
17909    public void setDrawingCacheEnabled(boolean enabled) {
17910        mCachingFailed = false;
17911        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17912    }
17913
17914    /**
17915     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17916     *
17917     * @return true if the drawing cache is enabled
17918     *
17919     * @see #setDrawingCacheEnabled(boolean)
17920     * @see #getDrawingCache()
17921     */
17922    @ViewDebug.ExportedProperty(category = "drawing")
17923    public boolean isDrawingCacheEnabled() {
17924        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17925    }
17926
17927    /**
17928     * Debugging utility which recursively outputs the dirty state of a view and its
17929     * descendants.
17930     *
17931     * @hide
17932     */
17933    @SuppressWarnings({"UnusedDeclaration"})
17934    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17935        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17936                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17937                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17938                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17939        if (clear) {
17940            mPrivateFlags &= clearMask;
17941        }
17942        if (this instanceof ViewGroup) {
17943            ViewGroup parent = (ViewGroup) this;
17944            final int count = parent.getChildCount();
17945            for (int i = 0; i < count; i++) {
17946                final View child = parent.getChildAt(i);
17947                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17948            }
17949        }
17950    }
17951
17952    /**
17953     * This method is used by ViewGroup to cause its children to restore or recreate their
17954     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17955     * to recreate its own display list, which would happen if it went through the normal
17956     * draw/dispatchDraw mechanisms.
17957     *
17958     * @hide
17959     */
17960    protected void dispatchGetDisplayList() {}
17961
17962    /**
17963     * A view that is not attached or hardware accelerated cannot create a display list.
17964     * This method checks these conditions and returns the appropriate result.
17965     *
17966     * @return true if view has the ability to create a display list, false otherwise.
17967     *
17968     * @hide
17969     */
17970    public boolean canHaveDisplayList() {
17971        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17972    }
17973
17974    /**
17975     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17976     * @hide
17977     */
17978    @NonNull
17979    public RenderNode updateDisplayListIfDirty() {
17980        final RenderNode renderNode = mRenderNode;
17981        if (!canHaveDisplayList()) {
17982            // can't populate RenderNode, don't try
17983            return renderNode;
17984        }
17985
17986        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17987                || !renderNode.isValid()
17988                || (mRecreateDisplayList)) {
17989            // Don't need to recreate the display list, just need to tell our
17990            // children to restore/recreate theirs
17991            if (renderNode.isValid()
17992                    && !mRecreateDisplayList) {
17993                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17994                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17995                dispatchGetDisplayList();
17996
17997                return renderNode; // no work needed
17998            }
17999
18000            // If we got here, we're recreating it. Mark it as such to ensure that
18001            // we copy in child display lists into ours in drawChild()
18002            mRecreateDisplayList = true;
18003
18004            int width = mRight - mLeft;
18005            int height = mBottom - mTop;
18006            int layerType = getLayerType();
18007
18008            final DisplayListCanvas canvas = renderNode.start(width, height);
18009            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
18010
18011            try {
18012                if (layerType == LAYER_TYPE_SOFTWARE) {
18013                    buildDrawingCache(true);
18014                    Bitmap cache = getDrawingCache(true);
18015                    if (cache != null) {
18016                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
18017                    }
18018                } else {
18019                    computeScroll();
18020
18021                    canvas.translate(-mScrollX, -mScrollY);
18022                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18023                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18024
18025                    // Fast path for layouts with no backgrounds
18026                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18027                        dispatchDraw(canvas);
18028                        drawAutofilledHighlight(canvas);
18029                        if (mOverlay != null && !mOverlay.isEmpty()) {
18030                            mOverlay.getOverlayView().draw(canvas);
18031                        }
18032                        if (debugDraw()) {
18033                            debugDrawFocus(canvas);
18034                        }
18035                    } else {
18036                        draw(canvas);
18037                    }
18038                }
18039            } finally {
18040                renderNode.end(canvas);
18041                setDisplayListProperties(renderNode);
18042            }
18043        } else {
18044            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18045            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18046        }
18047        return renderNode;
18048    }
18049
18050    private void resetDisplayList() {
18051        mRenderNode.discardDisplayList();
18052        if (mBackgroundRenderNode != null) {
18053            mBackgroundRenderNode.discardDisplayList();
18054        }
18055    }
18056
18057    /**
18058     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
18059     *
18060     * @return A non-scaled bitmap representing this view or null if cache is disabled.
18061     *
18062     * @see #getDrawingCache(boolean)
18063     */
18064    public Bitmap getDrawingCache() {
18065        return getDrawingCache(false);
18066    }
18067
18068    /**
18069     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
18070     * is null when caching is disabled. If caching is enabled and the cache is not ready,
18071     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
18072     * draw from the cache when the cache is enabled. To benefit from the cache, you must
18073     * request the drawing cache by calling this method and draw it on screen if the
18074     * returned bitmap is not null.</p>
18075     *
18076     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18077     * this method will create a bitmap of the same size as this view. Because this bitmap
18078     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18079     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18080     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18081     * size than the view. This implies that your application must be able to handle this
18082     * size.</p>
18083     *
18084     * @param autoScale Indicates whether the generated bitmap should be scaled based on
18085     *        the current density of the screen when the application is in compatibility
18086     *        mode.
18087     *
18088     * @return A bitmap representing this view or null if cache is disabled.
18089     *
18090     * @see #setDrawingCacheEnabled(boolean)
18091     * @see #isDrawingCacheEnabled()
18092     * @see #buildDrawingCache(boolean)
18093     * @see #destroyDrawingCache()
18094     */
18095    public Bitmap getDrawingCache(boolean autoScale) {
18096        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
18097            return null;
18098        }
18099        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
18100            buildDrawingCache(autoScale);
18101        }
18102        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
18103    }
18104
18105    /**
18106     * <p>Frees the resources used by the drawing cache. If you call
18107     * {@link #buildDrawingCache()} manually without calling
18108     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18109     * should cleanup the cache with this method afterwards.</p>
18110     *
18111     * @see #setDrawingCacheEnabled(boolean)
18112     * @see #buildDrawingCache()
18113     * @see #getDrawingCache()
18114     */
18115    public void destroyDrawingCache() {
18116        if (mDrawingCache != null) {
18117            mDrawingCache.recycle();
18118            mDrawingCache = null;
18119        }
18120        if (mUnscaledDrawingCache != null) {
18121            mUnscaledDrawingCache.recycle();
18122            mUnscaledDrawingCache = null;
18123        }
18124    }
18125
18126    /**
18127     * Setting a solid background color for the drawing cache's bitmaps will improve
18128     * performance and memory usage. Note, though that this should only be used if this
18129     * view will always be drawn on top of a solid color.
18130     *
18131     * @param color The background color to use for the drawing cache's bitmap
18132     *
18133     * @see #setDrawingCacheEnabled(boolean)
18134     * @see #buildDrawingCache()
18135     * @see #getDrawingCache()
18136     */
18137    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
18138        if (color != mDrawingCacheBackgroundColor) {
18139            mDrawingCacheBackgroundColor = color;
18140            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18141        }
18142    }
18143
18144    /**
18145     * @see #setDrawingCacheBackgroundColor(int)
18146     *
18147     * @return The background color to used for the drawing cache's bitmap
18148     */
18149    @ColorInt
18150    public int getDrawingCacheBackgroundColor() {
18151        return mDrawingCacheBackgroundColor;
18152    }
18153
18154    /**
18155     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
18156     *
18157     * @see #buildDrawingCache(boolean)
18158     */
18159    public void buildDrawingCache() {
18160        buildDrawingCache(false);
18161    }
18162
18163    /**
18164     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
18165     *
18166     * <p>If you call {@link #buildDrawingCache()} manually without calling
18167     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18168     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
18169     *
18170     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18171     * this method will create a bitmap of the same size as this view. Because this bitmap
18172     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18173     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18174     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18175     * size than the view. This implies that your application must be able to handle this
18176     * size.</p>
18177     *
18178     * <p>You should avoid calling this method when hardware acceleration is enabled. If
18179     * you do not need the drawing cache bitmap, calling this method will increase memory
18180     * usage and cause the view to be rendered in software once, thus negatively impacting
18181     * performance.</p>
18182     *
18183     * @see #getDrawingCache()
18184     * @see #destroyDrawingCache()
18185     */
18186    public void buildDrawingCache(boolean autoScale) {
18187        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
18188                mDrawingCache == null : mUnscaledDrawingCache == null)) {
18189            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
18190                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
18191                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
18192            }
18193            try {
18194                buildDrawingCacheImpl(autoScale);
18195            } finally {
18196                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
18197            }
18198        }
18199    }
18200
18201    /**
18202     * private, internal implementation of buildDrawingCache, used to enable tracing
18203     */
18204    private void buildDrawingCacheImpl(boolean autoScale) {
18205        mCachingFailed = false;
18206
18207        int width = mRight - mLeft;
18208        int height = mBottom - mTop;
18209
18210        final AttachInfo attachInfo = mAttachInfo;
18211        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
18212
18213        if (autoScale && scalingRequired) {
18214            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
18215            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
18216        }
18217
18218        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
18219        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
18220        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
18221
18222        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
18223        final long drawingCacheSize =
18224                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
18225        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
18226            if (width > 0 && height > 0) {
18227                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
18228                        + " too large to fit into a software layer (or drawing cache), needs "
18229                        + projectedBitmapSize + " bytes, only "
18230                        + drawingCacheSize + " available");
18231            }
18232            destroyDrawingCache();
18233            mCachingFailed = true;
18234            return;
18235        }
18236
18237        boolean clear = true;
18238        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
18239
18240        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
18241            Bitmap.Config quality;
18242            if (!opaque) {
18243                // Never pick ARGB_4444 because it looks awful
18244                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
18245                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
18246                    case DRAWING_CACHE_QUALITY_AUTO:
18247                    case DRAWING_CACHE_QUALITY_LOW:
18248                    case DRAWING_CACHE_QUALITY_HIGH:
18249                    default:
18250                        quality = Bitmap.Config.ARGB_8888;
18251                        break;
18252                }
18253            } else {
18254                // Optimization for translucent windows
18255                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
18256                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
18257            }
18258
18259            // Try to cleanup memory
18260            if (bitmap != null) bitmap.recycle();
18261
18262            try {
18263                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18264                        width, height, quality);
18265                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
18266                if (autoScale) {
18267                    mDrawingCache = bitmap;
18268                } else {
18269                    mUnscaledDrawingCache = bitmap;
18270                }
18271                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
18272            } catch (OutOfMemoryError e) {
18273                // If there is not enough memory to create the bitmap cache, just
18274                // ignore the issue as bitmap caches are not required to draw the
18275                // view hierarchy
18276                if (autoScale) {
18277                    mDrawingCache = null;
18278                } else {
18279                    mUnscaledDrawingCache = null;
18280                }
18281                mCachingFailed = true;
18282                return;
18283            }
18284
18285            clear = drawingCacheBackgroundColor != 0;
18286        }
18287
18288        Canvas canvas;
18289        if (attachInfo != null) {
18290            canvas = attachInfo.mCanvas;
18291            if (canvas == null) {
18292                canvas = new Canvas();
18293            }
18294            canvas.setBitmap(bitmap);
18295            // Temporarily clobber the cached Canvas in case one of our children
18296            // is also using a drawing cache. Without this, the children would
18297            // steal the canvas by attaching their own bitmap to it and bad, bad
18298            // thing would happen (invisible views, corrupted drawings, etc.)
18299            attachInfo.mCanvas = null;
18300        } else {
18301            // This case should hopefully never or seldom happen
18302            canvas = new Canvas(bitmap);
18303        }
18304
18305        if (clear) {
18306            bitmap.eraseColor(drawingCacheBackgroundColor);
18307        }
18308
18309        computeScroll();
18310        final int restoreCount = canvas.save();
18311
18312        if (autoScale && scalingRequired) {
18313            final float scale = attachInfo.mApplicationScale;
18314            canvas.scale(scale, scale);
18315        }
18316
18317        canvas.translate(-mScrollX, -mScrollY);
18318
18319        mPrivateFlags |= PFLAG_DRAWN;
18320        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18321                mLayerType != LAYER_TYPE_NONE) {
18322            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18323        }
18324
18325        // Fast path for layouts with no backgrounds
18326        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18327            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18328            dispatchDraw(canvas);
18329            drawAutofilledHighlight(canvas);
18330            if (mOverlay != null && !mOverlay.isEmpty()) {
18331                mOverlay.getOverlayView().draw(canvas);
18332            }
18333        } else {
18334            draw(canvas);
18335        }
18336
18337        canvas.restoreToCount(restoreCount);
18338        canvas.setBitmap(null);
18339
18340        if (attachInfo != null) {
18341            // Restore the cached Canvas for our siblings
18342            attachInfo.mCanvas = canvas;
18343        }
18344    }
18345
18346    /**
18347     * Create a snapshot of the view into a bitmap.  We should probably make
18348     * some form of this public, but should think about the API.
18349     *
18350     * @hide
18351     */
18352    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18353        int width = mRight - mLeft;
18354        int height = mBottom - mTop;
18355
18356        final AttachInfo attachInfo = mAttachInfo;
18357        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18358        width = (int) ((width * scale) + 0.5f);
18359        height = (int) ((height * scale) + 0.5f);
18360
18361        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18362                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18363        if (bitmap == null) {
18364            throw new OutOfMemoryError();
18365        }
18366
18367        Resources resources = getResources();
18368        if (resources != null) {
18369            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18370        }
18371
18372        Canvas canvas;
18373        if (attachInfo != null) {
18374            canvas = attachInfo.mCanvas;
18375            if (canvas == null) {
18376                canvas = new Canvas();
18377            }
18378            canvas.setBitmap(bitmap);
18379            // Temporarily clobber the cached Canvas in case one of our children
18380            // is also using a drawing cache. Without this, the children would
18381            // steal the canvas by attaching their own bitmap to it and bad, bad
18382            // things would happen (invisible views, corrupted drawings, etc.)
18383            attachInfo.mCanvas = null;
18384        } else {
18385            // This case should hopefully never or seldom happen
18386            canvas = new Canvas(bitmap);
18387        }
18388        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18389        canvas.setHwBitmapsInSwModeEnabled(true);
18390        if ((backgroundColor & 0xff000000) != 0) {
18391            bitmap.eraseColor(backgroundColor);
18392        }
18393
18394        computeScroll();
18395        final int restoreCount = canvas.save();
18396        canvas.scale(scale, scale);
18397        canvas.translate(-mScrollX, -mScrollY);
18398
18399        // Temporarily remove the dirty mask
18400        int flags = mPrivateFlags;
18401        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18402
18403        // Fast path for layouts with no backgrounds
18404        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18405            dispatchDraw(canvas);
18406            drawAutofilledHighlight(canvas);
18407            if (mOverlay != null && !mOverlay.isEmpty()) {
18408                mOverlay.getOverlayView().draw(canvas);
18409            }
18410        } else {
18411            draw(canvas);
18412        }
18413
18414        mPrivateFlags = flags;
18415
18416        canvas.restoreToCount(restoreCount);
18417        canvas.setBitmap(null);
18418        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18419
18420        if (attachInfo != null) {
18421            // Restore the cached Canvas for our siblings
18422            attachInfo.mCanvas = canvas;
18423        }
18424
18425        return bitmap;
18426    }
18427
18428    /**
18429     * Indicates whether this View is currently in edit mode. A View is usually
18430     * in edit mode when displayed within a developer tool. For instance, if
18431     * this View is being drawn by a visual user interface builder, this method
18432     * should return true.
18433     *
18434     * Subclasses should check the return value of this method to provide
18435     * different behaviors if their normal behavior might interfere with the
18436     * host environment. For instance: the class spawns a thread in its
18437     * constructor, the drawing code relies on device-specific features, etc.
18438     *
18439     * This method is usually checked in the drawing code of custom widgets.
18440     *
18441     * @return True if this View is in edit mode, false otherwise.
18442     */
18443    public boolean isInEditMode() {
18444        return false;
18445    }
18446
18447    /**
18448     * If the View draws content inside its padding and enables fading edges,
18449     * it needs to support padding offsets. Padding offsets are added to the
18450     * fading edges to extend the length of the fade so that it covers pixels
18451     * drawn inside the padding.
18452     *
18453     * Subclasses of this class should override this method if they need
18454     * to draw content inside the padding.
18455     *
18456     * @return True if padding offset must be applied, false otherwise.
18457     *
18458     * @see #getLeftPaddingOffset()
18459     * @see #getRightPaddingOffset()
18460     * @see #getTopPaddingOffset()
18461     * @see #getBottomPaddingOffset()
18462     *
18463     * @since CURRENT
18464     */
18465    protected boolean isPaddingOffsetRequired() {
18466        return false;
18467    }
18468
18469    /**
18470     * Amount by which to extend the left fading region. Called only when
18471     * {@link #isPaddingOffsetRequired()} returns true.
18472     *
18473     * @return The left padding offset in pixels.
18474     *
18475     * @see #isPaddingOffsetRequired()
18476     *
18477     * @since CURRENT
18478     */
18479    protected int getLeftPaddingOffset() {
18480        return 0;
18481    }
18482
18483    /**
18484     * Amount by which to extend the right fading region. Called only when
18485     * {@link #isPaddingOffsetRequired()} returns true.
18486     *
18487     * @return The right padding offset in pixels.
18488     *
18489     * @see #isPaddingOffsetRequired()
18490     *
18491     * @since CURRENT
18492     */
18493    protected int getRightPaddingOffset() {
18494        return 0;
18495    }
18496
18497    /**
18498     * Amount by which to extend the top fading region. Called only when
18499     * {@link #isPaddingOffsetRequired()} returns true.
18500     *
18501     * @return The top padding offset in pixels.
18502     *
18503     * @see #isPaddingOffsetRequired()
18504     *
18505     * @since CURRENT
18506     */
18507    protected int getTopPaddingOffset() {
18508        return 0;
18509    }
18510
18511    /**
18512     * Amount by which to extend the bottom fading region. Called only when
18513     * {@link #isPaddingOffsetRequired()} returns true.
18514     *
18515     * @return The bottom padding offset in pixels.
18516     *
18517     * @see #isPaddingOffsetRequired()
18518     *
18519     * @since CURRENT
18520     */
18521    protected int getBottomPaddingOffset() {
18522        return 0;
18523    }
18524
18525    /**
18526     * @hide
18527     * @param offsetRequired
18528     */
18529    protected int getFadeTop(boolean offsetRequired) {
18530        int top = mPaddingTop;
18531        if (offsetRequired) top += getTopPaddingOffset();
18532        return top;
18533    }
18534
18535    /**
18536     * @hide
18537     * @param offsetRequired
18538     */
18539    protected int getFadeHeight(boolean offsetRequired) {
18540        int padding = mPaddingTop;
18541        if (offsetRequired) padding += getTopPaddingOffset();
18542        return mBottom - mTop - mPaddingBottom - padding;
18543    }
18544
18545    /**
18546     * <p>Indicates whether this view is attached to a hardware accelerated
18547     * window or not.</p>
18548     *
18549     * <p>Even if this method returns true, it does not mean that every call
18550     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18551     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18552     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18553     * window is hardware accelerated,
18554     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18555     * return false, and this method will return true.</p>
18556     *
18557     * @return True if the view is attached to a window and the window is
18558     *         hardware accelerated; false in any other case.
18559     */
18560    @ViewDebug.ExportedProperty(category = "drawing")
18561    public boolean isHardwareAccelerated() {
18562        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18563    }
18564
18565    /**
18566     * Sets a rectangular area on this view to which the view will be clipped
18567     * when it is drawn. Setting the value to null will remove the clip bounds
18568     * and the view will draw normally, using its full bounds.
18569     *
18570     * @param clipBounds The rectangular area, in the local coordinates of
18571     * this view, to which future drawing operations will be clipped.
18572     */
18573    public void setClipBounds(Rect clipBounds) {
18574        if (clipBounds == mClipBounds
18575                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18576            return;
18577        }
18578        if (clipBounds != null) {
18579            if (mClipBounds == null) {
18580                mClipBounds = new Rect(clipBounds);
18581            } else {
18582                mClipBounds.set(clipBounds);
18583            }
18584        } else {
18585            mClipBounds = null;
18586        }
18587        mRenderNode.setClipBounds(mClipBounds);
18588        invalidateViewProperty(false, false);
18589    }
18590
18591    /**
18592     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18593     *
18594     * @return A copy of the current clip bounds if clip bounds are set,
18595     * otherwise null.
18596     */
18597    public Rect getClipBounds() {
18598        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18599    }
18600
18601
18602    /**
18603     * Populates an output rectangle with the clip bounds of the view,
18604     * returning {@code true} if successful or {@code false} if the view's
18605     * clip bounds are {@code null}.
18606     *
18607     * @param outRect rectangle in which to place the clip bounds of the view
18608     * @return {@code true} if successful or {@code false} if the view's
18609     *         clip bounds are {@code null}
18610     */
18611    public boolean getClipBounds(Rect outRect) {
18612        if (mClipBounds != null) {
18613            outRect.set(mClipBounds);
18614            return true;
18615        }
18616        return false;
18617    }
18618
18619    /**
18620     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18621     * case of an active Animation being run on the view.
18622     */
18623    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18624            Animation a, boolean scalingRequired) {
18625        Transformation invalidationTransform;
18626        final int flags = parent.mGroupFlags;
18627        final boolean initialized = a.isInitialized();
18628        if (!initialized) {
18629            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18630            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18631            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18632            onAnimationStart();
18633        }
18634
18635        final Transformation t = parent.getChildTransformation();
18636        boolean more = a.getTransformation(drawingTime, t, 1f);
18637        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18638            if (parent.mInvalidationTransformation == null) {
18639                parent.mInvalidationTransformation = new Transformation();
18640            }
18641            invalidationTransform = parent.mInvalidationTransformation;
18642            a.getTransformation(drawingTime, invalidationTransform, 1f);
18643        } else {
18644            invalidationTransform = t;
18645        }
18646
18647        if (more) {
18648            if (!a.willChangeBounds()) {
18649                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18650                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18651                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18652                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18653                    // The child need to draw an animation, potentially offscreen, so
18654                    // make sure we do not cancel invalidate requests
18655                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18656                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18657                }
18658            } else {
18659                if (parent.mInvalidateRegion == null) {
18660                    parent.mInvalidateRegion = new RectF();
18661                }
18662                final RectF region = parent.mInvalidateRegion;
18663                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18664                        invalidationTransform);
18665
18666                // The child need to draw an animation, potentially offscreen, so
18667                // make sure we do not cancel invalidate requests
18668                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18669
18670                final int left = mLeft + (int) region.left;
18671                final int top = mTop + (int) region.top;
18672                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18673                        top + (int) (region.height() + .5f));
18674            }
18675        }
18676        return more;
18677    }
18678
18679    /**
18680     * This method is called by getDisplayList() when a display list is recorded for a View.
18681     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18682     */
18683    void setDisplayListProperties(RenderNode renderNode) {
18684        if (renderNode != null) {
18685            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18686            renderNode.setClipToBounds(mParent instanceof ViewGroup
18687                    && ((ViewGroup) mParent).getClipChildren());
18688
18689            float alpha = 1;
18690            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18691                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18692                ViewGroup parentVG = (ViewGroup) mParent;
18693                final Transformation t = parentVG.getChildTransformation();
18694                if (parentVG.getChildStaticTransformation(this, t)) {
18695                    final int transformType = t.getTransformationType();
18696                    if (transformType != Transformation.TYPE_IDENTITY) {
18697                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18698                            alpha = t.getAlpha();
18699                        }
18700                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18701                            renderNode.setStaticMatrix(t.getMatrix());
18702                        }
18703                    }
18704                }
18705            }
18706            if (mTransformationInfo != null) {
18707                alpha *= getFinalAlpha();
18708                if (alpha < 1) {
18709                    final int multipliedAlpha = (int) (255 * alpha);
18710                    if (onSetAlpha(multipliedAlpha)) {
18711                        alpha = 1;
18712                    }
18713                }
18714                renderNode.setAlpha(alpha);
18715            } else if (alpha < 1) {
18716                renderNode.setAlpha(alpha);
18717            }
18718        }
18719    }
18720
18721    /**
18722     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18723     *
18724     * This is where the View specializes rendering behavior based on layer type,
18725     * and hardware acceleration.
18726     */
18727    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18728        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18729        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18730         *
18731         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18732         * HW accelerated, it can't handle drawing RenderNodes.
18733         */
18734        boolean drawingWithRenderNode = mAttachInfo != null
18735                && mAttachInfo.mHardwareAccelerated
18736                && hardwareAcceleratedCanvas;
18737
18738        boolean more = false;
18739        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18740        final int parentFlags = parent.mGroupFlags;
18741
18742        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18743            parent.getChildTransformation().clear();
18744            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18745        }
18746
18747        Transformation transformToApply = null;
18748        boolean concatMatrix = false;
18749        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18750        final Animation a = getAnimation();
18751        if (a != null) {
18752            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18753            concatMatrix = a.willChangeTransformationMatrix();
18754            if (concatMatrix) {
18755                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18756            }
18757            transformToApply = parent.getChildTransformation();
18758        } else {
18759            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18760                // No longer animating: clear out old animation matrix
18761                mRenderNode.setAnimationMatrix(null);
18762                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18763            }
18764            if (!drawingWithRenderNode
18765                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18766                final Transformation t = parent.getChildTransformation();
18767                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18768                if (hasTransform) {
18769                    final int transformType = t.getTransformationType();
18770                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18771                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18772                }
18773            }
18774        }
18775
18776        concatMatrix |= !childHasIdentityMatrix;
18777
18778        // Sets the flag as early as possible to allow draw() implementations
18779        // to call invalidate() successfully when doing animations
18780        mPrivateFlags |= PFLAG_DRAWN;
18781
18782        if (!concatMatrix &&
18783                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18784                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18785                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18786                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18787            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18788            return more;
18789        }
18790        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18791
18792        if (hardwareAcceleratedCanvas) {
18793            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18794            // retain the flag's value temporarily in the mRecreateDisplayList flag
18795            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18796            mPrivateFlags &= ~PFLAG_INVALIDATED;
18797        }
18798
18799        RenderNode renderNode = null;
18800        Bitmap cache = null;
18801        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18802        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18803             if (layerType != LAYER_TYPE_NONE) {
18804                 // If not drawing with RenderNode, treat HW layers as SW
18805                 layerType = LAYER_TYPE_SOFTWARE;
18806                 buildDrawingCache(true);
18807            }
18808            cache = getDrawingCache(true);
18809        }
18810
18811        if (drawingWithRenderNode) {
18812            // Delay getting the display list until animation-driven alpha values are
18813            // set up and possibly passed on to the view
18814            renderNode = updateDisplayListIfDirty();
18815            if (!renderNode.isValid()) {
18816                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18817                // to getDisplayList(), the display list will be marked invalid and we should not
18818                // try to use it again.
18819                renderNode = null;
18820                drawingWithRenderNode = false;
18821            }
18822        }
18823
18824        int sx = 0;
18825        int sy = 0;
18826        if (!drawingWithRenderNode) {
18827            computeScroll();
18828            sx = mScrollX;
18829            sy = mScrollY;
18830        }
18831
18832        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18833        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18834
18835        int restoreTo = -1;
18836        if (!drawingWithRenderNode || transformToApply != null) {
18837            restoreTo = canvas.save();
18838        }
18839        if (offsetForScroll) {
18840            canvas.translate(mLeft - sx, mTop - sy);
18841        } else {
18842            if (!drawingWithRenderNode) {
18843                canvas.translate(mLeft, mTop);
18844            }
18845            if (scalingRequired) {
18846                if (drawingWithRenderNode) {
18847                    // TODO: Might not need this if we put everything inside the DL
18848                    restoreTo = canvas.save();
18849                }
18850                // mAttachInfo cannot be null, otherwise scalingRequired == false
18851                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18852                canvas.scale(scale, scale);
18853            }
18854        }
18855
18856        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18857        if (transformToApply != null
18858                || alpha < 1
18859                || !hasIdentityMatrix()
18860                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18861            if (transformToApply != null || !childHasIdentityMatrix) {
18862                int transX = 0;
18863                int transY = 0;
18864
18865                if (offsetForScroll) {
18866                    transX = -sx;
18867                    transY = -sy;
18868                }
18869
18870                if (transformToApply != null) {
18871                    if (concatMatrix) {
18872                        if (drawingWithRenderNode) {
18873                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18874                        } else {
18875                            // Undo the scroll translation, apply the transformation matrix,
18876                            // then redo the scroll translate to get the correct result.
18877                            canvas.translate(-transX, -transY);
18878                            canvas.concat(transformToApply.getMatrix());
18879                            canvas.translate(transX, transY);
18880                        }
18881                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18882                    }
18883
18884                    float transformAlpha = transformToApply.getAlpha();
18885                    if (transformAlpha < 1) {
18886                        alpha *= transformAlpha;
18887                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18888                    }
18889                }
18890
18891                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18892                    canvas.translate(-transX, -transY);
18893                    canvas.concat(getMatrix());
18894                    canvas.translate(transX, transY);
18895                }
18896            }
18897
18898            // Deal with alpha if it is or used to be <1
18899            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18900                if (alpha < 1) {
18901                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18902                } else {
18903                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18904                }
18905                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18906                if (!drawingWithDrawingCache) {
18907                    final int multipliedAlpha = (int) (255 * alpha);
18908                    if (!onSetAlpha(multipliedAlpha)) {
18909                        if (drawingWithRenderNode) {
18910                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18911                        } else if (layerType == LAYER_TYPE_NONE) {
18912                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18913                                    multipliedAlpha);
18914                        }
18915                    } else {
18916                        // Alpha is handled by the child directly, clobber the layer's alpha
18917                        mPrivateFlags |= PFLAG_ALPHA_SET;
18918                    }
18919                }
18920            }
18921        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18922            onSetAlpha(255);
18923            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18924        }
18925
18926        if (!drawingWithRenderNode) {
18927            // apply clips directly, since RenderNode won't do it for this draw
18928            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18929                if (offsetForScroll) {
18930                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18931                } else {
18932                    if (!scalingRequired || cache == null) {
18933                        canvas.clipRect(0, 0, getWidth(), getHeight());
18934                    } else {
18935                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18936                    }
18937                }
18938            }
18939
18940            if (mClipBounds != null) {
18941                // clip bounds ignore scroll
18942                canvas.clipRect(mClipBounds);
18943            }
18944        }
18945
18946        if (!drawingWithDrawingCache) {
18947            if (drawingWithRenderNode) {
18948                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18949                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18950            } else {
18951                // Fast path for layouts with no backgrounds
18952                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18953                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18954                    dispatchDraw(canvas);
18955                } else {
18956                    draw(canvas);
18957                }
18958            }
18959        } else if (cache != null) {
18960            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18961            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18962                // no layer paint, use temporary paint to draw bitmap
18963                Paint cachePaint = parent.mCachePaint;
18964                if (cachePaint == null) {
18965                    cachePaint = new Paint();
18966                    cachePaint.setDither(false);
18967                    parent.mCachePaint = cachePaint;
18968                }
18969                cachePaint.setAlpha((int) (alpha * 255));
18970                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18971            } else {
18972                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18973                int layerPaintAlpha = mLayerPaint.getAlpha();
18974                if (alpha < 1) {
18975                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18976                }
18977                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18978                if (alpha < 1) {
18979                    mLayerPaint.setAlpha(layerPaintAlpha);
18980                }
18981            }
18982        }
18983
18984        if (restoreTo >= 0) {
18985            canvas.restoreToCount(restoreTo);
18986        }
18987
18988        if (a != null && !more) {
18989            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18990                onSetAlpha(255);
18991            }
18992            parent.finishAnimatingView(this, a);
18993        }
18994
18995        if (more && hardwareAcceleratedCanvas) {
18996            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18997                // alpha animations should cause the child to recreate its display list
18998                invalidate(true);
18999            }
19000        }
19001
19002        mRecreateDisplayList = false;
19003
19004        return more;
19005    }
19006
19007    static Paint getDebugPaint() {
19008        if (sDebugPaint == null) {
19009            sDebugPaint = new Paint();
19010            sDebugPaint.setAntiAlias(false);
19011        }
19012        return sDebugPaint;
19013    }
19014
19015    final int dipsToPixels(int dips) {
19016        float scale = getContext().getResources().getDisplayMetrics().density;
19017        return (int) (dips * scale + 0.5f);
19018    }
19019
19020    final private void debugDrawFocus(Canvas canvas) {
19021        if (isFocused()) {
19022            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
19023            final int l = mScrollX;
19024            final int r = l + mRight - mLeft;
19025            final int t = mScrollY;
19026            final int b = t + mBottom - mTop;
19027
19028            final Paint paint = getDebugPaint();
19029            paint.setColor(DEBUG_CORNERS_COLOR);
19030
19031            // Draw squares in corners.
19032            paint.setStyle(Paint.Style.FILL);
19033            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
19034            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
19035            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
19036            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
19037
19038            // Draw big X across the view.
19039            paint.setStyle(Paint.Style.STROKE);
19040            canvas.drawLine(l, t, r, b, paint);
19041            canvas.drawLine(l, b, r, t, paint);
19042        }
19043    }
19044
19045    /**
19046     * Manually render this view (and all of its children) to the given Canvas.
19047     * The view must have already done a full layout before this function is
19048     * called.  When implementing a view, implement
19049     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
19050     * If you do need to override this method, call the superclass version.
19051     *
19052     * @param canvas The Canvas to which the View is rendered.
19053     */
19054    @CallSuper
19055    public void draw(Canvas canvas) {
19056        final int privateFlags = mPrivateFlags;
19057        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
19058                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
19059        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
19060
19061        /*
19062         * Draw traversal performs several drawing steps which must be executed
19063         * in the appropriate order:
19064         *
19065         *      1. Draw the background
19066         *      2. If necessary, save the canvas' layers to prepare for fading
19067         *      3. Draw view's content
19068         *      4. Draw children
19069         *      5. If necessary, draw the fading edges and restore layers
19070         *      6. Draw decorations (scrollbars for instance)
19071         */
19072
19073        // Step 1, draw the background, if needed
19074        int saveCount;
19075
19076        if (!dirtyOpaque) {
19077            drawBackground(canvas);
19078        }
19079
19080        // skip step 2 & 5 if possible (common case)
19081        final int viewFlags = mViewFlags;
19082        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
19083        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
19084        if (!verticalEdges && !horizontalEdges) {
19085            // Step 3, draw the content
19086            if (!dirtyOpaque) onDraw(canvas);
19087
19088            // Step 4, draw the children
19089            dispatchDraw(canvas);
19090
19091            drawAutofilledHighlight(canvas);
19092
19093            // Overlay is part of the content and draws beneath Foreground
19094            if (mOverlay != null && !mOverlay.isEmpty()) {
19095                mOverlay.getOverlayView().dispatchDraw(canvas);
19096            }
19097
19098            // Step 6, draw decorations (foreground, scrollbars)
19099            onDrawForeground(canvas);
19100
19101            // Step 7, draw the default focus highlight
19102            drawDefaultFocusHighlight(canvas);
19103
19104            if (debugDraw()) {
19105                debugDrawFocus(canvas);
19106            }
19107
19108            // we're done...
19109            return;
19110        }
19111
19112        /*
19113         * Here we do the full fledged routine...
19114         * (this is an uncommon case where speed matters less,
19115         * this is why we repeat some of the tests that have been
19116         * done above)
19117         */
19118
19119        boolean drawTop = false;
19120        boolean drawBottom = false;
19121        boolean drawLeft = false;
19122        boolean drawRight = false;
19123
19124        float topFadeStrength = 0.0f;
19125        float bottomFadeStrength = 0.0f;
19126        float leftFadeStrength = 0.0f;
19127        float rightFadeStrength = 0.0f;
19128
19129        // Step 2, save the canvas' layers
19130        int paddingLeft = mPaddingLeft;
19131
19132        final boolean offsetRequired = isPaddingOffsetRequired();
19133        if (offsetRequired) {
19134            paddingLeft += getLeftPaddingOffset();
19135        }
19136
19137        int left = mScrollX + paddingLeft;
19138        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
19139        int top = mScrollY + getFadeTop(offsetRequired);
19140        int bottom = top + getFadeHeight(offsetRequired);
19141
19142        if (offsetRequired) {
19143            right += getRightPaddingOffset();
19144            bottom += getBottomPaddingOffset();
19145        }
19146
19147        final ScrollabilityCache scrollabilityCache = mScrollCache;
19148        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
19149        int length = (int) fadeHeight;
19150
19151        // clip the fade length if top and bottom fades overlap
19152        // overlapping fades produce odd-looking artifacts
19153        if (verticalEdges && (top + length > bottom - length)) {
19154            length = (bottom - top) / 2;
19155        }
19156
19157        // also clip horizontal fades if necessary
19158        if (horizontalEdges && (left + length > right - length)) {
19159            length = (right - left) / 2;
19160        }
19161
19162        if (verticalEdges) {
19163            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
19164            drawTop = topFadeStrength * fadeHeight > 1.0f;
19165            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
19166            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
19167        }
19168
19169        if (horizontalEdges) {
19170            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
19171            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
19172            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
19173            drawRight = rightFadeStrength * fadeHeight > 1.0f;
19174        }
19175
19176        saveCount = canvas.getSaveCount();
19177
19178        int solidColor = getSolidColor();
19179        if (solidColor == 0) {
19180            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
19181
19182            if (drawTop) {
19183                canvas.saveLayer(left, top, right, top + length, null, flags);
19184            }
19185
19186            if (drawBottom) {
19187                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
19188            }
19189
19190            if (drawLeft) {
19191                canvas.saveLayer(left, top, left + length, bottom, null, flags);
19192            }
19193
19194            if (drawRight) {
19195                canvas.saveLayer(right - length, top, right, bottom, null, flags);
19196            }
19197        } else {
19198            scrollabilityCache.setFadeColor(solidColor);
19199        }
19200
19201        // Step 3, draw the content
19202        if (!dirtyOpaque) onDraw(canvas);
19203
19204        // Step 4, draw the children
19205        dispatchDraw(canvas);
19206
19207        // Step 5, draw the fade effect and restore layers
19208        final Paint p = scrollabilityCache.paint;
19209        final Matrix matrix = scrollabilityCache.matrix;
19210        final Shader fade = scrollabilityCache.shader;
19211
19212        if (drawTop) {
19213            matrix.setScale(1, fadeHeight * topFadeStrength);
19214            matrix.postTranslate(left, top);
19215            fade.setLocalMatrix(matrix);
19216            p.setShader(fade);
19217            canvas.drawRect(left, top, right, top + length, p);
19218        }
19219
19220        if (drawBottom) {
19221            matrix.setScale(1, fadeHeight * bottomFadeStrength);
19222            matrix.postRotate(180);
19223            matrix.postTranslate(left, bottom);
19224            fade.setLocalMatrix(matrix);
19225            p.setShader(fade);
19226            canvas.drawRect(left, bottom - length, right, bottom, p);
19227        }
19228
19229        if (drawLeft) {
19230            matrix.setScale(1, fadeHeight * leftFadeStrength);
19231            matrix.postRotate(-90);
19232            matrix.postTranslate(left, top);
19233            fade.setLocalMatrix(matrix);
19234            p.setShader(fade);
19235            canvas.drawRect(left, top, left + length, bottom, p);
19236        }
19237
19238        if (drawRight) {
19239            matrix.setScale(1, fadeHeight * rightFadeStrength);
19240            matrix.postRotate(90);
19241            matrix.postTranslate(right, top);
19242            fade.setLocalMatrix(matrix);
19243            p.setShader(fade);
19244            canvas.drawRect(right - length, top, right, bottom, p);
19245        }
19246
19247        canvas.restoreToCount(saveCount);
19248
19249        drawAutofilledHighlight(canvas);
19250
19251        // Overlay is part of the content and draws beneath Foreground
19252        if (mOverlay != null && !mOverlay.isEmpty()) {
19253            mOverlay.getOverlayView().dispatchDraw(canvas);
19254        }
19255
19256        // Step 6, draw decorations (foreground, scrollbars)
19257        onDrawForeground(canvas);
19258
19259        if (debugDraw()) {
19260            debugDrawFocus(canvas);
19261        }
19262    }
19263
19264    /**
19265     * Draws the background onto the specified canvas.
19266     *
19267     * @param canvas Canvas on which to draw the background
19268     */
19269    private void drawBackground(Canvas canvas) {
19270        final Drawable background = mBackground;
19271        if (background == null) {
19272            return;
19273        }
19274
19275        setBackgroundBounds();
19276
19277        // Attempt to use a display list if requested.
19278        if (canvas.isHardwareAccelerated() && mAttachInfo != null
19279                && mAttachInfo.mThreadedRenderer != null) {
19280            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
19281
19282            final RenderNode renderNode = mBackgroundRenderNode;
19283            if (renderNode != null && renderNode.isValid()) {
19284                setBackgroundRenderNodeProperties(renderNode);
19285                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19286                return;
19287            }
19288        }
19289
19290        final int scrollX = mScrollX;
19291        final int scrollY = mScrollY;
19292        if ((scrollX | scrollY) == 0) {
19293            background.draw(canvas);
19294        } else {
19295            canvas.translate(scrollX, scrollY);
19296            background.draw(canvas);
19297            canvas.translate(-scrollX, -scrollY);
19298        }
19299    }
19300
19301    /**
19302     * Sets the correct background bounds and rebuilds the outline, if needed.
19303     * <p/>
19304     * This is called by LayoutLib.
19305     */
19306    void setBackgroundBounds() {
19307        if (mBackgroundSizeChanged && mBackground != null) {
19308            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19309            mBackgroundSizeChanged = false;
19310            rebuildOutline();
19311        }
19312    }
19313
19314    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19315        renderNode.setTranslationX(mScrollX);
19316        renderNode.setTranslationY(mScrollY);
19317    }
19318
19319    /**
19320     * Creates a new display list or updates the existing display list for the
19321     * specified Drawable.
19322     *
19323     * @param drawable Drawable for which to create a display list
19324     * @param renderNode Existing RenderNode, or {@code null}
19325     * @return A valid display list for the specified drawable
19326     */
19327    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19328        if (renderNode == null) {
19329            renderNode = RenderNode.create(drawable.getClass().getName(), this);
19330        }
19331
19332        final Rect bounds = drawable.getBounds();
19333        final int width = bounds.width();
19334        final int height = bounds.height();
19335        final DisplayListCanvas canvas = renderNode.start(width, height);
19336
19337        // Reverse left/top translation done by drawable canvas, which will
19338        // instead be applied by rendernode's LTRB bounds below. This way, the
19339        // drawable's bounds match with its rendernode bounds and its content
19340        // will lie within those bounds in the rendernode tree.
19341        canvas.translate(-bounds.left, -bounds.top);
19342
19343        try {
19344            drawable.draw(canvas);
19345        } finally {
19346            renderNode.end(canvas);
19347        }
19348
19349        // Set up drawable properties that are view-independent.
19350        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19351        renderNode.setProjectBackwards(drawable.isProjected());
19352        renderNode.setProjectionReceiver(true);
19353        renderNode.setClipToBounds(false);
19354        return renderNode;
19355    }
19356
19357    /**
19358     * Returns the overlay for this view, creating it if it does not yet exist.
19359     * Adding drawables to the overlay will cause them to be displayed whenever
19360     * the view itself is redrawn. Objects in the overlay should be actively
19361     * managed: remove them when they should not be displayed anymore. The
19362     * overlay will always have the same size as its host view.
19363     *
19364     * <p>Note: Overlays do not currently work correctly with {@link
19365     * SurfaceView} or {@link TextureView}; contents in overlays for these
19366     * types of views may not display correctly.</p>
19367     *
19368     * @return The ViewOverlay object for this view.
19369     * @see ViewOverlay
19370     */
19371    public ViewOverlay getOverlay() {
19372        if (mOverlay == null) {
19373            mOverlay = new ViewOverlay(mContext, this);
19374        }
19375        return mOverlay;
19376    }
19377
19378    /**
19379     * Override this if your view is known to always be drawn on top of a solid color background,
19380     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19381     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19382     * should be set to 0xFF.
19383     *
19384     * @see #setVerticalFadingEdgeEnabled(boolean)
19385     * @see #setHorizontalFadingEdgeEnabled(boolean)
19386     *
19387     * @return The known solid color background for this view, or 0 if the color may vary
19388     */
19389    @ViewDebug.ExportedProperty(category = "drawing")
19390    @ColorInt
19391    public int getSolidColor() {
19392        return 0;
19393    }
19394
19395    /**
19396     * Build a human readable string representation of the specified view flags.
19397     *
19398     * @param flags the view flags to convert to a string
19399     * @return a String representing the supplied flags
19400     */
19401    private static String printFlags(int flags) {
19402        String output = "";
19403        int numFlags = 0;
19404        if ((flags & FOCUSABLE) == FOCUSABLE) {
19405            output += "TAKES_FOCUS";
19406            numFlags++;
19407        }
19408
19409        switch (flags & VISIBILITY_MASK) {
19410        case INVISIBLE:
19411            if (numFlags > 0) {
19412                output += " ";
19413            }
19414            output += "INVISIBLE";
19415            // USELESS HERE numFlags++;
19416            break;
19417        case GONE:
19418            if (numFlags > 0) {
19419                output += " ";
19420            }
19421            output += "GONE";
19422            // USELESS HERE numFlags++;
19423            break;
19424        default:
19425            break;
19426        }
19427        return output;
19428    }
19429
19430    /**
19431     * Build a human readable string representation of the specified private
19432     * view flags.
19433     *
19434     * @param privateFlags the private view flags to convert to a string
19435     * @return a String representing the supplied flags
19436     */
19437    private static String printPrivateFlags(int privateFlags) {
19438        String output = "";
19439        int numFlags = 0;
19440
19441        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19442            output += "WANTS_FOCUS";
19443            numFlags++;
19444        }
19445
19446        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19447            if (numFlags > 0) {
19448                output += " ";
19449            }
19450            output += "FOCUSED";
19451            numFlags++;
19452        }
19453
19454        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19455            if (numFlags > 0) {
19456                output += " ";
19457            }
19458            output += "SELECTED";
19459            numFlags++;
19460        }
19461
19462        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19463            if (numFlags > 0) {
19464                output += " ";
19465            }
19466            output += "IS_ROOT_NAMESPACE";
19467            numFlags++;
19468        }
19469
19470        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19471            if (numFlags > 0) {
19472                output += " ";
19473            }
19474            output += "HAS_BOUNDS";
19475            numFlags++;
19476        }
19477
19478        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19479            if (numFlags > 0) {
19480                output += " ";
19481            }
19482            output += "DRAWN";
19483            // USELESS HERE numFlags++;
19484        }
19485        return output;
19486    }
19487
19488    /**
19489     * <p>Indicates whether or not this view's layout will be requested during
19490     * the next hierarchy layout pass.</p>
19491     *
19492     * @return true if the layout will be forced during next layout pass
19493     */
19494    public boolean isLayoutRequested() {
19495        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19496    }
19497
19498    /**
19499     * Return true if o is a ViewGroup that is laying out using optical bounds.
19500     * @hide
19501     */
19502    public static boolean isLayoutModeOptical(Object o) {
19503        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19504    }
19505
19506    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19507        Insets parentInsets = mParent instanceof View ?
19508                ((View) mParent).getOpticalInsets() : Insets.NONE;
19509        Insets childInsets = getOpticalInsets();
19510        return setFrame(
19511                left   + parentInsets.left - childInsets.left,
19512                top    + parentInsets.top  - childInsets.top,
19513                right  + parentInsets.left + childInsets.right,
19514                bottom + parentInsets.top  + childInsets.bottom);
19515    }
19516
19517    /**
19518     * Assign a size and position to a view and all of its
19519     * descendants
19520     *
19521     * <p>This is the second phase of the layout mechanism.
19522     * (The first is measuring). In this phase, each parent calls
19523     * layout on all of its children to position them.
19524     * This is typically done using the child measurements
19525     * that were stored in the measure pass().</p>
19526     *
19527     * <p>Derived classes should not override this method.
19528     * Derived classes with children should override
19529     * onLayout. In that method, they should
19530     * call layout on each of their children.</p>
19531     *
19532     * @param l Left position, relative to parent
19533     * @param t Top position, relative to parent
19534     * @param r Right position, relative to parent
19535     * @param b Bottom position, relative to parent
19536     */
19537    @SuppressWarnings({"unchecked"})
19538    public void layout(int l, int t, int r, int b) {
19539        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19540            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19541            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19542        }
19543
19544        int oldL = mLeft;
19545        int oldT = mTop;
19546        int oldB = mBottom;
19547        int oldR = mRight;
19548
19549        boolean changed = isLayoutModeOptical(mParent) ?
19550                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19551
19552        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19553            onLayout(changed, l, t, r, b);
19554
19555            if (shouldDrawRoundScrollbar()) {
19556                if(mRoundScrollbarRenderer == null) {
19557                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19558                }
19559            } else {
19560                mRoundScrollbarRenderer = null;
19561            }
19562
19563            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19564
19565            ListenerInfo li = mListenerInfo;
19566            if (li != null && li.mOnLayoutChangeListeners != null) {
19567                ArrayList<OnLayoutChangeListener> listenersCopy =
19568                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19569                int numListeners = listenersCopy.size();
19570                for (int i = 0; i < numListeners; ++i) {
19571                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19572                }
19573            }
19574        }
19575
19576        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19577        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19578
19579        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
19580            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
19581            notifyEnterOrExitForAutoFillIfNeeded(true);
19582        }
19583    }
19584
19585    /**
19586     * Called from layout when this view should
19587     * assign a size and position to each of its children.
19588     *
19589     * Derived classes with children should override
19590     * this method and call layout on each of
19591     * their children.
19592     * @param changed This is a new size or position for this view
19593     * @param left Left position, relative to parent
19594     * @param top Top position, relative to parent
19595     * @param right Right position, relative to parent
19596     * @param bottom Bottom position, relative to parent
19597     */
19598    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19599    }
19600
19601    /**
19602     * Assign a size and position to this view.
19603     *
19604     * This is called from layout.
19605     *
19606     * @param left Left position, relative to parent
19607     * @param top Top position, relative to parent
19608     * @param right Right position, relative to parent
19609     * @param bottom Bottom position, relative to parent
19610     * @return true if the new size and position are different than the
19611     *         previous ones
19612     * {@hide}
19613     */
19614    protected boolean setFrame(int left, int top, int right, int bottom) {
19615        boolean changed = false;
19616
19617        if (DBG) {
19618            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19619                    + right + "," + bottom + ")");
19620        }
19621
19622        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19623            changed = true;
19624
19625            // Remember our drawn bit
19626            int drawn = mPrivateFlags & PFLAG_DRAWN;
19627
19628            int oldWidth = mRight - mLeft;
19629            int oldHeight = mBottom - mTop;
19630            int newWidth = right - left;
19631            int newHeight = bottom - top;
19632            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19633
19634            // Invalidate our old position
19635            invalidate(sizeChanged);
19636
19637            mLeft = left;
19638            mTop = top;
19639            mRight = right;
19640            mBottom = bottom;
19641            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19642
19643            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19644
19645
19646            if (sizeChanged) {
19647                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19648            }
19649
19650            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19651                // If we are visible, force the DRAWN bit to on so that
19652                // this invalidate will go through (at least to our parent).
19653                // This is because someone may have invalidated this view
19654                // before this call to setFrame came in, thereby clearing
19655                // the DRAWN bit.
19656                mPrivateFlags |= PFLAG_DRAWN;
19657                invalidate(sizeChanged);
19658                // parent display list may need to be recreated based on a change in the bounds
19659                // of any child
19660                invalidateParentCaches();
19661            }
19662
19663            // Reset drawn bit to original value (invalidate turns it off)
19664            mPrivateFlags |= drawn;
19665
19666            mBackgroundSizeChanged = true;
19667            mDefaultFocusHighlightSizeChanged = true;
19668            if (mForegroundInfo != null) {
19669                mForegroundInfo.mBoundsChanged = true;
19670            }
19671
19672            notifySubtreeAccessibilityStateChangedIfNeeded();
19673        }
19674        return changed;
19675    }
19676
19677    /**
19678     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19679     * @hide
19680     */
19681    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19682        setFrame(left, top, right, bottom);
19683    }
19684
19685    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19686        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19687        if (mOverlay != null) {
19688            mOverlay.getOverlayView().setRight(newWidth);
19689            mOverlay.getOverlayView().setBottom(newHeight);
19690        }
19691        rebuildOutline();
19692    }
19693
19694    /**
19695     * Finalize inflating a view from XML.  This is called as the last phase
19696     * of inflation, after all child views have been added.
19697     *
19698     * <p>Even if the subclass overrides onFinishInflate, they should always be
19699     * sure to call the super method, so that we get called.
19700     */
19701    @CallSuper
19702    protected void onFinishInflate() {
19703    }
19704
19705    /**
19706     * Returns the resources associated with this view.
19707     *
19708     * @return Resources object.
19709     */
19710    public Resources getResources() {
19711        return mResources;
19712    }
19713
19714    /**
19715     * Invalidates the specified Drawable.
19716     *
19717     * @param drawable the drawable to invalidate
19718     */
19719    @Override
19720    public void invalidateDrawable(@NonNull Drawable drawable) {
19721        if (verifyDrawable(drawable)) {
19722            final Rect dirty = drawable.getDirtyBounds();
19723            final int scrollX = mScrollX;
19724            final int scrollY = mScrollY;
19725
19726            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19727                    dirty.right + scrollX, dirty.bottom + scrollY);
19728            rebuildOutline();
19729        }
19730    }
19731
19732    /**
19733     * Schedules an action on a drawable to occur at a specified time.
19734     *
19735     * @param who the recipient of the action
19736     * @param what the action to run on the drawable
19737     * @param when the time at which the action must occur. Uses the
19738     *        {@link SystemClock#uptimeMillis} timebase.
19739     */
19740    @Override
19741    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19742        if (verifyDrawable(who) && what != null) {
19743            final long delay = when - SystemClock.uptimeMillis();
19744            if (mAttachInfo != null) {
19745                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19746                        Choreographer.CALLBACK_ANIMATION, what, who,
19747                        Choreographer.subtractFrameDelay(delay));
19748            } else {
19749                // Postpone the runnable until we know
19750                // on which thread it needs to run.
19751                getRunQueue().postDelayed(what, delay);
19752            }
19753        }
19754    }
19755
19756    /**
19757     * Cancels a scheduled action on a drawable.
19758     *
19759     * @param who the recipient of the action
19760     * @param what the action to cancel
19761     */
19762    @Override
19763    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19764        if (verifyDrawable(who) && what != null) {
19765            if (mAttachInfo != null) {
19766                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19767                        Choreographer.CALLBACK_ANIMATION, what, who);
19768            }
19769            getRunQueue().removeCallbacks(what);
19770        }
19771    }
19772
19773    /**
19774     * Unschedule any events associated with the given Drawable.  This can be
19775     * used when selecting a new Drawable into a view, so that the previous
19776     * one is completely unscheduled.
19777     *
19778     * @param who The Drawable to unschedule.
19779     *
19780     * @see #drawableStateChanged
19781     */
19782    public void unscheduleDrawable(Drawable who) {
19783        if (mAttachInfo != null && who != null) {
19784            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19785                    Choreographer.CALLBACK_ANIMATION, null, who);
19786        }
19787    }
19788
19789    /**
19790     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19791     * that the View directionality can and will be resolved before its Drawables.
19792     *
19793     * Will call {@link View#onResolveDrawables} when resolution is done.
19794     *
19795     * @hide
19796     */
19797    protected void resolveDrawables() {
19798        // Drawables resolution may need to happen before resolving the layout direction (which is
19799        // done only during the measure() call).
19800        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19801        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19802        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19803        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19804        // direction to be resolved as its resolved value will be the same as its raw value.
19805        if (!isLayoutDirectionResolved() &&
19806                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19807            return;
19808        }
19809
19810        final int layoutDirection = isLayoutDirectionResolved() ?
19811                getLayoutDirection() : getRawLayoutDirection();
19812
19813        if (mBackground != null) {
19814            mBackground.setLayoutDirection(layoutDirection);
19815        }
19816        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19817            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19818        }
19819        if (mDefaultFocusHighlight != null) {
19820            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19821        }
19822        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19823        onResolveDrawables(layoutDirection);
19824    }
19825
19826    boolean areDrawablesResolved() {
19827        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19828    }
19829
19830    /**
19831     * Called when layout direction has been resolved.
19832     *
19833     * The default implementation does nothing.
19834     *
19835     * @param layoutDirection The resolved layout direction.
19836     *
19837     * @see #LAYOUT_DIRECTION_LTR
19838     * @see #LAYOUT_DIRECTION_RTL
19839     *
19840     * @hide
19841     */
19842    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19843    }
19844
19845    /**
19846     * @hide
19847     */
19848    protected void resetResolvedDrawables() {
19849        resetResolvedDrawablesInternal();
19850    }
19851
19852    void resetResolvedDrawablesInternal() {
19853        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19854    }
19855
19856    /**
19857     * If your view subclass is displaying its own Drawable objects, it should
19858     * override this function and return true for any Drawable it is
19859     * displaying.  This allows animations for those drawables to be
19860     * scheduled.
19861     *
19862     * <p>Be sure to call through to the super class when overriding this
19863     * function.
19864     *
19865     * @param who The Drawable to verify.  Return true if it is one you are
19866     *            displaying, else return the result of calling through to the
19867     *            super class.
19868     *
19869     * @return boolean If true than the Drawable is being displayed in the
19870     *         view; else false and it is not allowed to animate.
19871     *
19872     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19873     * @see #drawableStateChanged()
19874     */
19875    @CallSuper
19876    protected boolean verifyDrawable(@NonNull Drawable who) {
19877        // Avoid verifying the scroll bar drawable so that we don't end up in
19878        // an invalidation loop. This effectively prevents the scroll bar
19879        // drawable from triggering invalidations and scheduling runnables.
19880        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19881                || (mDefaultFocusHighlight == who);
19882    }
19883
19884    /**
19885     * This function is called whenever the state of the view changes in such
19886     * a way that it impacts the state of drawables being shown.
19887     * <p>
19888     * If the View has a StateListAnimator, it will also be called to run necessary state
19889     * change animations.
19890     * <p>
19891     * Be sure to call through to the superclass when overriding this function.
19892     *
19893     * @see Drawable#setState(int[])
19894     */
19895    @CallSuper
19896    protected void drawableStateChanged() {
19897        final int[] state = getDrawableState();
19898        boolean changed = false;
19899
19900        final Drawable bg = mBackground;
19901        if (bg != null && bg.isStateful()) {
19902            changed |= bg.setState(state);
19903        }
19904
19905        final Drawable hl = mDefaultFocusHighlight;
19906        if (hl != null && hl.isStateful()) {
19907            changed |= hl.setState(state);
19908        }
19909
19910        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19911        if (fg != null && fg.isStateful()) {
19912            changed |= fg.setState(state);
19913        }
19914
19915        if (mScrollCache != null) {
19916            final Drawable scrollBar = mScrollCache.scrollBar;
19917            if (scrollBar != null && scrollBar.isStateful()) {
19918                changed |= scrollBar.setState(state)
19919                        && mScrollCache.state != ScrollabilityCache.OFF;
19920            }
19921        }
19922
19923        if (mStateListAnimator != null) {
19924            mStateListAnimator.setState(state);
19925        }
19926
19927        if (changed) {
19928            invalidate();
19929        }
19930    }
19931
19932    /**
19933     * This function is called whenever the view hotspot changes and needs to
19934     * be propagated to drawables or child views managed by the view.
19935     * <p>
19936     * Dispatching to child views is handled by
19937     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19938     * <p>
19939     * Be sure to call through to the superclass when overriding this function.
19940     *
19941     * @param x hotspot x coordinate
19942     * @param y hotspot y coordinate
19943     */
19944    @CallSuper
19945    public void drawableHotspotChanged(float x, float y) {
19946        if (mBackground != null) {
19947            mBackground.setHotspot(x, y);
19948        }
19949        if (mDefaultFocusHighlight != null) {
19950            mDefaultFocusHighlight.setHotspot(x, y);
19951        }
19952        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19953            mForegroundInfo.mDrawable.setHotspot(x, y);
19954        }
19955
19956        dispatchDrawableHotspotChanged(x, y);
19957    }
19958
19959    /**
19960     * Dispatches drawableHotspotChanged to all of this View's children.
19961     *
19962     * @param x hotspot x coordinate
19963     * @param y hotspot y coordinate
19964     * @see #drawableHotspotChanged(float, float)
19965     */
19966    public void dispatchDrawableHotspotChanged(float x, float y) {
19967    }
19968
19969    /**
19970     * Call this to force a view to update its drawable state. This will cause
19971     * drawableStateChanged to be called on this view. Views that are interested
19972     * in the new state should call getDrawableState.
19973     *
19974     * @see #drawableStateChanged
19975     * @see #getDrawableState
19976     */
19977    public void refreshDrawableState() {
19978        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19979        drawableStateChanged();
19980
19981        ViewParent parent = mParent;
19982        if (parent != null) {
19983            parent.childDrawableStateChanged(this);
19984        }
19985    }
19986
19987    /**
19988     * Create a default focus highlight if it doesn't exist.
19989     * @return a default focus highlight.
19990     */
19991    private Drawable getDefaultFocusHighlightDrawable() {
19992        if (mDefaultFocusHighlightCache == null) {
19993            if (mContext != null) {
19994                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
19995                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
19996                mDefaultFocusHighlightCache = ta.getDrawable(0);
19997                ta.recycle();
19998            }
19999        }
20000        return mDefaultFocusHighlightCache;
20001    }
20002
20003    /**
20004     * Set the current default focus highlight.
20005     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
20006     */
20007    private void setDefaultFocusHighlight(Drawable highlight) {
20008        mDefaultFocusHighlight = highlight;
20009        mDefaultFocusHighlightSizeChanged = true;
20010        if (highlight != null) {
20011            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20012                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20013            }
20014            highlight.setLayoutDirection(getLayoutDirection());
20015            if (highlight.isStateful()) {
20016                highlight.setState(getDrawableState());
20017            }
20018            if (isAttachedToWindow()) {
20019                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20020            }
20021            // Set callback last, since the view may still be initializing.
20022            highlight.setCallback(this);
20023        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20024                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20025            mPrivateFlags |= PFLAG_SKIP_DRAW;
20026        }
20027        invalidate();
20028    }
20029
20030    /**
20031     * Check whether we need to draw a default focus highlight when this view gets focused,
20032     * which requires:
20033     * <ul>
20034     *     <li>In both background and foreground, {@link android.R.attr#state_focused}
20035     *         is not defined.</li>
20036     *     <li>This view is not in touch mode.</li>
20037     *     <li>This view doesn't opt out for a default focus highlight, via
20038     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
20039     *     <li>This view is attached to window.</li>
20040     * </ul>
20041     * @return {@code true} if a default focus highlight is needed.
20042     * @hide
20043     */
20044    @TestApi
20045    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
20046        final boolean lackFocusState = (background == null || !background.isStateful()
20047                || !background.hasFocusStateSpecified())
20048                && (foreground == null || !foreground.isStateful()
20049                || !foreground.hasFocusStateSpecified());
20050        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
20051                && isAttachedToWindow() && sUseDefaultFocusHighlight;
20052    }
20053
20054    /**
20055     * When this view is focused, switches on/off the default focused highlight.
20056     * <p>
20057     * This always happens when this view is focused, and only at this moment the default focus
20058     * highlight can be visible.
20059     */
20060    private void switchDefaultFocusHighlight() {
20061        if (isFocused()) {
20062            final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
20063                    mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
20064            final boolean active = mDefaultFocusHighlight != null;
20065            if (needed && !active) {
20066                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
20067            } else if (!needed && active) {
20068                // The highlight is no longer needed, so tear it down.
20069                setDefaultFocusHighlight(null);
20070            }
20071        }
20072    }
20073
20074    /**
20075     * Draw the default focus highlight onto the canvas.
20076     * @param canvas the canvas where we're drawing the highlight.
20077     */
20078    private void drawDefaultFocusHighlight(Canvas canvas) {
20079        if (mDefaultFocusHighlight != null) {
20080            if (mDefaultFocusHighlightSizeChanged) {
20081                mDefaultFocusHighlightSizeChanged = false;
20082                final int l = mScrollX;
20083                final int r = l + mRight - mLeft;
20084                final int t = mScrollY;
20085                final int b = t + mBottom - mTop;
20086                mDefaultFocusHighlight.setBounds(l, t, r, b);
20087            }
20088            mDefaultFocusHighlight.draw(canvas);
20089        }
20090    }
20091
20092    /**
20093     * Return an array of resource IDs of the drawable states representing the
20094     * current state of the view.
20095     *
20096     * @return The current drawable state
20097     *
20098     * @see Drawable#setState(int[])
20099     * @see #drawableStateChanged()
20100     * @see #onCreateDrawableState(int)
20101     */
20102    public final int[] getDrawableState() {
20103        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
20104            return mDrawableState;
20105        } else {
20106            mDrawableState = onCreateDrawableState(0);
20107            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
20108            return mDrawableState;
20109        }
20110    }
20111
20112    /**
20113     * Generate the new {@link android.graphics.drawable.Drawable} state for
20114     * this view. This is called by the view
20115     * system when the cached Drawable state is determined to be invalid.  To
20116     * retrieve the current state, you should use {@link #getDrawableState}.
20117     *
20118     * @param extraSpace if non-zero, this is the number of extra entries you
20119     * would like in the returned array in which you can place your own
20120     * states.
20121     *
20122     * @return Returns an array holding the current {@link Drawable} state of
20123     * the view.
20124     *
20125     * @see #mergeDrawableStates(int[], int[])
20126     */
20127    protected int[] onCreateDrawableState(int extraSpace) {
20128        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
20129                mParent instanceof View) {
20130            return ((View) mParent).onCreateDrawableState(extraSpace);
20131        }
20132
20133        int[] drawableState;
20134
20135        int privateFlags = mPrivateFlags;
20136
20137        int viewStateIndex = 0;
20138        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
20139        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
20140        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
20141        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
20142        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
20143        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
20144        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
20145                ThreadedRenderer.isAvailable()) {
20146            // This is set if HW acceleration is requested, even if the current
20147            // process doesn't allow it.  This is just to allow app preview
20148            // windows to better match their app.
20149            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
20150        }
20151        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
20152
20153        final int privateFlags2 = mPrivateFlags2;
20154        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
20155            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
20156        }
20157        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
20158            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
20159        }
20160
20161        drawableState = StateSet.get(viewStateIndex);
20162
20163        //noinspection ConstantIfStatement
20164        if (false) {
20165            Log.i("View", "drawableStateIndex=" + viewStateIndex);
20166            Log.i("View", toString()
20167                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
20168                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
20169                    + " fo=" + hasFocus()
20170                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
20171                    + " wf=" + hasWindowFocus()
20172                    + ": " + Arrays.toString(drawableState));
20173        }
20174
20175        if (extraSpace == 0) {
20176            return drawableState;
20177        }
20178
20179        final int[] fullState;
20180        if (drawableState != null) {
20181            fullState = new int[drawableState.length + extraSpace];
20182            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
20183        } else {
20184            fullState = new int[extraSpace];
20185        }
20186
20187        return fullState;
20188    }
20189
20190    /**
20191     * Merge your own state values in <var>additionalState</var> into the base
20192     * state values <var>baseState</var> that were returned by
20193     * {@link #onCreateDrawableState(int)}.
20194     *
20195     * @param baseState The base state values returned by
20196     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
20197     * own additional state values.
20198     *
20199     * @param additionalState The additional state values you would like
20200     * added to <var>baseState</var>; this array is not modified.
20201     *
20202     * @return As a convenience, the <var>baseState</var> array you originally
20203     * passed into the function is returned.
20204     *
20205     * @see #onCreateDrawableState(int)
20206     */
20207    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
20208        final int N = baseState.length;
20209        int i = N - 1;
20210        while (i >= 0 && baseState[i] == 0) {
20211            i--;
20212        }
20213        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
20214        return baseState;
20215    }
20216
20217    /**
20218     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
20219     * on all Drawable objects associated with this view.
20220     * <p>
20221     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
20222     * attached to this view.
20223     */
20224    @CallSuper
20225    public void jumpDrawablesToCurrentState() {
20226        if (mBackground != null) {
20227            mBackground.jumpToCurrentState();
20228        }
20229        if (mStateListAnimator != null) {
20230            mStateListAnimator.jumpToCurrentState();
20231        }
20232        if (mDefaultFocusHighlight != null) {
20233            mDefaultFocusHighlight.jumpToCurrentState();
20234        }
20235        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20236            mForegroundInfo.mDrawable.jumpToCurrentState();
20237        }
20238    }
20239
20240    /**
20241     * Sets the background color for this view.
20242     * @param color the color of the background
20243     */
20244    @RemotableViewMethod
20245    public void setBackgroundColor(@ColorInt int color) {
20246        if (mBackground instanceof ColorDrawable) {
20247            ((ColorDrawable) mBackground.mutate()).setColor(color);
20248            computeOpaqueFlags();
20249            mBackgroundResource = 0;
20250        } else {
20251            setBackground(new ColorDrawable(color));
20252        }
20253    }
20254
20255    /**
20256     * Set the background to a given resource. The resource should refer to
20257     * a Drawable object or 0 to remove the background.
20258     * @param resid The identifier of the resource.
20259     *
20260     * @attr ref android.R.styleable#View_background
20261     */
20262    @RemotableViewMethod
20263    public void setBackgroundResource(@DrawableRes int resid) {
20264        if (resid != 0 && resid == mBackgroundResource) {
20265            return;
20266        }
20267
20268        Drawable d = null;
20269        if (resid != 0) {
20270            d = mContext.getDrawable(resid);
20271        }
20272        setBackground(d);
20273
20274        mBackgroundResource = resid;
20275    }
20276
20277    /**
20278     * Set the background to a given Drawable, or remove the background. If the
20279     * background has padding, this View's padding is set to the background's
20280     * padding. However, when a background is removed, this View's padding isn't
20281     * touched. If setting the padding is desired, please use
20282     * {@link #setPadding(int, int, int, int)}.
20283     *
20284     * @param background The Drawable to use as the background, or null to remove the
20285     *        background
20286     */
20287    public void setBackground(Drawable background) {
20288        //noinspection deprecation
20289        setBackgroundDrawable(background);
20290    }
20291
20292    /**
20293     * @deprecated use {@link #setBackground(Drawable)} instead
20294     */
20295    @Deprecated
20296    public void setBackgroundDrawable(Drawable background) {
20297        computeOpaqueFlags();
20298
20299        if (background == mBackground) {
20300            return;
20301        }
20302
20303        boolean requestLayout = false;
20304
20305        mBackgroundResource = 0;
20306
20307        /*
20308         * Regardless of whether we're setting a new background or not, we want
20309         * to clear the previous drawable. setVisible first while we still have the callback set.
20310         */
20311        if (mBackground != null) {
20312            if (isAttachedToWindow()) {
20313                mBackground.setVisible(false, false);
20314            }
20315            mBackground.setCallback(null);
20316            unscheduleDrawable(mBackground);
20317        }
20318
20319        if (background != null) {
20320            Rect padding = sThreadLocal.get();
20321            if (padding == null) {
20322                padding = new Rect();
20323                sThreadLocal.set(padding);
20324            }
20325            resetResolvedDrawablesInternal();
20326            background.setLayoutDirection(getLayoutDirection());
20327            if (background.getPadding(padding)) {
20328                resetResolvedPaddingInternal();
20329                switch (background.getLayoutDirection()) {
20330                    case LAYOUT_DIRECTION_RTL:
20331                        mUserPaddingLeftInitial = padding.right;
20332                        mUserPaddingRightInitial = padding.left;
20333                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20334                        break;
20335                    case LAYOUT_DIRECTION_LTR:
20336                    default:
20337                        mUserPaddingLeftInitial = padding.left;
20338                        mUserPaddingRightInitial = padding.right;
20339                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20340                }
20341                mLeftPaddingDefined = false;
20342                mRightPaddingDefined = false;
20343            }
20344
20345            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20346            // if it has a different minimum size, we should layout again
20347            if (mBackground == null
20348                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
20349                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20350                requestLayout = true;
20351            }
20352
20353            // Set mBackground before we set this as the callback and start making other
20354            // background drawable state change calls. In particular, the setVisible call below
20355            // can result in drawables attempting to start animations or otherwise invalidate,
20356            // which requires the view set as the callback (us) to recognize the drawable as
20357            // belonging to it as per verifyDrawable.
20358            mBackground = background;
20359            if (background.isStateful()) {
20360                background.setState(getDrawableState());
20361            }
20362            if (isAttachedToWindow()) {
20363                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20364            }
20365
20366            applyBackgroundTint();
20367
20368            // Set callback last, since the view may still be initializing.
20369            background.setCallback(this);
20370
20371            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20372                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20373                requestLayout = true;
20374            }
20375        } else {
20376            /* Remove the background */
20377            mBackground = null;
20378            if ((mViewFlags & WILL_NOT_DRAW) != 0
20379                    && (mDefaultFocusHighlight == null)
20380                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20381                mPrivateFlags |= PFLAG_SKIP_DRAW;
20382            }
20383
20384            /*
20385             * When the background is set, we try to apply its padding to this
20386             * View. When the background is removed, we don't touch this View's
20387             * padding. This is noted in the Javadocs. Hence, we don't need to
20388             * requestLayout(), the invalidate() below is sufficient.
20389             */
20390
20391            // The old background's minimum size could have affected this
20392            // View's layout, so let's requestLayout
20393            requestLayout = true;
20394        }
20395
20396        computeOpaqueFlags();
20397
20398        if (requestLayout) {
20399            requestLayout();
20400        }
20401
20402        mBackgroundSizeChanged = true;
20403        invalidate(true);
20404        invalidateOutline();
20405    }
20406
20407    /**
20408     * Gets the background drawable
20409     *
20410     * @return The drawable used as the background for this view, if any.
20411     *
20412     * @see #setBackground(Drawable)
20413     *
20414     * @attr ref android.R.styleable#View_background
20415     */
20416    public Drawable getBackground() {
20417        return mBackground;
20418    }
20419
20420    /**
20421     * Applies a tint to the background drawable. Does not modify the current tint
20422     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20423     * <p>
20424     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20425     * mutate the drawable and apply the specified tint and tint mode using
20426     * {@link Drawable#setTintList(ColorStateList)}.
20427     *
20428     * @param tint the tint to apply, may be {@code null} to clear tint
20429     *
20430     * @attr ref android.R.styleable#View_backgroundTint
20431     * @see #getBackgroundTintList()
20432     * @see Drawable#setTintList(ColorStateList)
20433     */
20434    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20435        if (mBackgroundTint == null) {
20436            mBackgroundTint = new TintInfo();
20437        }
20438        mBackgroundTint.mTintList = tint;
20439        mBackgroundTint.mHasTintList = true;
20440
20441        applyBackgroundTint();
20442    }
20443
20444    /**
20445     * Return the tint applied to the background drawable, if specified.
20446     *
20447     * @return the tint applied to the background drawable
20448     * @attr ref android.R.styleable#View_backgroundTint
20449     * @see #setBackgroundTintList(ColorStateList)
20450     */
20451    @Nullable
20452    public ColorStateList getBackgroundTintList() {
20453        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20454    }
20455
20456    /**
20457     * Specifies the blending mode used to apply the tint specified by
20458     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20459     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20460     *
20461     * @param tintMode the blending mode used to apply the tint, may be
20462     *                 {@code null} to clear tint
20463     * @attr ref android.R.styleable#View_backgroundTintMode
20464     * @see #getBackgroundTintMode()
20465     * @see Drawable#setTintMode(PorterDuff.Mode)
20466     */
20467    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20468        if (mBackgroundTint == null) {
20469            mBackgroundTint = new TintInfo();
20470        }
20471        mBackgroundTint.mTintMode = tintMode;
20472        mBackgroundTint.mHasTintMode = true;
20473
20474        applyBackgroundTint();
20475    }
20476
20477    /**
20478     * Return the blending mode used to apply the tint to the background
20479     * drawable, if specified.
20480     *
20481     * @return the blending mode used to apply the tint to the background
20482     *         drawable
20483     * @attr ref android.R.styleable#View_backgroundTintMode
20484     * @see #setBackgroundTintMode(PorterDuff.Mode)
20485     */
20486    @Nullable
20487    public PorterDuff.Mode getBackgroundTintMode() {
20488        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20489    }
20490
20491    private void applyBackgroundTint() {
20492        if (mBackground != null && mBackgroundTint != null) {
20493            final TintInfo tintInfo = mBackgroundTint;
20494            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20495                mBackground = mBackground.mutate();
20496
20497                if (tintInfo.mHasTintList) {
20498                    mBackground.setTintList(tintInfo.mTintList);
20499                }
20500
20501                if (tintInfo.mHasTintMode) {
20502                    mBackground.setTintMode(tintInfo.mTintMode);
20503                }
20504
20505                // The drawable (or one of its children) may not have been
20506                // stateful before applying the tint, so let's try again.
20507                if (mBackground.isStateful()) {
20508                    mBackground.setState(getDrawableState());
20509                }
20510            }
20511        }
20512    }
20513
20514    /**
20515     * Returns the drawable used as the foreground of this View. The
20516     * foreground drawable, if non-null, is always drawn on top of the view's content.
20517     *
20518     * @return a Drawable or null if no foreground was set
20519     *
20520     * @see #onDrawForeground(Canvas)
20521     */
20522    public Drawable getForeground() {
20523        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20524    }
20525
20526    /**
20527     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20528     *
20529     * @param foreground the Drawable to be drawn on top of the children
20530     *
20531     * @attr ref android.R.styleable#View_foreground
20532     */
20533    public void setForeground(Drawable foreground) {
20534        if (mForegroundInfo == null) {
20535            if (foreground == null) {
20536                // Nothing to do.
20537                return;
20538            }
20539            mForegroundInfo = new ForegroundInfo();
20540        }
20541
20542        if (foreground == mForegroundInfo.mDrawable) {
20543            // Nothing to do
20544            return;
20545        }
20546
20547        if (mForegroundInfo.mDrawable != null) {
20548            if (isAttachedToWindow()) {
20549                mForegroundInfo.mDrawable.setVisible(false, false);
20550            }
20551            mForegroundInfo.mDrawable.setCallback(null);
20552            unscheduleDrawable(mForegroundInfo.mDrawable);
20553        }
20554
20555        mForegroundInfo.mDrawable = foreground;
20556        mForegroundInfo.mBoundsChanged = true;
20557        if (foreground != null) {
20558            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20559                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20560            }
20561            foreground.setLayoutDirection(getLayoutDirection());
20562            if (foreground.isStateful()) {
20563                foreground.setState(getDrawableState());
20564            }
20565            applyForegroundTint();
20566            if (isAttachedToWindow()) {
20567                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20568            }
20569            // Set callback last, since the view may still be initializing.
20570            foreground.setCallback(this);
20571        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20572                && (mDefaultFocusHighlight == null)) {
20573            mPrivateFlags |= PFLAG_SKIP_DRAW;
20574        }
20575        requestLayout();
20576        invalidate();
20577    }
20578
20579    /**
20580     * Magic bit used to support features of framework-internal window decor implementation details.
20581     * This used to live exclusively in FrameLayout.
20582     *
20583     * @return true if the foreground should draw inside the padding region or false
20584     *         if it should draw inset by the view's padding
20585     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20586     */
20587    public boolean isForegroundInsidePadding() {
20588        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20589    }
20590
20591    /**
20592     * Describes how the foreground is positioned.
20593     *
20594     * @return foreground gravity.
20595     *
20596     * @see #setForegroundGravity(int)
20597     *
20598     * @attr ref android.R.styleable#View_foregroundGravity
20599     */
20600    public int getForegroundGravity() {
20601        return mForegroundInfo != null ? mForegroundInfo.mGravity
20602                : Gravity.START | Gravity.TOP;
20603    }
20604
20605    /**
20606     * Describes how the foreground is positioned. Defaults to START and TOP.
20607     *
20608     * @param gravity see {@link android.view.Gravity}
20609     *
20610     * @see #getForegroundGravity()
20611     *
20612     * @attr ref android.R.styleable#View_foregroundGravity
20613     */
20614    public void setForegroundGravity(int gravity) {
20615        if (mForegroundInfo == null) {
20616            mForegroundInfo = new ForegroundInfo();
20617        }
20618
20619        if (mForegroundInfo.mGravity != gravity) {
20620            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20621                gravity |= Gravity.START;
20622            }
20623
20624            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20625                gravity |= Gravity.TOP;
20626            }
20627
20628            mForegroundInfo.mGravity = gravity;
20629            requestLayout();
20630        }
20631    }
20632
20633    /**
20634     * Applies a tint to the foreground drawable. Does not modify the current tint
20635     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20636     * <p>
20637     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20638     * mutate the drawable and apply the specified tint and tint mode using
20639     * {@link Drawable#setTintList(ColorStateList)}.
20640     *
20641     * @param tint the tint to apply, may be {@code null} to clear tint
20642     *
20643     * @attr ref android.R.styleable#View_foregroundTint
20644     * @see #getForegroundTintList()
20645     * @see Drawable#setTintList(ColorStateList)
20646     */
20647    public void setForegroundTintList(@Nullable ColorStateList tint) {
20648        if (mForegroundInfo == null) {
20649            mForegroundInfo = new ForegroundInfo();
20650        }
20651        if (mForegroundInfo.mTintInfo == null) {
20652            mForegroundInfo.mTintInfo = new TintInfo();
20653        }
20654        mForegroundInfo.mTintInfo.mTintList = tint;
20655        mForegroundInfo.mTintInfo.mHasTintList = true;
20656
20657        applyForegroundTint();
20658    }
20659
20660    /**
20661     * Return the tint applied to the foreground drawable, if specified.
20662     *
20663     * @return the tint applied to the foreground drawable
20664     * @attr ref android.R.styleable#View_foregroundTint
20665     * @see #setForegroundTintList(ColorStateList)
20666     */
20667    @Nullable
20668    public ColorStateList getForegroundTintList() {
20669        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20670                ? mForegroundInfo.mTintInfo.mTintList : null;
20671    }
20672
20673    /**
20674     * Specifies the blending mode used to apply the tint specified by
20675     * {@link #setForegroundTintList(ColorStateList)}} to the background
20676     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20677     *
20678     * @param tintMode the blending mode used to apply the tint, may be
20679     *                 {@code null} to clear tint
20680     * @attr ref android.R.styleable#View_foregroundTintMode
20681     * @see #getForegroundTintMode()
20682     * @see Drawable#setTintMode(PorterDuff.Mode)
20683     */
20684    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20685        if (mForegroundInfo == null) {
20686            mForegroundInfo = new ForegroundInfo();
20687        }
20688        if (mForegroundInfo.mTintInfo == null) {
20689            mForegroundInfo.mTintInfo = new TintInfo();
20690        }
20691        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20692        mForegroundInfo.mTintInfo.mHasTintMode = true;
20693
20694        applyForegroundTint();
20695    }
20696
20697    /**
20698     * Return the blending mode used to apply the tint to the foreground
20699     * drawable, if specified.
20700     *
20701     * @return the blending mode used to apply the tint to the foreground
20702     *         drawable
20703     * @attr ref android.R.styleable#View_foregroundTintMode
20704     * @see #setForegroundTintMode(PorterDuff.Mode)
20705     */
20706    @Nullable
20707    public PorterDuff.Mode getForegroundTintMode() {
20708        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20709                ? mForegroundInfo.mTintInfo.mTintMode : null;
20710    }
20711
20712    private void applyForegroundTint() {
20713        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20714                && mForegroundInfo.mTintInfo != null) {
20715            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20716            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20717                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20718
20719                if (tintInfo.mHasTintList) {
20720                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20721                }
20722
20723                if (tintInfo.mHasTintMode) {
20724                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20725                }
20726
20727                // The drawable (or one of its children) may not have been
20728                // stateful before applying the tint, so let's try again.
20729                if (mForegroundInfo.mDrawable.isStateful()) {
20730                    mForegroundInfo.mDrawable.setState(getDrawableState());
20731                }
20732            }
20733        }
20734    }
20735
20736    /**
20737     * Get the drawable to be overlayed when a view is autofilled
20738     *
20739     * @return The drawable
20740     *
20741     * @throws IllegalStateException if the drawable could not be found.
20742     */
20743    @Nullable private Drawable getAutofilledDrawable() {
20744        if (mAttachInfo == null) {
20745            return null;
20746        }
20747        // Lazily load the isAutofilled drawable.
20748        if (mAttachInfo.mAutofilledDrawable == null) {
20749            Context rootContext = getRootView().getContext();
20750            TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20751            int attributeResourceId = a.getResourceId(0, 0);
20752            mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
20753            a.recycle();
20754        }
20755
20756        return mAttachInfo.mAutofilledDrawable;
20757    }
20758
20759    /**
20760     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20761     *
20762     * @param canvas The canvas to draw on
20763     */
20764    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20765        if (isAutofilled()) {
20766            Drawable autofilledHighlight = getAutofilledDrawable();
20767
20768            if (autofilledHighlight != null) {
20769                autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20770                autofilledHighlight.draw(canvas);
20771            }
20772        }
20773    }
20774
20775    /**
20776     * Draw any foreground content for this view.
20777     *
20778     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20779     * drawable or other view-specific decorations. The foreground is drawn on top of the
20780     * primary view content.</p>
20781     *
20782     * @param canvas canvas to draw into
20783     */
20784    public void onDrawForeground(Canvas canvas) {
20785        onDrawScrollIndicators(canvas);
20786        onDrawScrollBars(canvas);
20787
20788        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20789        if (foreground != null) {
20790            if (mForegroundInfo.mBoundsChanged) {
20791                mForegroundInfo.mBoundsChanged = false;
20792                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20793                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20794
20795                if (mForegroundInfo.mInsidePadding) {
20796                    selfBounds.set(0, 0, getWidth(), getHeight());
20797                } else {
20798                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20799                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20800                }
20801
20802                final int ld = getLayoutDirection();
20803                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20804                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20805                foreground.setBounds(overlayBounds);
20806            }
20807
20808            foreground.draw(canvas);
20809        }
20810    }
20811
20812    /**
20813     * Sets the padding. The view may add on the space required to display
20814     * the scrollbars, depending on the style and visibility of the scrollbars.
20815     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20816     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20817     * from the values set in this call.
20818     *
20819     * @attr ref android.R.styleable#View_padding
20820     * @attr ref android.R.styleable#View_paddingBottom
20821     * @attr ref android.R.styleable#View_paddingLeft
20822     * @attr ref android.R.styleable#View_paddingRight
20823     * @attr ref android.R.styleable#View_paddingTop
20824     * @param left the left padding in pixels
20825     * @param top the top padding in pixels
20826     * @param right the right padding in pixels
20827     * @param bottom the bottom padding in pixels
20828     */
20829    public void setPadding(int left, int top, int right, int bottom) {
20830        resetResolvedPaddingInternal();
20831
20832        mUserPaddingStart = UNDEFINED_PADDING;
20833        mUserPaddingEnd = UNDEFINED_PADDING;
20834
20835        mUserPaddingLeftInitial = left;
20836        mUserPaddingRightInitial = right;
20837
20838        mLeftPaddingDefined = true;
20839        mRightPaddingDefined = true;
20840
20841        internalSetPadding(left, top, right, bottom);
20842    }
20843
20844    /**
20845     * @hide
20846     */
20847    protected void internalSetPadding(int left, int top, int right, int bottom) {
20848        mUserPaddingLeft = left;
20849        mUserPaddingRight = right;
20850        mUserPaddingBottom = bottom;
20851
20852        final int viewFlags = mViewFlags;
20853        boolean changed = false;
20854
20855        // Common case is there are no scroll bars.
20856        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20857            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20858                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20859                        ? 0 : getVerticalScrollbarWidth();
20860                switch (mVerticalScrollbarPosition) {
20861                    case SCROLLBAR_POSITION_DEFAULT:
20862                        if (isLayoutRtl()) {
20863                            left += offset;
20864                        } else {
20865                            right += offset;
20866                        }
20867                        break;
20868                    case SCROLLBAR_POSITION_RIGHT:
20869                        right += offset;
20870                        break;
20871                    case SCROLLBAR_POSITION_LEFT:
20872                        left += offset;
20873                        break;
20874                }
20875            }
20876            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20877                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20878                        ? 0 : getHorizontalScrollbarHeight();
20879            }
20880        }
20881
20882        if (mPaddingLeft != left) {
20883            changed = true;
20884            mPaddingLeft = left;
20885        }
20886        if (mPaddingTop != top) {
20887            changed = true;
20888            mPaddingTop = top;
20889        }
20890        if (mPaddingRight != right) {
20891            changed = true;
20892            mPaddingRight = right;
20893        }
20894        if (mPaddingBottom != bottom) {
20895            changed = true;
20896            mPaddingBottom = bottom;
20897        }
20898
20899        if (changed) {
20900            requestLayout();
20901            invalidateOutline();
20902        }
20903    }
20904
20905    /**
20906     * Sets the relative padding. The view may add on the space required to display
20907     * the scrollbars, depending on the style and visibility of the scrollbars.
20908     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20909     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20910     * from the values set in this call.
20911     *
20912     * @attr ref android.R.styleable#View_padding
20913     * @attr ref android.R.styleable#View_paddingBottom
20914     * @attr ref android.R.styleable#View_paddingStart
20915     * @attr ref android.R.styleable#View_paddingEnd
20916     * @attr ref android.R.styleable#View_paddingTop
20917     * @param start the start padding in pixels
20918     * @param top the top padding in pixels
20919     * @param end the end padding in pixels
20920     * @param bottom the bottom padding in pixels
20921     */
20922    public void setPaddingRelative(int start, int top, int end, int bottom) {
20923        resetResolvedPaddingInternal();
20924
20925        mUserPaddingStart = start;
20926        mUserPaddingEnd = end;
20927        mLeftPaddingDefined = true;
20928        mRightPaddingDefined = true;
20929
20930        switch(getLayoutDirection()) {
20931            case LAYOUT_DIRECTION_RTL:
20932                mUserPaddingLeftInitial = end;
20933                mUserPaddingRightInitial = start;
20934                internalSetPadding(end, top, start, bottom);
20935                break;
20936            case LAYOUT_DIRECTION_LTR:
20937            default:
20938                mUserPaddingLeftInitial = start;
20939                mUserPaddingRightInitial = end;
20940                internalSetPadding(start, top, end, bottom);
20941        }
20942    }
20943
20944    /**
20945     * Returns the top padding of this view.
20946     *
20947     * @return the top padding in pixels
20948     */
20949    public int getPaddingTop() {
20950        return mPaddingTop;
20951    }
20952
20953    /**
20954     * Returns the bottom padding of this view. If there are inset and enabled
20955     * scrollbars, this value may include the space required to display the
20956     * scrollbars as well.
20957     *
20958     * @return the bottom padding in pixels
20959     */
20960    public int getPaddingBottom() {
20961        return mPaddingBottom;
20962    }
20963
20964    /**
20965     * Returns the left padding of this view. If there are inset and enabled
20966     * scrollbars, this value may include the space required to display the
20967     * scrollbars as well.
20968     *
20969     * @return the left padding in pixels
20970     */
20971    public int getPaddingLeft() {
20972        if (!isPaddingResolved()) {
20973            resolvePadding();
20974        }
20975        return mPaddingLeft;
20976    }
20977
20978    /**
20979     * Returns the start padding of this view depending on its resolved layout direction.
20980     * If there are inset and enabled scrollbars, this value may include the space
20981     * required to display the scrollbars as well.
20982     *
20983     * @return the start padding in pixels
20984     */
20985    public int getPaddingStart() {
20986        if (!isPaddingResolved()) {
20987            resolvePadding();
20988        }
20989        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20990                mPaddingRight : mPaddingLeft;
20991    }
20992
20993    /**
20994     * Returns the right padding of this view. If there are inset and enabled
20995     * scrollbars, this value may include the space required to display the
20996     * scrollbars as well.
20997     *
20998     * @return the right padding in pixels
20999     */
21000    public int getPaddingRight() {
21001        if (!isPaddingResolved()) {
21002            resolvePadding();
21003        }
21004        return mPaddingRight;
21005    }
21006
21007    /**
21008     * Returns the end padding of this view depending on its resolved layout direction.
21009     * If there are inset and enabled scrollbars, this value may include the space
21010     * required to display the scrollbars as well.
21011     *
21012     * @return the end padding in pixels
21013     */
21014    public int getPaddingEnd() {
21015        if (!isPaddingResolved()) {
21016            resolvePadding();
21017        }
21018        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21019                mPaddingLeft : mPaddingRight;
21020    }
21021
21022    /**
21023     * Return if the padding has been set through relative values
21024     * {@link #setPaddingRelative(int, int, int, int)} or through
21025     * @attr ref android.R.styleable#View_paddingStart or
21026     * @attr ref android.R.styleable#View_paddingEnd
21027     *
21028     * @return true if the padding is relative or false if it is not.
21029     */
21030    public boolean isPaddingRelative() {
21031        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
21032    }
21033
21034    Insets computeOpticalInsets() {
21035        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
21036    }
21037
21038    /**
21039     * @hide
21040     */
21041    public void resetPaddingToInitialValues() {
21042        if (isRtlCompatibilityMode()) {
21043            mPaddingLeft = mUserPaddingLeftInitial;
21044            mPaddingRight = mUserPaddingRightInitial;
21045            return;
21046        }
21047        if (isLayoutRtl()) {
21048            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
21049            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
21050        } else {
21051            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
21052            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
21053        }
21054    }
21055
21056    /**
21057     * @hide
21058     */
21059    public Insets getOpticalInsets() {
21060        if (mLayoutInsets == null) {
21061            mLayoutInsets = computeOpticalInsets();
21062        }
21063        return mLayoutInsets;
21064    }
21065
21066    /**
21067     * Set this view's optical insets.
21068     *
21069     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
21070     * property. Views that compute their own optical insets should call it as part of measurement.
21071     * This method does not request layout. If you are setting optical insets outside of
21072     * measure/layout itself you will want to call requestLayout() yourself.
21073     * </p>
21074     * @hide
21075     */
21076    public void setOpticalInsets(Insets insets) {
21077        mLayoutInsets = insets;
21078    }
21079
21080    /**
21081     * Changes the selection state of this view. A view can be selected or not.
21082     * Note that selection is not the same as focus. Views are typically
21083     * selected in the context of an AdapterView like ListView or GridView;
21084     * the selected view is the view that is highlighted.
21085     *
21086     * @param selected true if the view must be selected, false otherwise
21087     */
21088    public void setSelected(boolean selected) {
21089        //noinspection DoubleNegation
21090        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
21091            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
21092            if (!selected) resetPressedState();
21093            invalidate(true);
21094            refreshDrawableState();
21095            dispatchSetSelected(selected);
21096            if (selected) {
21097                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
21098            } else {
21099                notifyViewAccessibilityStateChangedIfNeeded(
21100                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
21101            }
21102        }
21103    }
21104
21105    /**
21106     * Dispatch setSelected to all of this View's children.
21107     *
21108     * @see #setSelected(boolean)
21109     *
21110     * @param selected The new selected state
21111     */
21112    protected void dispatchSetSelected(boolean selected) {
21113    }
21114
21115    /**
21116     * Indicates the selection state of this view.
21117     *
21118     * @return true if the view is selected, false otherwise
21119     */
21120    @ViewDebug.ExportedProperty
21121    public boolean isSelected() {
21122        return (mPrivateFlags & PFLAG_SELECTED) != 0;
21123    }
21124
21125    /**
21126     * Changes the activated state of this view. A view can be activated or not.
21127     * Note that activation is not the same as selection.  Selection is
21128     * a transient property, representing the view (hierarchy) the user is
21129     * currently interacting with.  Activation is a longer-term state that the
21130     * user can move views in and out of.  For example, in a list view with
21131     * single or multiple selection enabled, the views in the current selection
21132     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
21133     * here.)  The activated state is propagated down to children of the view it
21134     * is set on.
21135     *
21136     * @param activated true if the view must be activated, false otherwise
21137     */
21138    public void setActivated(boolean activated) {
21139        //noinspection DoubleNegation
21140        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
21141            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
21142            invalidate(true);
21143            refreshDrawableState();
21144            dispatchSetActivated(activated);
21145        }
21146    }
21147
21148    /**
21149     * Dispatch setActivated to all of this View's children.
21150     *
21151     * @see #setActivated(boolean)
21152     *
21153     * @param activated The new activated state
21154     */
21155    protected void dispatchSetActivated(boolean activated) {
21156    }
21157
21158    /**
21159     * Indicates the activation state of this view.
21160     *
21161     * @return true if the view is activated, false otherwise
21162     */
21163    @ViewDebug.ExportedProperty
21164    public boolean isActivated() {
21165        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
21166    }
21167
21168    /**
21169     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
21170     * observer can be used to get notifications when global events, like
21171     * layout, happen.
21172     *
21173     * The returned ViewTreeObserver observer is not guaranteed to remain
21174     * valid for the lifetime of this View. If the caller of this method keeps
21175     * a long-lived reference to ViewTreeObserver, it should always check for
21176     * the return value of {@link ViewTreeObserver#isAlive()}.
21177     *
21178     * @return The ViewTreeObserver for this view's hierarchy.
21179     */
21180    public ViewTreeObserver getViewTreeObserver() {
21181        if (mAttachInfo != null) {
21182            return mAttachInfo.mTreeObserver;
21183        }
21184        if (mFloatingTreeObserver == null) {
21185            mFloatingTreeObserver = new ViewTreeObserver(mContext);
21186        }
21187        return mFloatingTreeObserver;
21188    }
21189
21190    /**
21191     * <p>Finds the topmost view in the current view hierarchy.</p>
21192     *
21193     * @return the topmost view containing this view
21194     */
21195    public View getRootView() {
21196        if (mAttachInfo != null) {
21197            final View v = mAttachInfo.mRootView;
21198            if (v != null) {
21199                return v;
21200            }
21201        }
21202
21203        View parent = this;
21204
21205        while (parent.mParent != null && parent.mParent instanceof View) {
21206            parent = (View) parent.mParent;
21207        }
21208
21209        return parent;
21210    }
21211
21212    /**
21213     * Transforms a motion event from view-local coordinates to on-screen
21214     * coordinates.
21215     *
21216     * @param ev the view-local motion event
21217     * @return false if the transformation could not be applied
21218     * @hide
21219     */
21220    public boolean toGlobalMotionEvent(MotionEvent ev) {
21221        final AttachInfo info = mAttachInfo;
21222        if (info == null) {
21223            return false;
21224        }
21225
21226        final Matrix m = info.mTmpMatrix;
21227        m.set(Matrix.IDENTITY_MATRIX);
21228        transformMatrixToGlobal(m);
21229        ev.transform(m);
21230        return true;
21231    }
21232
21233    /**
21234     * Transforms a motion event from on-screen coordinates to view-local
21235     * coordinates.
21236     *
21237     * @param ev the on-screen motion event
21238     * @return false if the transformation could not be applied
21239     * @hide
21240     */
21241    public boolean toLocalMotionEvent(MotionEvent ev) {
21242        final AttachInfo info = mAttachInfo;
21243        if (info == null) {
21244            return false;
21245        }
21246
21247        final Matrix m = info.mTmpMatrix;
21248        m.set(Matrix.IDENTITY_MATRIX);
21249        transformMatrixToLocal(m);
21250        ev.transform(m);
21251        return true;
21252    }
21253
21254    /**
21255     * Modifies the input matrix such that it maps view-local coordinates to
21256     * on-screen coordinates.
21257     *
21258     * @param m input matrix to modify
21259     * @hide
21260     */
21261    public void transformMatrixToGlobal(Matrix m) {
21262        final ViewParent parent = mParent;
21263        if (parent instanceof View) {
21264            final View vp = (View) parent;
21265            vp.transformMatrixToGlobal(m);
21266            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
21267        } else if (parent instanceof ViewRootImpl) {
21268            final ViewRootImpl vr = (ViewRootImpl) parent;
21269            vr.transformMatrixToGlobal(m);
21270            m.preTranslate(0, -vr.mCurScrollY);
21271        }
21272
21273        m.preTranslate(mLeft, mTop);
21274
21275        if (!hasIdentityMatrix()) {
21276            m.preConcat(getMatrix());
21277        }
21278    }
21279
21280    /**
21281     * Modifies the input matrix such that it maps on-screen coordinates to
21282     * view-local coordinates.
21283     *
21284     * @param m input matrix to modify
21285     * @hide
21286     */
21287    public void transformMatrixToLocal(Matrix m) {
21288        final ViewParent parent = mParent;
21289        if (parent instanceof View) {
21290            final View vp = (View) parent;
21291            vp.transformMatrixToLocal(m);
21292            m.postTranslate(vp.mScrollX, vp.mScrollY);
21293        } else if (parent instanceof ViewRootImpl) {
21294            final ViewRootImpl vr = (ViewRootImpl) parent;
21295            vr.transformMatrixToLocal(m);
21296            m.postTranslate(0, vr.mCurScrollY);
21297        }
21298
21299        m.postTranslate(-mLeft, -mTop);
21300
21301        if (!hasIdentityMatrix()) {
21302            m.postConcat(getInverseMatrix());
21303        }
21304    }
21305
21306    /**
21307     * @hide
21308     */
21309    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
21310            @ViewDebug.IntToString(from = 0, to = "x"),
21311            @ViewDebug.IntToString(from = 1, to = "y")
21312    })
21313    public int[] getLocationOnScreen() {
21314        int[] location = new int[2];
21315        getLocationOnScreen(location);
21316        return location;
21317    }
21318
21319    /**
21320     * <p>Computes the coordinates of this view on the screen. The argument
21321     * must be an array of two integers. After the method returns, the array
21322     * contains the x and y location in that order.</p>
21323     *
21324     * @param outLocation an array of two integers in which to hold the coordinates
21325     */
21326    public void getLocationOnScreen(@Size(2) int[] outLocation) {
21327        getLocationInWindow(outLocation);
21328
21329        final AttachInfo info = mAttachInfo;
21330        if (info != null) {
21331            outLocation[0] += info.mWindowLeft;
21332            outLocation[1] += info.mWindowTop;
21333        }
21334    }
21335
21336    /**
21337     * <p>Computes the coordinates of this view in its window. The argument
21338     * must be an array of two integers. After the method returns, the array
21339     * contains the x and y location in that order.</p>
21340     *
21341     * @param outLocation an array of two integers in which to hold the coordinates
21342     */
21343    public void getLocationInWindow(@Size(2) int[] outLocation) {
21344        if (outLocation == null || outLocation.length < 2) {
21345            throw new IllegalArgumentException("outLocation must be an array of two integers");
21346        }
21347
21348        outLocation[0] = 0;
21349        outLocation[1] = 0;
21350
21351        transformFromViewToWindowSpace(outLocation);
21352    }
21353
21354    /** @hide */
21355    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21356        if (inOutLocation == null || inOutLocation.length < 2) {
21357            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21358        }
21359
21360        if (mAttachInfo == null) {
21361            // When the view is not attached to a window, this method does not make sense
21362            inOutLocation[0] = inOutLocation[1] = 0;
21363            return;
21364        }
21365
21366        float position[] = mAttachInfo.mTmpTransformLocation;
21367        position[0] = inOutLocation[0];
21368        position[1] = inOutLocation[1];
21369
21370        if (!hasIdentityMatrix()) {
21371            getMatrix().mapPoints(position);
21372        }
21373
21374        position[0] += mLeft;
21375        position[1] += mTop;
21376
21377        ViewParent viewParent = mParent;
21378        while (viewParent instanceof View) {
21379            final View view = (View) viewParent;
21380
21381            position[0] -= view.mScrollX;
21382            position[1] -= view.mScrollY;
21383
21384            if (!view.hasIdentityMatrix()) {
21385                view.getMatrix().mapPoints(position);
21386            }
21387
21388            position[0] += view.mLeft;
21389            position[1] += view.mTop;
21390
21391            viewParent = view.mParent;
21392         }
21393
21394        if (viewParent instanceof ViewRootImpl) {
21395            // *cough*
21396            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21397            position[1] -= vr.mCurScrollY;
21398        }
21399
21400        inOutLocation[0] = Math.round(position[0]);
21401        inOutLocation[1] = Math.round(position[1]);
21402    }
21403
21404    /**
21405     * @param id the id of the view to be found
21406     * @return the view of the specified id, null if cannot be found
21407     * @hide
21408     */
21409    protected <T extends View> T findViewTraversal(@IdRes int id) {
21410        if (id == mID) {
21411            return (T) this;
21412        }
21413        return null;
21414    }
21415
21416    /**
21417     * @param tag the tag of the view to be found
21418     * @return the view of specified tag, null if cannot be found
21419     * @hide
21420     */
21421    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21422        if (tag != null && tag.equals(mTag)) {
21423            return (T) this;
21424        }
21425        return null;
21426    }
21427
21428    /**
21429     * @param predicate The predicate to evaluate.
21430     * @param childToSkip If not null, ignores this child during the recursive traversal.
21431     * @return The first view that matches the predicate or null.
21432     * @hide
21433     */
21434    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21435            View childToSkip) {
21436        if (predicate.test(this)) {
21437            return (T) this;
21438        }
21439        return null;
21440    }
21441
21442    /**
21443     * Finds the first descendant view with the given ID, the view itself if
21444     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21445     * (< 0) or there is no matching view in the hierarchy.
21446     * <p>
21447     * <strong>Note:</strong> In most cases -- depending on compiler support --
21448     * the resulting view is automatically cast to the target class type. If
21449     * the target class type is unconstrained, an explicit cast may be
21450     * necessary.
21451     *
21452     * @param id the ID to search for
21453     * @return a view with given ID if found, or {@code null} otherwise
21454     * @see View#findViewById(int)
21455     */
21456    @Nullable
21457    public final <T extends View> T findViewById(@IdRes int id) {
21458        if (id == NO_ID) {
21459            return null;
21460        }
21461        return findViewTraversal(id);
21462    }
21463
21464    /**
21465     * Finds a view by its unuque and stable accessibility id.
21466     *
21467     * @param accessibilityId The searched accessibility id.
21468     * @return The found view.
21469     */
21470    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
21471        if (accessibilityId < 0) {
21472            return null;
21473        }
21474        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21475        if (view != null) {
21476            return view.includeForAccessibility() ? view : null;
21477        }
21478        return null;
21479    }
21480
21481    /**
21482     * Performs the traversal to find a view by its unuque and stable accessibility id.
21483     *
21484     * <strong>Note:</strong>This method does not stop at the root namespace
21485     * boundary since the user can touch the screen at an arbitrary location
21486     * potentially crossing the root namespace bounday which will send an
21487     * accessibility event to accessibility services and they should be able
21488     * to obtain the event source. Also accessibility ids are guaranteed to be
21489     * unique in the window.
21490     *
21491     * @param accessibilityId The accessibility id.
21492     * @return The found view.
21493     * @hide
21494     */
21495    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21496        if (getAccessibilityViewId() == accessibilityId) {
21497            return (T) this;
21498        }
21499        return null;
21500    }
21501
21502    /**
21503     * Look for a child view with the given tag.  If this view has the given
21504     * tag, return this view.
21505     *
21506     * @param tag The tag to search for, using "tag.equals(getTag())".
21507     * @return The View that has the given tag in the hierarchy or null
21508     */
21509    public final <T extends View> T findViewWithTag(Object tag) {
21510        if (tag == null) {
21511            return null;
21512        }
21513        return findViewWithTagTraversal(tag);
21514    }
21515
21516    /**
21517     * Look for a child view that matches the specified predicate.
21518     * If this view matches the predicate, return this view.
21519     *
21520     * @param predicate The predicate to evaluate.
21521     * @return The first view that matches the predicate or null.
21522     * @hide
21523     */
21524    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21525        return findViewByPredicateTraversal(predicate, null);
21526    }
21527
21528    /**
21529     * Look for a child view that matches the specified predicate,
21530     * starting with the specified view and its descendents and then
21531     * recusively searching the ancestors and siblings of that view
21532     * until this view is reached.
21533     *
21534     * This method is useful in cases where the predicate does not match
21535     * a single unique view (perhaps multiple views use the same id)
21536     * and we are trying to find the view that is "closest" in scope to the
21537     * starting view.
21538     *
21539     * @param start The view to start from.
21540     * @param predicate The predicate to evaluate.
21541     * @return The first view that matches the predicate or null.
21542     * @hide
21543     */
21544    public final <T extends View> T findViewByPredicateInsideOut(
21545            View start, Predicate<View> predicate) {
21546        View childToSkip = null;
21547        for (;;) {
21548            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21549            if (view != null || start == this) {
21550                return view;
21551            }
21552
21553            ViewParent parent = start.getParent();
21554            if (parent == null || !(parent instanceof View)) {
21555                return null;
21556            }
21557
21558            childToSkip = start;
21559            start = (View) parent;
21560        }
21561    }
21562
21563    /**
21564     * Sets the identifier for this view. The identifier does not have to be
21565     * unique in this view's hierarchy. The identifier should be a positive
21566     * number.
21567     *
21568     * @see #NO_ID
21569     * @see #getId()
21570     * @see #findViewById(int)
21571     *
21572     * @param id a number used to identify the view
21573     *
21574     * @attr ref android.R.styleable#View_id
21575     */
21576    public void setId(@IdRes int id) {
21577        mID = id;
21578        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21579            mID = generateViewId();
21580        }
21581    }
21582
21583    /**
21584     * {@hide}
21585     *
21586     * @param isRoot true if the view belongs to the root namespace, false
21587     *        otherwise
21588     */
21589    public void setIsRootNamespace(boolean isRoot) {
21590        if (isRoot) {
21591            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21592        } else {
21593            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21594        }
21595    }
21596
21597    /**
21598     * {@hide}
21599     *
21600     * @return true if the view belongs to the root namespace, false otherwise
21601     */
21602    public boolean isRootNamespace() {
21603        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21604    }
21605
21606    /**
21607     * Returns this view's identifier.
21608     *
21609     * @return a positive integer used to identify the view or {@link #NO_ID}
21610     *         if the view has no ID
21611     *
21612     * @see #setId(int)
21613     * @see #findViewById(int)
21614     * @attr ref android.R.styleable#View_id
21615     */
21616    @IdRes
21617    @ViewDebug.CapturedViewProperty
21618    public int getId() {
21619        return mID;
21620    }
21621
21622    /**
21623     * Returns this view's tag.
21624     *
21625     * @return the Object stored in this view as a tag, or {@code null} if not
21626     *         set
21627     *
21628     * @see #setTag(Object)
21629     * @see #getTag(int)
21630     */
21631    @ViewDebug.ExportedProperty
21632    public Object getTag() {
21633        return mTag;
21634    }
21635
21636    /**
21637     * Sets the tag associated with this view. A tag can be used to mark
21638     * a view in its hierarchy and does not have to be unique within the
21639     * hierarchy. Tags can also be used to store data within a view without
21640     * resorting to another data structure.
21641     *
21642     * @param tag an Object to tag the view with
21643     *
21644     * @see #getTag()
21645     * @see #setTag(int, Object)
21646     */
21647    public void setTag(final Object tag) {
21648        mTag = tag;
21649    }
21650
21651    /**
21652     * Returns the tag associated with this view and the specified key.
21653     *
21654     * @param key The key identifying the tag
21655     *
21656     * @return the Object stored in this view as a tag, or {@code null} if not
21657     *         set
21658     *
21659     * @see #setTag(int, Object)
21660     * @see #getTag()
21661     */
21662    public Object getTag(int key) {
21663        if (mKeyedTags != null) return mKeyedTags.get(key);
21664        return null;
21665    }
21666
21667    /**
21668     * Sets a tag associated with this view and a key. A tag can be used
21669     * to mark a view in its hierarchy and does not have to be unique within
21670     * the hierarchy. Tags can also be used to store data within a view
21671     * without resorting to another data structure.
21672     *
21673     * The specified key should be an id declared in the resources of the
21674     * application to ensure it is unique (see the <a
21675     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21676     * Keys identified as belonging to
21677     * the Android framework or not associated with any package will cause
21678     * an {@link IllegalArgumentException} to be thrown.
21679     *
21680     * @param key The key identifying the tag
21681     * @param tag An Object to tag the view with
21682     *
21683     * @throws IllegalArgumentException If they specified key is not valid
21684     *
21685     * @see #setTag(Object)
21686     * @see #getTag(int)
21687     */
21688    public void setTag(int key, final Object tag) {
21689        // If the package id is 0x00 or 0x01, it's either an undefined package
21690        // or a framework id
21691        if ((key >>> 24) < 2) {
21692            throw new IllegalArgumentException("The key must be an application-specific "
21693                    + "resource id.");
21694        }
21695
21696        setKeyedTag(key, tag);
21697    }
21698
21699    /**
21700     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21701     * framework id.
21702     *
21703     * @hide
21704     */
21705    public void setTagInternal(int key, Object tag) {
21706        if ((key >>> 24) != 0x1) {
21707            throw new IllegalArgumentException("The key must be a framework-specific "
21708                    + "resource id.");
21709        }
21710
21711        setKeyedTag(key, tag);
21712    }
21713
21714    private void setKeyedTag(int key, Object tag) {
21715        if (mKeyedTags == null) {
21716            mKeyedTags = new SparseArray<Object>(2);
21717        }
21718
21719        mKeyedTags.put(key, tag);
21720    }
21721
21722    /**
21723     * Prints information about this view in the log output, with the tag
21724     * {@link #VIEW_LOG_TAG}.
21725     *
21726     * @hide
21727     */
21728    public void debug() {
21729        debug(0);
21730    }
21731
21732    /**
21733     * Prints information about this view in the log output, with the tag
21734     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21735     * indentation defined by the <code>depth</code>.
21736     *
21737     * @param depth the indentation level
21738     *
21739     * @hide
21740     */
21741    protected void debug(int depth) {
21742        String output = debugIndent(depth - 1);
21743
21744        output += "+ " + this;
21745        int id = getId();
21746        if (id != -1) {
21747            output += " (id=" + id + ")";
21748        }
21749        Object tag = getTag();
21750        if (tag != null) {
21751            output += " (tag=" + tag + ")";
21752        }
21753        Log.d(VIEW_LOG_TAG, output);
21754
21755        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21756            output = debugIndent(depth) + " FOCUSED";
21757            Log.d(VIEW_LOG_TAG, output);
21758        }
21759
21760        output = debugIndent(depth);
21761        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21762                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21763                + "} ";
21764        Log.d(VIEW_LOG_TAG, output);
21765
21766        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21767                || mPaddingBottom != 0) {
21768            output = debugIndent(depth);
21769            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21770                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21771            Log.d(VIEW_LOG_TAG, output);
21772        }
21773
21774        output = debugIndent(depth);
21775        output += "mMeasureWidth=" + mMeasuredWidth +
21776                " mMeasureHeight=" + mMeasuredHeight;
21777        Log.d(VIEW_LOG_TAG, output);
21778
21779        output = debugIndent(depth);
21780        if (mLayoutParams == null) {
21781            output += "BAD! no layout params";
21782        } else {
21783            output = mLayoutParams.debug(output);
21784        }
21785        Log.d(VIEW_LOG_TAG, output);
21786
21787        output = debugIndent(depth);
21788        output += "flags={";
21789        output += View.printFlags(mViewFlags);
21790        output += "}";
21791        Log.d(VIEW_LOG_TAG, output);
21792
21793        output = debugIndent(depth);
21794        output += "privateFlags={";
21795        output += View.printPrivateFlags(mPrivateFlags);
21796        output += "}";
21797        Log.d(VIEW_LOG_TAG, output);
21798    }
21799
21800    /**
21801     * Creates a string of whitespaces used for indentation.
21802     *
21803     * @param depth the indentation level
21804     * @return a String containing (depth * 2 + 3) * 2 white spaces
21805     *
21806     * @hide
21807     */
21808    protected static String debugIndent(int depth) {
21809        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21810        for (int i = 0; i < (depth * 2) + 3; i++) {
21811            spaces.append(' ').append(' ');
21812        }
21813        return spaces.toString();
21814    }
21815
21816    /**
21817     * <p>Return the offset of the widget's text baseline from the widget's top
21818     * boundary. If this widget does not support baseline alignment, this
21819     * method returns -1. </p>
21820     *
21821     * @return the offset of the baseline within the widget's bounds or -1
21822     *         if baseline alignment is not supported
21823     */
21824    @ViewDebug.ExportedProperty(category = "layout")
21825    public int getBaseline() {
21826        return -1;
21827    }
21828
21829    /**
21830     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21831     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21832     * a layout pass.
21833     *
21834     * @return whether the view hierarchy is currently undergoing a layout pass
21835     */
21836    public boolean isInLayout() {
21837        ViewRootImpl viewRoot = getViewRootImpl();
21838        return (viewRoot != null && viewRoot.isInLayout());
21839    }
21840
21841    /**
21842     * Call this when something has changed which has invalidated the
21843     * layout of this view. This will schedule a layout pass of the view
21844     * tree. This should not be called while the view hierarchy is currently in a layout
21845     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21846     * end of the current layout pass (and then layout will run again) or after the current
21847     * frame is drawn and the next layout occurs.
21848     *
21849     * <p>Subclasses which override this method should call the superclass method to
21850     * handle possible request-during-layout errors correctly.</p>
21851     */
21852    @CallSuper
21853    public void requestLayout() {
21854        if (mMeasureCache != null) mMeasureCache.clear();
21855
21856        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21857            // Only trigger request-during-layout logic if this is the view requesting it,
21858            // not the views in its parent hierarchy
21859            ViewRootImpl viewRoot = getViewRootImpl();
21860            if (viewRoot != null && viewRoot.isInLayout()) {
21861                if (!viewRoot.requestLayoutDuringLayout(this)) {
21862                    return;
21863                }
21864            }
21865            mAttachInfo.mViewRequestingLayout = this;
21866        }
21867
21868        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21869        mPrivateFlags |= PFLAG_INVALIDATED;
21870
21871        if (mParent != null && !mParent.isLayoutRequested()) {
21872            mParent.requestLayout();
21873        }
21874        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21875            mAttachInfo.mViewRequestingLayout = null;
21876        }
21877    }
21878
21879    /**
21880     * Forces this view to be laid out during the next layout pass.
21881     * This method does not call requestLayout() or forceLayout()
21882     * on the parent.
21883     */
21884    public void forceLayout() {
21885        if (mMeasureCache != null) mMeasureCache.clear();
21886
21887        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21888        mPrivateFlags |= PFLAG_INVALIDATED;
21889    }
21890
21891    /**
21892     * <p>
21893     * This is called to find out how big a view should be. The parent
21894     * supplies constraint information in the width and height parameters.
21895     * </p>
21896     *
21897     * <p>
21898     * The actual measurement work of a view is performed in
21899     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21900     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21901     * </p>
21902     *
21903     *
21904     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21905     *        parent
21906     * @param heightMeasureSpec Vertical space requirements as imposed by the
21907     *        parent
21908     *
21909     * @see #onMeasure(int, int)
21910     */
21911    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21912        boolean optical = isLayoutModeOptical(this);
21913        if (optical != isLayoutModeOptical(mParent)) {
21914            Insets insets = getOpticalInsets();
21915            int oWidth  = insets.left + insets.right;
21916            int oHeight = insets.top  + insets.bottom;
21917            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21918            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21919        }
21920
21921        // Suppress sign extension for the low bytes
21922        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21923        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21924
21925        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21926
21927        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21928        // already measured as the correct size. In API 23 and below, this
21929        // extra pass is required to make LinearLayout re-distribute weight.
21930        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21931                || heightMeasureSpec != mOldHeightMeasureSpec;
21932        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21933                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21934        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21935                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21936        final boolean needsLayout = specChanged
21937                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21938
21939        if (forceLayout || needsLayout) {
21940            // first clears the measured dimension flag
21941            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21942
21943            resolveRtlPropertiesIfNeeded();
21944
21945            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21946            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21947                // measure ourselves, this should set the measured dimension flag back
21948                onMeasure(widthMeasureSpec, heightMeasureSpec);
21949                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21950            } else {
21951                long value = mMeasureCache.valueAt(cacheIndex);
21952                // Casting a long to int drops the high 32 bits, no mask needed
21953                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21954                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21955            }
21956
21957            // flag not set, setMeasuredDimension() was not invoked, we raise
21958            // an exception to warn the developer
21959            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21960                throw new IllegalStateException("View with id " + getId() + ": "
21961                        + getClass().getName() + "#onMeasure() did not set the"
21962                        + " measured dimension by calling"
21963                        + " setMeasuredDimension()");
21964            }
21965
21966            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21967        }
21968
21969        mOldWidthMeasureSpec = widthMeasureSpec;
21970        mOldHeightMeasureSpec = heightMeasureSpec;
21971
21972        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21973                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21974    }
21975
21976    /**
21977     * <p>
21978     * Measure the view and its content to determine the measured width and the
21979     * measured height. This method is invoked by {@link #measure(int, int)} and
21980     * should be overridden by subclasses to provide accurate and efficient
21981     * measurement of their contents.
21982     * </p>
21983     *
21984     * <p>
21985     * <strong>CONTRACT:</strong> When overriding this method, you
21986     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21987     * measured width and height of this view. Failure to do so will trigger an
21988     * <code>IllegalStateException</code>, thrown by
21989     * {@link #measure(int, int)}. Calling the superclass'
21990     * {@link #onMeasure(int, int)} is a valid use.
21991     * </p>
21992     *
21993     * <p>
21994     * The base class implementation of measure defaults to the background size,
21995     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21996     * override {@link #onMeasure(int, int)} to provide better measurements of
21997     * their content.
21998     * </p>
21999     *
22000     * <p>
22001     * If this method is overridden, it is the subclass's responsibility to make
22002     * sure the measured height and width are at least the view's minimum height
22003     * and width ({@link #getSuggestedMinimumHeight()} and
22004     * {@link #getSuggestedMinimumWidth()}).
22005     * </p>
22006     *
22007     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
22008     *                         The requirements are encoded with
22009     *                         {@link android.view.View.MeasureSpec}.
22010     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
22011     *                         The requirements are encoded with
22012     *                         {@link android.view.View.MeasureSpec}.
22013     *
22014     * @see #getMeasuredWidth()
22015     * @see #getMeasuredHeight()
22016     * @see #setMeasuredDimension(int, int)
22017     * @see #getSuggestedMinimumHeight()
22018     * @see #getSuggestedMinimumWidth()
22019     * @see android.view.View.MeasureSpec#getMode(int)
22020     * @see android.view.View.MeasureSpec#getSize(int)
22021     */
22022    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22023        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
22024                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
22025    }
22026
22027    /**
22028     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
22029     * measured width and measured height. Failing to do so will trigger an
22030     * exception at measurement time.</p>
22031     *
22032     * @param measuredWidth The measured width of this view.  May be a complex
22033     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22034     * {@link #MEASURED_STATE_TOO_SMALL}.
22035     * @param measuredHeight The measured height of this view.  May be a complex
22036     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22037     * {@link #MEASURED_STATE_TOO_SMALL}.
22038     */
22039    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
22040        boolean optical = isLayoutModeOptical(this);
22041        if (optical != isLayoutModeOptical(mParent)) {
22042            Insets insets = getOpticalInsets();
22043            int opticalWidth  = insets.left + insets.right;
22044            int opticalHeight = insets.top  + insets.bottom;
22045
22046            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
22047            measuredHeight += optical ? opticalHeight : -opticalHeight;
22048        }
22049        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
22050    }
22051
22052    /**
22053     * Sets the measured dimension without extra processing for things like optical bounds.
22054     * Useful for reapplying consistent values that have already been cooked with adjustments
22055     * for optical bounds, etc. such as those from the measurement cache.
22056     *
22057     * @param measuredWidth The measured width of this view.  May be a complex
22058     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22059     * {@link #MEASURED_STATE_TOO_SMALL}.
22060     * @param measuredHeight The measured height of this view.  May be a complex
22061     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22062     * {@link #MEASURED_STATE_TOO_SMALL}.
22063     */
22064    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
22065        mMeasuredWidth = measuredWidth;
22066        mMeasuredHeight = measuredHeight;
22067
22068        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
22069    }
22070
22071    /**
22072     * Merge two states as returned by {@link #getMeasuredState()}.
22073     * @param curState The current state as returned from a view or the result
22074     * of combining multiple views.
22075     * @param newState The new view state to combine.
22076     * @return Returns a new integer reflecting the combination of the two
22077     * states.
22078     */
22079    public static int combineMeasuredStates(int curState, int newState) {
22080        return curState | newState;
22081    }
22082
22083    /**
22084     * Version of {@link #resolveSizeAndState(int, int, int)}
22085     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
22086     */
22087    public static int resolveSize(int size, int measureSpec) {
22088        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
22089    }
22090
22091    /**
22092     * Utility to reconcile a desired size and state, with constraints imposed
22093     * by a MeasureSpec. Will take the desired size, unless a different size
22094     * is imposed by the constraints. The returned value is a compound integer,
22095     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
22096     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
22097     * resulting size is smaller than the size the view wants to be.
22098     *
22099     * @param size How big the view wants to be.
22100     * @param measureSpec Constraints imposed by the parent.
22101     * @param childMeasuredState Size information bit mask for the view's
22102     *                           children.
22103     * @return Size information bit mask as defined by
22104     *         {@link #MEASURED_SIZE_MASK} and
22105     *         {@link #MEASURED_STATE_TOO_SMALL}.
22106     */
22107    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
22108        final int specMode = MeasureSpec.getMode(measureSpec);
22109        final int specSize = MeasureSpec.getSize(measureSpec);
22110        final int result;
22111        switch (specMode) {
22112            case MeasureSpec.AT_MOST:
22113                if (specSize < size) {
22114                    result = specSize | MEASURED_STATE_TOO_SMALL;
22115                } else {
22116                    result = size;
22117                }
22118                break;
22119            case MeasureSpec.EXACTLY:
22120                result = specSize;
22121                break;
22122            case MeasureSpec.UNSPECIFIED:
22123            default:
22124                result = size;
22125        }
22126        return result | (childMeasuredState & MEASURED_STATE_MASK);
22127    }
22128
22129    /**
22130     * Utility to return a default size. Uses the supplied size if the
22131     * MeasureSpec imposed no constraints. Will get larger if allowed
22132     * by the MeasureSpec.
22133     *
22134     * @param size Default size for this view
22135     * @param measureSpec Constraints imposed by the parent
22136     * @return The size this view should be.
22137     */
22138    public static int getDefaultSize(int size, int measureSpec) {
22139        int result = size;
22140        int specMode = MeasureSpec.getMode(measureSpec);
22141        int specSize = MeasureSpec.getSize(measureSpec);
22142
22143        switch (specMode) {
22144        case MeasureSpec.UNSPECIFIED:
22145            result = size;
22146            break;
22147        case MeasureSpec.AT_MOST:
22148        case MeasureSpec.EXACTLY:
22149            result = specSize;
22150            break;
22151        }
22152        return result;
22153    }
22154
22155    /**
22156     * Returns the suggested minimum height that the view should use. This
22157     * returns the maximum of the view's minimum height
22158     * and the background's minimum height
22159     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
22160     * <p>
22161     * When being used in {@link #onMeasure(int, int)}, the caller should still
22162     * ensure the returned height is within the requirements of the parent.
22163     *
22164     * @return The suggested minimum height of the view.
22165     */
22166    protected int getSuggestedMinimumHeight() {
22167        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
22168
22169    }
22170
22171    /**
22172     * Returns the suggested minimum width that the view should use. This
22173     * returns the maximum of the view's minimum width
22174     * and the background's minimum width
22175     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
22176     * <p>
22177     * When being used in {@link #onMeasure(int, int)}, the caller should still
22178     * ensure the returned width is within the requirements of the parent.
22179     *
22180     * @return The suggested minimum width of the view.
22181     */
22182    protected int getSuggestedMinimumWidth() {
22183        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
22184    }
22185
22186    /**
22187     * Returns the minimum height of the view.
22188     *
22189     * @return the minimum height the view will try to be, in pixels
22190     *
22191     * @see #setMinimumHeight(int)
22192     *
22193     * @attr ref android.R.styleable#View_minHeight
22194     */
22195    public int getMinimumHeight() {
22196        return mMinHeight;
22197    }
22198
22199    /**
22200     * Sets the minimum height of the view. It is not guaranteed the view will
22201     * be able to achieve this minimum height (for example, if its parent layout
22202     * constrains it with less available height).
22203     *
22204     * @param minHeight The minimum height the view will try to be, in pixels
22205     *
22206     * @see #getMinimumHeight()
22207     *
22208     * @attr ref android.R.styleable#View_minHeight
22209     */
22210    @RemotableViewMethod
22211    public void setMinimumHeight(int minHeight) {
22212        mMinHeight = minHeight;
22213        requestLayout();
22214    }
22215
22216    /**
22217     * Returns the minimum width of the view.
22218     *
22219     * @return the minimum width the view will try to be, in pixels
22220     *
22221     * @see #setMinimumWidth(int)
22222     *
22223     * @attr ref android.R.styleable#View_minWidth
22224     */
22225    public int getMinimumWidth() {
22226        return mMinWidth;
22227    }
22228
22229    /**
22230     * Sets the minimum width of the view. It is not guaranteed the view will
22231     * be able to achieve this minimum width (for example, if its parent layout
22232     * constrains it with less available width).
22233     *
22234     * @param minWidth The minimum width the view will try to be, in pixels
22235     *
22236     * @see #getMinimumWidth()
22237     *
22238     * @attr ref android.R.styleable#View_minWidth
22239     */
22240    public void setMinimumWidth(int minWidth) {
22241        mMinWidth = minWidth;
22242        requestLayout();
22243
22244    }
22245
22246    /**
22247     * Get the animation currently associated with this view.
22248     *
22249     * @return The animation that is currently playing or
22250     *         scheduled to play for this view.
22251     */
22252    public Animation getAnimation() {
22253        return mCurrentAnimation;
22254    }
22255
22256    /**
22257     * Start the specified animation now.
22258     *
22259     * @param animation the animation to start now
22260     */
22261    public void startAnimation(Animation animation) {
22262        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
22263        setAnimation(animation);
22264        invalidateParentCaches();
22265        invalidate(true);
22266    }
22267
22268    /**
22269     * Cancels any animations for this view.
22270     */
22271    public void clearAnimation() {
22272        if (mCurrentAnimation != null) {
22273            mCurrentAnimation.detach();
22274        }
22275        mCurrentAnimation = null;
22276        invalidateParentIfNeeded();
22277    }
22278
22279    /**
22280     * Sets the next animation to play for this view.
22281     * If you want the animation to play immediately, use
22282     * {@link #startAnimation(android.view.animation.Animation)} instead.
22283     * This method provides allows fine-grained
22284     * control over the start time and invalidation, but you
22285     * must make sure that 1) the animation has a start time set, and
22286     * 2) the view's parent (which controls animations on its children)
22287     * will be invalidated when the animation is supposed to
22288     * start.
22289     *
22290     * @param animation The next animation, or null.
22291     */
22292    public void setAnimation(Animation animation) {
22293        mCurrentAnimation = animation;
22294
22295        if (animation != null) {
22296            // If the screen is off assume the animation start time is now instead of
22297            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
22298            // would cause the animation to start when the screen turns back on
22299            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
22300                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
22301                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
22302            }
22303            animation.reset();
22304        }
22305    }
22306
22307    /**
22308     * Invoked by a parent ViewGroup to notify the start of the animation
22309     * currently associated with this view. If you override this method,
22310     * always call super.onAnimationStart();
22311     *
22312     * @see #setAnimation(android.view.animation.Animation)
22313     * @see #getAnimation()
22314     */
22315    @CallSuper
22316    protected void onAnimationStart() {
22317        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22318    }
22319
22320    /**
22321     * Invoked by a parent ViewGroup to notify the end of the animation
22322     * currently associated with this view. If you override this method,
22323     * always call super.onAnimationEnd();
22324     *
22325     * @see #setAnimation(android.view.animation.Animation)
22326     * @see #getAnimation()
22327     */
22328    @CallSuper
22329    protected void onAnimationEnd() {
22330        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22331    }
22332
22333    /**
22334     * Invoked if there is a Transform that involves alpha. Subclass that can
22335     * draw themselves with the specified alpha should return true, and then
22336     * respect that alpha when their onDraw() is called. If this returns false
22337     * then the view may be redirected to draw into an offscreen buffer to
22338     * fulfill the request, which will look fine, but may be slower than if the
22339     * subclass handles it internally. The default implementation returns false.
22340     *
22341     * @param alpha The alpha (0..255) to apply to the view's drawing
22342     * @return true if the view can draw with the specified alpha.
22343     */
22344    protected boolean onSetAlpha(int alpha) {
22345        return false;
22346    }
22347
22348    /**
22349     * This is used by the RootView to perform an optimization when
22350     * the view hierarchy contains one or several SurfaceView.
22351     * SurfaceView is always considered transparent, but its children are not,
22352     * therefore all View objects remove themselves from the global transparent
22353     * region (passed as a parameter to this function).
22354     *
22355     * @param region The transparent region for this ViewAncestor (window).
22356     *
22357     * @return Returns true if the effective visibility of the view at this
22358     * point is opaque, regardless of the transparent region; returns false
22359     * if it is possible for underlying windows to be seen behind the view.
22360     *
22361     * {@hide}
22362     */
22363    public boolean gatherTransparentRegion(Region region) {
22364        final AttachInfo attachInfo = mAttachInfo;
22365        if (region != null && attachInfo != null) {
22366            final int pflags = mPrivateFlags;
22367            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22368                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22369                // remove it from the transparent region.
22370                final int[] location = attachInfo.mTransparentLocation;
22371                getLocationInWindow(location);
22372                // When a view has Z value, then it will be better to leave some area below the view
22373                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22374                // the bottom part needs more offset than the left, top and right parts due to the
22375                // spot light effects.
22376                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22377                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22378                        location[0] + mRight - mLeft + shadowOffset,
22379                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22380            } else {
22381                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22382                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22383                    // the background drawable's non-transparent parts from this transparent region.
22384                    applyDrawableToTransparentRegion(mBackground, region);
22385                }
22386                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22387                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22388                    // Similarly, we remove the foreground drawable's non-transparent parts.
22389                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22390                }
22391                if (mDefaultFocusHighlight != null
22392                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22393                    // Similarly, we remove the default focus highlight's non-transparent parts.
22394                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22395                }
22396            }
22397        }
22398        return true;
22399    }
22400
22401    /**
22402     * Play a sound effect for this view.
22403     *
22404     * <p>The framework will play sound effects for some built in actions, such as
22405     * clicking, but you may wish to play these effects in your widget,
22406     * for instance, for internal navigation.
22407     *
22408     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22409     * {@link #isSoundEffectsEnabled()} is true.
22410     *
22411     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22412     */
22413    public void playSoundEffect(int soundConstant) {
22414        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22415            return;
22416        }
22417        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22418    }
22419
22420    /**
22421     * BZZZTT!!1!
22422     *
22423     * <p>Provide haptic feedback to the user for this view.
22424     *
22425     * <p>The framework will provide haptic feedback for some built in actions,
22426     * such as long presses, but you may wish to provide feedback for your
22427     * own widget.
22428     *
22429     * <p>The feedback will only be performed if
22430     * {@link #isHapticFeedbackEnabled()} is true.
22431     *
22432     * @param feedbackConstant One of the constants defined in
22433     * {@link HapticFeedbackConstants}
22434     */
22435    public boolean performHapticFeedback(int feedbackConstant) {
22436        return performHapticFeedback(feedbackConstant, 0);
22437    }
22438
22439    /**
22440     * BZZZTT!!1!
22441     *
22442     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22443     *
22444     * @param feedbackConstant One of the constants defined in
22445     * {@link HapticFeedbackConstants}
22446     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22447     */
22448    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22449        if (mAttachInfo == null) {
22450            return false;
22451        }
22452        //noinspection SimplifiableIfStatement
22453        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22454                && !isHapticFeedbackEnabled()) {
22455            return false;
22456        }
22457        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22458                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22459    }
22460
22461    /**
22462     * Request that the visibility of the status bar or other screen/window
22463     * decorations be changed.
22464     *
22465     * <p>This method is used to put the over device UI into temporary modes
22466     * where the user's attention is focused more on the application content,
22467     * by dimming or hiding surrounding system affordances.  This is typically
22468     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22469     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22470     * to be placed behind the action bar (and with these flags other system
22471     * affordances) so that smooth transitions between hiding and showing them
22472     * can be done.
22473     *
22474     * <p>Two representative examples of the use of system UI visibility is
22475     * implementing a content browsing application (like a magazine reader)
22476     * and a video playing application.
22477     *
22478     * <p>The first code shows a typical implementation of a View in a content
22479     * browsing application.  In this implementation, the application goes
22480     * into a content-oriented mode by hiding the status bar and action bar,
22481     * and putting the navigation elements into lights out mode.  The user can
22482     * then interact with content while in this mode.  Such an application should
22483     * provide an easy way for the user to toggle out of the mode (such as to
22484     * check information in the status bar or access notifications).  In the
22485     * implementation here, this is done simply by tapping on the content.
22486     *
22487     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22488     *      content}
22489     *
22490     * <p>This second code sample shows a typical implementation of a View
22491     * in a video playing application.  In this situation, while the video is
22492     * playing the application would like to go into a complete full-screen mode,
22493     * to use as much of the display as possible for the video.  When in this state
22494     * the user can not interact with the application; the system intercepts
22495     * touching on the screen to pop the UI out of full screen mode.  See
22496     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22497     *
22498     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22499     *      content}
22500     *
22501     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22502     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22503     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22504     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22505     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22506     */
22507    public void setSystemUiVisibility(int visibility) {
22508        if (visibility != mSystemUiVisibility) {
22509            mSystemUiVisibility = visibility;
22510            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22511                mParent.recomputeViewAttributes(this);
22512            }
22513        }
22514    }
22515
22516    /**
22517     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22518     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22519     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22520     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22521     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22522     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22523     */
22524    public int getSystemUiVisibility() {
22525        return mSystemUiVisibility;
22526    }
22527
22528    /**
22529     * Returns the current system UI visibility that is currently set for
22530     * the entire window.  This is the combination of the
22531     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22532     * views in the window.
22533     */
22534    public int getWindowSystemUiVisibility() {
22535        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22536    }
22537
22538    /**
22539     * Override to find out when the window's requested system UI visibility
22540     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22541     * This is different from the callbacks received through
22542     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22543     * in that this is only telling you about the local request of the window,
22544     * not the actual values applied by the system.
22545     */
22546    public void onWindowSystemUiVisibilityChanged(int visible) {
22547    }
22548
22549    /**
22550     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22551     * the view hierarchy.
22552     */
22553    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22554        onWindowSystemUiVisibilityChanged(visible);
22555    }
22556
22557    /**
22558     * Set a listener to receive callbacks when the visibility of the system bar changes.
22559     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22560     */
22561    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22562        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22563        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22564            mParent.recomputeViewAttributes(this);
22565        }
22566    }
22567
22568    /**
22569     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22570     * the view hierarchy.
22571     */
22572    public void dispatchSystemUiVisibilityChanged(int visibility) {
22573        ListenerInfo li = mListenerInfo;
22574        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22575            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22576                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22577        }
22578    }
22579
22580    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22581        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22582        if (val != mSystemUiVisibility) {
22583            setSystemUiVisibility(val);
22584            return true;
22585        }
22586        return false;
22587    }
22588
22589    /** @hide */
22590    public void setDisabledSystemUiVisibility(int flags) {
22591        if (mAttachInfo != null) {
22592            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22593                mAttachInfo.mDisabledSystemUiVisibility = flags;
22594                if (mParent != null) {
22595                    mParent.recomputeViewAttributes(this);
22596                }
22597            }
22598        }
22599    }
22600
22601    /**
22602     * Creates an image that the system displays during the drag and drop
22603     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22604     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22605     * appearance as the given View. The default also positions the center of the drag shadow
22606     * directly under the touch point. If no View is provided (the constructor with no parameters
22607     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22608     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22609     * default is an invisible drag shadow.
22610     * <p>
22611     * You are not required to use the View you provide to the constructor as the basis of the
22612     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22613     * anything you want as the drag shadow.
22614     * </p>
22615     * <p>
22616     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22617     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22618     *  size and position of the drag shadow. It uses this data to construct a
22619     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22620     *  so that your application can draw the shadow image in the Canvas.
22621     * </p>
22622     *
22623     * <div class="special reference">
22624     * <h3>Developer Guides</h3>
22625     * <p>For a guide to implementing drag and drop features, read the
22626     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22627     * </div>
22628     */
22629    public static class DragShadowBuilder {
22630        private final WeakReference<View> mView;
22631
22632        /**
22633         * Constructs a shadow image builder based on a View. By default, the resulting drag
22634         * shadow will have the same appearance and dimensions as the View, with the touch point
22635         * over the center of the View.
22636         * @param view A View. Any View in scope can be used.
22637         */
22638        public DragShadowBuilder(View view) {
22639            mView = new WeakReference<View>(view);
22640        }
22641
22642        /**
22643         * Construct a shadow builder object with no associated View.  This
22644         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22645         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22646         * to supply the drag shadow's dimensions and appearance without
22647         * reference to any View object. If they are not overridden, then the result is an
22648         * invisible drag shadow.
22649         */
22650        public DragShadowBuilder() {
22651            mView = new WeakReference<View>(null);
22652        }
22653
22654        /**
22655         * Returns the View object that had been passed to the
22656         * {@link #View.DragShadowBuilder(View)}
22657         * constructor.  If that View parameter was {@code null} or if the
22658         * {@link #View.DragShadowBuilder()}
22659         * constructor was used to instantiate the builder object, this method will return
22660         * null.
22661         *
22662         * @return The View object associate with this builder object.
22663         */
22664        @SuppressWarnings({"JavadocReference"})
22665        final public View getView() {
22666            return mView.get();
22667        }
22668
22669        /**
22670         * Provides the metrics for the shadow image. These include the dimensions of
22671         * the shadow image, and the point within that shadow that should
22672         * be centered under the touch location while dragging.
22673         * <p>
22674         * The default implementation sets the dimensions of the shadow to be the
22675         * same as the dimensions of the View itself and centers the shadow under
22676         * the touch point.
22677         * </p>
22678         *
22679         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22680         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22681         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22682         * image.
22683         *
22684         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22685         * shadow image that should be underneath the touch point during the drag and drop
22686         * operation. Your application must set {@link android.graphics.Point#x} to the
22687         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22688         */
22689        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22690            final View view = mView.get();
22691            if (view != null) {
22692                outShadowSize.set(view.getWidth(), view.getHeight());
22693                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22694            } else {
22695                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22696            }
22697        }
22698
22699        /**
22700         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22701         * based on the dimensions it received from the
22702         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22703         *
22704         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22705         */
22706        public void onDrawShadow(Canvas canvas) {
22707            final View view = mView.get();
22708            if (view != null) {
22709                view.draw(canvas);
22710            } else {
22711                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22712            }
22713        }
22714    }
22715
22716    /**
22717     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22718     * startDragAndDrop()} for newer platform versions.
22719     */
22720    @Deprecated
22721    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22722                                   Object myLocalState, int flags) {
22723        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22724    }
22725
22726    /**
22727     * Starts a drag and drop operation. When your application calls this method, it passes a
22728     * {@link android.view.View.DragShadowBuilder} object to the system. The
22729     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22730     * to get metrics for the drag shadow, and then calls the object's
22731     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22732     * <p>
22733     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22734     *  drag events to all the View objects in your application that are currently visible. It does
22735     *  this either by calling the View object's drag listener (an implementation of
22736     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22737     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22738     *  Both are passed a {@link android.view.DragEvent} object that has a
22739     *  {@link android.view.DragEvent#getAction()} value of
22740     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22741     * </p>
22742     * <p>
22743     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22744     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22745     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22746     * to the View the user selected for dragging.
22747     * </p>
22748     * @param data A {@link android.content.ClipData} object pointing to the data to be
22749     * transferred by the drag and drop operation.
22750     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22751     * drag shadow.
22752     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22753     * drop operation. When dispatching drag events to views in the same activity this object
22754     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22755     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22756     * will return null).
22757     * <p>
22758     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22759     * to the target Views. For example, it can contain flags that differentiate between a
22760     * a copy operation and a move operation.
22761     * </p>
22762     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22763     * flags, or any combination of the following:
22764     *     <ul>
22765     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22766     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22767     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22768     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22769     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22770     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22771     *     </ul>
22772     * @return {@code true} if the method completes successfully, or
22773     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22774     * do a drag, and so no drag operation is in progress.
22775     */
22776    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22777            Object myLocalState, int flags) {
22778        if (ViewDebug.DEBUG_DRAG) {
22779            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22780        }
22781        if (mAttachInfo == null) {
22782            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22783            return false;
22784        }
22785
22786        if (data != null) {
22787            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22788        }
22789
22790        boolean okay = false;
22791
22792        Point shadowSize = new Point();
22793        Point shadowTouchPoint = new Point();
22794        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22795
22796        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22797                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22798            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22799        }
22800
22801        if (ViewDebug.DEBUG_DRAG) {
22802            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22803                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22804        }
22805        if (mAttachInfo.mDragSurface != null) {
22806            mAttachInfo.mDragSurface.release();
22807        }
22808        mAttachInfo.mDragSurface = new Surface();
22809        try {
22810            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22811                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22812            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22813                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22814            if (mAttachInfo.mDragToken != null) {
22815                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22816                try {
22817                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22818                    shadowBuilder.onDrawShadow(canvas);
22819                } finally {
22820                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22821                }
22822
22823                final ViewRootImpl root = getViewRootImpl();
22824
22825                // Cache the local state object for delivery with DragEvents
22826                root.setLocalDragState(myLocalState);
22827
22828                // repurpose 'shadowSize' for the last touch point
22829                root.getLastTouchPoint(shadowSize);
22830
22831                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22832                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22833                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22834                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22835            }
22836        } catch (Exception e) {
22837            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22838            mAttachInfo.mDragSurface.destroy();
22839            mAttachInfo.mDragSurface = null;
22840        }
22841
22842        return okay;
22843    }
22844
22845    /**
22846     * Cancels an ongoing drag and drop operation.
22847     * <p>
22848     * A {@link android.view.DragEvent} object with
22849     * {@link android.view.DragEvent#getAction()} value of
22850     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22851     * {@link android.view.DragEvent#getResult()} value of {@code false}
22852     * will be sent to every
22853     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22854     * even if they are not currently visible.
22855     * </p>
22856     * <p>
22857     * This method can be called on any View in the same window as the View on which
22858     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22859     * was called.
22860     * </p>
22861     */
22862    public final void cancelDragAndDrop() {
22863        if (ViewDebug.DEBUG_DRAG) {
22864            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22865        }
22866        if (mAttachInfo == null) {
22867            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22868            return;
22869        }
22870        if (mAttachInfo.mDragToken != null) {
22871            try {
22872                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22873            } catch (Exception e) {
22874                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22875            }
22876            mAttachInfo.mDragToken = null;
22877        } else {
22878            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22879        }
22880    }
22881
22882    /**
22883     * Updates the drag shadow for the ongoing drag and drop operation.
22884     *
22885     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22886     * new drag shadow.
22887     */
22888    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22889        if (ViewDebug.DEBUG_DRAG) {
22890            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22891        }
22892        if (mAttachInfo == null) {
22893            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22894            return;
22895        }
22896        if (mAttachInfo.mDragToken != null) {
22897            try {
22898                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22899                try {
22900                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22901                    shadowBuilder.onDrawShadow(canvas);
22902                } finally {
22903                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22904                }
22905            } catch (Exception e) {
22906                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22907            }
22908        } else {
22909            Log.e(VIEW_LOG_TAG, "No active drag");
22910        }
22911    }
22912
22913    /**
22914     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22915     * between {startX, startY} and the new cursor positon.
22916     * @param startX horizontal coordinate where the move started.
22917     * @param startY vertical coordinate where the move started.
22918     * @return whether moving was started successfully.
22919     * @hide
22920     */
22921    public final boolean startMovingTask(float startX, float startY) {
22922        if (ViewDebug.DEBUG_POSITIONING) {
22923            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22924        }
22925        try {
22926            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22927        } catch (RemoteException e) {
22928            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22929        }
22930        return false;
22931    }
22932
22933    /**
22934     * Handles drag events sent by the system following a call to
22935     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22936     * startDragAndDrop()}.
22937     *<p>
22938     * When the system calls this method, it passes a
22939     * {@link android.view.DragEvent} object. A call to
22940     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22941     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22942     * operation.
22943     * @param event The {@link android.view.DragEvent} sent by the system.
22944     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22945     * in DragEvent, indicating the type of drag event represented by this object.
22946     * @return {@code true} if the method was successful, otherwise {@code false}.
22947     * <p>
22948     *  The method should return {@code true} in response to an action type of
22949     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22950     *  operation.
22951     * </p>
22952     * <p>
22953     *  The method should also return {@code true} in response to an action type of
22954     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22955     *  {@code false} if it didn't.
22956     * </p>
22957     * <p>
22958     *  For all other events, the return value is ignored.
22959     * </p>
22960     */
22961    public boolean onDragEvent(DragEvent event) {
22962        return false;
22963    }
22964
22965    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22966    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22967        return callDragEventHandler(event);
22968    }
22969
22970    /**
22971     * Detects if this View is enabled and has a drag event listener.
22972     * If both are true, then it calls the drag event listener with the
22973     * {@link android.view.DragEvent} it received. If the drag event listener returns
22974     * {@code true}, then dispatchDragEvent() returns {@code true}.
22975     * <p>
22976     * For all other cases, the method calls the
22977     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22978     * method and returns its result.
22979     * </p>
22980     * <p>
22981     * This ensures that a drag event is always consumed, even if the View does not have a drag
22982     * event listener. However, if the View has a listener and the listener returns true, then
22983     * onDragEvent() is not called.
22984     * </p>
22985     */
22986    public boolean dispatchDragEvent(DragEvent event) {
22987        event.mEventHandlerWasCalled = true;
22988        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22989            event.mAction == DragEvent.ACTION_DROP) {
22990            // About to deliver an event with coordinates to this view. Notify that now this view
22991            // has drag focus. This will send exit/enter events as needed.
22992            getViewRootImpl().setDragFocus(this, event);
22993        }
22994        return callDragEventHandler(event);
22995    }
22996
22997    final boolean callDragEventHandler(DragEvent event) {
22998        final boolean result;
22999
23000        ListenerInfo li = mListenerInfo;
23001        //noinspection SimplifiableIfStatement
23002        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
23003                && li.mOnDragListener.onDrag(this, event)) {
23004            result = true;
23005        } else {
23006            result = onDragEvent(event);
23007        }
23008
23009        switch (event.mAction) {
23010            case DragEvent.ACTION_DRAG_ENTERED: {
23011                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
23012                refreshDrawableState();
23013            } break;
23014            case DragEvent.ACTION_DRAG_EXITED: {
23015                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
23016                refreshDrawableState();
23017            } break;
23018            case DragEvent.ACTION_DRAG_ENDED: {
23019                mPrivateFlags2 &= ~View.DRAG_MASK;
23020                refreshDrawableState();
23021            } break;
23022        }
23023
23024        return result;
23025    }
23026
23027    boolean canAcceptDrag() {
23028        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
23029    }
23030
23031    /**
23032     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
23033     * it is ever exposed at all.
23034     * @hide
23035     */
23036    public void onCloseSystemDialogs(String reason) {
23037    }
23038
23039    /**
23040     * Given a Drawable whose bounds have been set to draw into this view,
23041     * update a Region being computed for
23042     * {@link #gatherTransparentRegion(android.graphics.Region)} so
23043     * that any non-transparent parts of the Drawable are removed from the
23044     * given transparent region.
23045     *
23046     * @param dr The Drawable whose transparency is to be applied to the region.
23047     * @param region A Region holding the current transparency information,
23048     * where any parts of the region that are set are considered to be
23049     * transparent.  On return, this region will be modified to have the
23050     * transparency information reduced by the corresponding parts of the
23051     * Drawable that are not transparent.
23052     * {@hide}
23053     */
23054    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
23055        if (DBG) {
23056            Log.i("View", "Getting transparent region for: " + this);
23057        }
23058        final Region r = dr.getTransparentRegion();
23059        final Rect db = dr.getBounds();
23060        final AttachInfo attachInfo = mAttachInfo;
23061        if (r != null && attachInfo != null) {
23062            final int w = getRight()-getLeft();
23063            final int h = getBottom()-getTop();
23064            if (db.left > 0) {
23065                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
23066                r.op(0, 0, db.left, h, Region.Op.UNION);
23067            }
23068            if (db.right < w) {
23069                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
23070                r.op(db.right, 0, w, h, Region.Op.UNION);
23071            }
23072            if (db.top > 0) {
23073                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
23074                r.op(0, 0, w, db.top, Region.Op.UNION);
23075            }
23076            if (db.bottom < h) {
23077                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
23078                r.op(0, db.bottom, w, h, Region.Op.UNION);
23079            }
23080            final int[] location = attachInfo.mTransparentLocation;
23081            getLocationInWindow(location);
23082            r.translate(location[0], location[1]);
23083            region.op(r, Region.Op.INTERSECT);
23084        } else {
23085            region.op(db, Region.Op.DIFFERENCE);
23086        }
23087    }
23088
23089    private void checkForLongClick(int delayOffset, float x, float y) {
23090        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
23091            mHasPerformedLongPress = false;
23092
23093            if (mPendingCheckForLongPress == null) {
23094                mPendingCheckForLongPress = new CheckForLongPress();
23095            }
23096            mPendingCheckForLongPress.setAnchor(x, y);
23097            mPendingCheckForLongPress.rememberWindowAttachCount();
23098            mPendingCheckForLongPress.rememberPressedState();
23099            postDelayed(mPendingCheckForLongPress,
23100                    ViewConfiguration.getLongPressTimeout() - delayOffset);
23101        }
23102    }
23103
23104    /**
23105     * Inflate a view from an XML resource.  This convenience method wraps the {@link
23106     * LayoutInflater} class, which provides a full range of options for view inflation.
23107     *
23108     * @param context The Context object for your activity or application.
23109     * @param resource The resource ID to inflate
23110     * @param root A view group that will be the parent.  Used to properly inflate the
23111     * layout_* parameters.
23112     * @see LayoutInflater
23113     */
23114    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
23115        LayoutInflater factory = LayoutInflater.from(context);
23116        return factory.inflate(resource, root);
23117    }
23118
23119    /**
23120     * Scroll the view with standard behavior for scrolling beyond the normal
23121     * content boundaries. Views that call this method should override
23122     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
23123     * results of an over-scroll operation.
23124     *
23125     * Views can use this method to handle any touch or fling-based scrolling.
23126     *
23127     * @param deltaX Change in X in pixels
23128     * @param deltaY Change in Y in pixels
23129     * @param scrollX Current X scroll value in pixels before applying deltaX
23130     * @param scrollY Current Y scroll value in pixels before applying deltaY
23131     * @param scrollRangeX Maximum content scroll range along the X axis
23132     * @param scrollRangeY Maximum content scroll range along the Y axis
23133     * @param maxOverScrollX Number of pixels to overscroll by in either direction
23134     *          along the X axis.
23135     * @param maxOverScrollY Number of pixels to overscroll by in either direction
23136     *          along the Y axis.
23137     * @param isTouchEvent true if this scroll operation is the result of a touch event.
23138     * @return true if scrolling was clamped to an over-scroll boundary along either
23139     *          axis, false otherwise.
23140     */
23141    @SuppressWarnings({"UnusedParameters"})
23142    protected boolean overScrollBy(int deltaX, int deltaY,
23143            int scrollX, int scrollY,
23144            int scrollRangeX, int scrollRangeY,
23145            int maxOverScrollX, int maxOverScrollY,
23146            boolean isTouchEvent) {
23147        final int overScrollMode = mOverScrollMode;
23148        final boolean canScrollHorizontal =
23149                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
23150        final boolean canScrollVertical =
23151                computeVerticalScrollRange() > computeVerticalScrollExtent();
23152        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
23153                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
23154        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
23155                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
23156
23157        int newScrollX = scrollX + deltaX;
23158        if (!overScrollHorizontal) {
23159            maxOverScrollX = 0;
23160        }
23161
23162        int newScrollY = scrollY + deltaY;
23163        if (!overScrollVertical) {
23164            maxOverScrollY = 0;
23165        }
23166
23167        // Clamp values if at the limits and record
23168        final int left = -maxOverScrollX;
23169        final int right = maxOverScrollX + scrollRangeX;
23170        final int top = -maxOverScrollY;
23171        final int bottom = maxOverScrollY + scrollRangeY;
23172
23173        boolean clampedX = false;
23174        if (newScrollX > right) {
23175            newScrollX = right;
23176            clampedX = true;
23177        } else if (newScrollX < left) {
23178            newScrollX = left;
23179            clampedX = true;
23180        }
23181
23182        boolean clampedY = false;
23183        if (newScrollY > bottom) {
23184            newScrollY = bottom;
23185            clampedY = true;
23186        } else if (newScrollY < top) {
23187            newScrollY = top;
23188            clampedY = true;
23189        }
23190
23191        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
23192
23193        return clampedX || clampedY;
23194    }
23195
23196    /**
23197     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
23198     * respond to the results of an over-scroll operation.
23199     *
23200     * @param scrollX New X scroll value in pixels
23201     * @param scrollY New Y scroll value in pixels
23202     * @param clampedX True if scrollX was clamped to an over-scroll boundary
23203     * @param clampedY True if scrollY was clamped to an over-scroll boundary
23204     */
23205    protected void onOverScrolled(int scrollX, int scrollY,
23206            boolean clampedX, boolean clampedY) {
23207        // Intentionally empty.
23208    }
23209
23210    /**
23211     * Returns the over-scroll mode for this view. The result will be
23212     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23213     * (allow over-scrolling only if the view content is larger than the container),
23214     * or {@link #OVER_SCROLL_NEVER}.
23215     *
23216     * @return This view's over-scroll mode.
23217     */
23218    public int getOverScrollMode() {
23219        return mOverScrollMode;
23220    }
23221
23222    /**
23223     * Set the over-scroll mode for this view. Valid over-scroll modes are
23224     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23225     * (allow over-scrolling only if the view content is larger than the container),
23226     * or {@link #OVER_SCROLL_NEVER}.
23227     *
23228     * Setting the over-scroll mode of a view will have an effect only if the
23229     * view is capable of scrolling.
23230     *
23231     * @param overScrollMode The new over-scroll mode for this view.
23232     */
23233    public void setOverScrollMode(int overScrollMode) {
23234        if (overScrollMode != OVER_SCROLL_ALWAYS &&
23235                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
23236                overScrollMode != OVER_SCROLL_NEVER) {
23237            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
23238        }
23239        mOverScrollMode = overScrollMode;
23240    }
23241
23242    /**
23243     * Enable or disable nested scrolling for this view.
23244     *
23245     * <p>If this property is set to true the view will be permitted to initiate nested
23246     * scrolling operations with a compatible parent view in the current hierarchy. If this
23247     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
23248     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
23249     * the nested scroll.</p>
23250     *
23251     * @param enabled true to enable nested scrolling, false to disable
23252     *
23253     * @see #isNestedScrollingEnabled()
23254     */
23255    public void setNestedScrollingEnabled(boolean enabled) {
23256        if (enabled) {
23257            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
23258        } else {
23259            stopNestedScroll();
23260            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
23261        }
23262    }
23263
23264    /**
23265     * Returns true if nested scrolling is enabled for this view.
23266     *
23267     * <p>If nested scrolling is enabled and this View class implementation supports it,
23268     * this view will act as a nested scrolling child view when applicable, forwarding data
23269     * about the scroll operation in progress to a compatible and cooperating nested scrolling
23270     * parent.</p>
23271     *
23272     * @return true if nested scrolling is enabled
23273     *
23274     * @see #setNestedScrollingEnabled(boolean)
23275     */
23276    public boolean isNestedScrollingEnabled() {
23277        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
23278                PFLAG3_NESTED_SCROLLING_ENABLED;
23279    }
23280
23281    /**
23282     * Begin a nestable scroll operation along the given axes.
23283     *
23284     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
23285     *
23286     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
23287     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
23288     * In the case of touch scrolling the nested scroll will be terminated automatically in
23289     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
23290     * In the event of programmatic scrolling the caller must explicitly call
23291     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
23292     *
23293     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
23294     * If it returns false the caller may ignore the rest of this contract until the next scroll.
23295     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
23296     *
23297     * <p>At each incremental step of the scroll the caller should invoke
23298     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
23299     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
23300     * parent at least partially consumed the scroll and the caller should adjust the amount it
23301     * scrolls by.</p>
23302     *
23303     * <p>After applying the remainder of the scroll delta the caller should invoke
23304     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
23305     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
23306     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
23307     * </p>
23308     *
23309     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
23310     *             {@link #SCROLL_AXIS_VERTICAL}.
23311     * @return true if a cooperative parent was found and nested scrolling has been enabled for
23312     *         the current gesture.
23313     *
23314     * @see #stopNestedScroll()
23315     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23316     * @see #dispatchNestedScroll(int, int, int, int, int[])
23317     */
23318    public boolean startNestedScroll(int axes) {
23319        if (hasNestedScrollingParent()) {
23320            // Already in progress
23321            return true;
23322        }
23323        if (isNestedScrollingEnabled()) {
23324            ViewParent p = getParent();
23325            View child = this;
23326            while (p != null) {
23327                try {
23328                    if (p.onStartNestedScroll(child, this, axes)) {
23329                        mNestedScrollingParent = p;
23330                        p.onNestedScrollAccepted(child, this, axes);
23331                        return true;
23332                    }
23333                } catch (AbstractMethodError e) {
23334                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23335                            "method onStartNestedScroll", e);
23336                    // Allow the search upward to continue
23337                }
23338                if (p instanceof View) {
23339                    child = (View) p;
23340                }
23341                p = p.getParent();
23342            }
23343        }
23344        return false;
23345    }
23346
23347    /**
23348     * Stop a nested scroll in progress.
23349     *
23350     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23351     *
23352     * @see #startNestedScroll(int)
23353     */
23354    public void stopNestedScroll() {
23355        if (mNestedScrollingParent != null) {
23356            mNestedScrollingParent.onStopNestedScroll(this);
23357            mNestedScrollingParent = null;
23358        }
23359    }
23360
23361    /**
23362     * Returns true if this view has a nested scrolling parent.
23363     *
23364     * <p>The presence of a nested scrolling parent indicates that this view has initiated
23365     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23366     *
23367     * @return whether this view has a nested scrolling parent
23368     */
23369    public boolean hasNestedScrollingParent() {
23370        return mNestedScrollingParent != null;
23371    }
23372
23373    /**
23374     * Dispatch one step of a nested scroll in progress.
23375     *
23376     * <p>Implementations of views that support nested scrolling should call this to report
23377     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23378     * is not currently in progress or nested scrolling is not
23379     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23380     *
23381     * <p>Compatible View implementations should also call
23382     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23383     * consuming a component of the scroll event themselves.</p>
23384     *
23385     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23386     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23387     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23388     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23389     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23390     *                       in local view coordinates of this view from before this operation
23391     *                       to after it completes. View implementations may use this to adjust
23392     *                       expected input coordinate tracking.
23393     * @return true if the event was dispatched, false if it could not be dispatched.
23394     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23395     */
23396    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23397            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23398        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23399            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23400                int startX = 0;
23401                int startY = 0;
23402                if (offsetInWindow != null) {
23403                    getLocationInWindow(offsetInWindow);
23404                    startX = offsetInWindow[0];
23405                    startY = offsetInWindow[1];
23406                }
23407
23408                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23409                        dxUnconsumed, dyUnconsumed);
23410
23411                if (offsetInWindow != null) {
23412                    getLocationInWindow(offsetInWindow);
23413                    offsetInWindow[0] -= startX;
23414                    offsetInWindow[1] -= startY;
23415                }
23416                return true;
23417            } else if (offsetInWindow != null) {
23418                // No motion, no dispatch. Keep offsetInWindow up to date.
23419                offsetInWindow[0] = 0;
23420                offsetInWindow[1] = 0;
23421            }
23422        }
23423        return false;
23424    }
23425
23426    /**
23427     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23428     *
23429     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23430     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23431     * scrolling operation to consume some or all of the scroll operation before the child view
23432     * consumes it.</p>
23433     *
23434     * @param dx Horizontal scroll distance in pixels
23435     * @param dy Vertical scroll distance in pixels
23436     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23437     *                 and consumed[1] the consumed dy.
23438     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23439     *                       in local view coordinates of this view from before this operation
23440     *                       to after it completes. View implementations may use this to adjust
23441     *                       expected input coordinate tracking.
23442     * @return true if the parent consumed some or all of the scroll delta
23443     * @see #dispatchNestedScroll(int, int, int, int, int[])
23444     */
23445    public boolean dispatchNestedPreScroll(int dx, int dy,
23446            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23447        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23448            if (dx != 0 || dy != 0) {
23449                int startX = 0;
23450                int startY = 0;
23451                if (offsetInWindow != null) {
23452                    getLocationInWindow(offsetInWindow);
23453                    startX = offsetInWindow[0];
23454                    startY = offsetInWindow[1];
23455                }
23456
23457                if (consumed == null) {
23458                    if (mTempNestedScrollConsumed == null) {
23459                        mTempNestedScrollConsumed = new int[2];
23460                    }
23461                    consumed = mTempNestedScrollConsumed;
23462                }
23463                consumed[0] = 0;
23464                consumed[1] = 0;
23465                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23466
23467                if (offsetInWindow != null) {
23468                    getLocationInWindow(offsetInWindow);
23469                    offsetInWindow[0] -= startX;
23470                    offsetInWindow[1] -= startY;
23471                }
23472                return consumed[0] != 0 || consumed[1] != 0;
23473            } else if (offsetInWindow != null) {
23474                offsetInWindow[0] = 0;
23475                offsetInWindow[1] = 0;
23476            }
23477        }
23478        return false;
23479    }
23480
23481    /**
23482     * Dispatch a fling to a nested scrolling parent.
23483     *
23484     * <p>This method should be used to indicate that a nested scrolling child has detected
23485     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23486     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23487     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23488     * along a scrollable axis.</p>
23489     *
23490     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23491     * its own content, it can use this method to delegate the fling to its nested scrolling
23492     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23493     *
23494     * @param velocityX Horizontal fling velocity in pixels per second
23495     * @param velocityY Vertical fling velocity in pixels per second
23496     * @param consumed true if the child consumed the fling, false otherwise
23497     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23498     */
23499    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23500        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23501            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23502        }
23503        return false;
23504    }
23505
23506    /**
23507     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23508     *
23509     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23510     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23511     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23512     * before the child view consumes it. If this method returns <code>true</code>, a nested
23513     * parent view consumed the fling and this view should not scroll as a result.</p>
23514     *
23515     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23516     * the fling at a time. If a parent view consumed the fling this method will return false.
23517     * Custom view implementations should account for this in two ways:</p>
23518     *
23519     * <ul>
23520     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23521     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23522     *     position regardless.</li>
23523     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23524     *     even to settle back to a valid idle position.</li>
23525     * </ul>
23526     *
23527     * <p>Views should also not offer fling velocities to nested parent views along an axis
23528     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23529     * should not offer a horizontal fling velocity to its parents since scrolling along that
23530     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23531     *
23532     * @param velocityX Horizontal fling velocity in pixels per second
23533     * @param velocityY Vertical fling velocity in pixels per second
23534     * @return true if a nested scrolling parent consumed the fling
23535     */
23536    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23537        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23538            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23539        }
23540        return false;
23541    }
23542
23543    /**
23544     * Gets a scale factor that determines the distance the view should scroll
23545     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23546     * @return The vertical scroll scale factor.
23547     * @hide
23548     */
23549    protected float getVerticalScrollFactor() {
23550        if (mVerticalScrollFactor == 0) {
23551            TypedValue outValue = new TypedValue();
23552            if (!mContext.getTheme().resolveAttribute(
23553                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23554                throw new IllegalStateException(
23555                        "Expected theme to define listPreferredItemHeight.");
23556            }
23557            mVerticalScrollFactor = outValue.getDimension(
23558                    mContext.getResources().getDisplayMetrics());
23559        }
23560        return mVerticalScrollFactor;
23561    }
23562
23563    /**
23564     * Gets a scale factor that determines the distance the view should scroll
23565     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23566     * @return The horizontal scroll scale factor.
23567     * @hide
23568     */
23569    protected float getHorizontalScrollFactor() {
23570        // TODO: Should use something else.
23571        return getVerticalScrollFactor();
23572    }
23573
23574    /**
23575     * Return the value specifying the text direction or policy that was set with
23576     * {@link #setTextDirection(int)}.
23577     *
23578     * @return the defined text direction. It can be one of:
23579     *
23580     * {@link #TEXT_DIRECTION_INHERIT},
23581     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23582     * {@link #TEXT_DIRECTION_ANY_RTL},
23583     * {@link #TEXT_DIRECTION_LTR},
23584     * {@link #TEXT_DIRECTION_RTL},
23585     * {@link #TEXT_DIRECTION_LOCALE},
23586     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23587     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23588     *
23589     * @attr ref android.R.styleable#View_textDirection
23590     *
23591     * @hide
23592     */
23593    @ViewDebug.ExportedProperty(category = "text", mapping = {
23594            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23595            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23596            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23597            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23598            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23599            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23600            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23601            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23602    })
23603    public int getRawTextDirection() {
23604        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23605    }
23606
23607    /**
23608     * Set the text direction.
23609     *
23610     * @param textDirection the direction to set. Should be one of:
23611     *
23612     * {@link #TEXT_DIRECTION_INHERIT},
23613     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23614     * {@link #TEXT_DIRECTION_ANY_RTL},
23615     * {@link #TEXT_DIRECTION_LTR},
23616     * {@link #TEXT_DIRECTION_RTL},
23617     * {@link #TEXT_DIRECTION_LOCALE}
23618     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23619     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23620     *
23621     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23622     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23623     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23624     *
23625     * @attr ref android.R.styleable#View_textDirection
23626     */
23627    public void setTextDirection(int textDirection) {
23628        if (getRawTextDirection() != textDirection) {
23629            // Reset the current text direction and the resolved one
23630            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23631            resetResolvedTextDirection();
23632            // Set the new text direction
23633            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23634            // Do resolution
23635            resolveTextDirection();
23636            // Notify change
23637            onRtlPropertiesChanged(getLayoutDirection());
23638            // Refresh
23639            requestLayout();
23640            invalidate(true);
23641        }
23642    }
23643
23644    /**
23645     * Return the resolved text direction.
23646     *
23647     * @return the resolved text direction. Returns one of:
23648     *
23649     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23650     * {@link #TEXT_DIRECTION_ANY_RTL},
23651     * {@link #TEXT_DIRECTION_LTR},
23652     * {@link #TEXT_DIRECTION_RTL},
23653     * {@link #TEXT_DIRECTION_LOCALE},
23654     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23655     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23656     *
23657     * @attr ref android.R.styleable#View_textDirection
23658     */
23659    @ViewDebug.ExportedProperty(category = "text", mapping = {
23660            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23661            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23662            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23663            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23664            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23665            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23666            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23667            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23668    })
23669    public int getTextDirection() {
23670        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23671    }
23672
23673    /**
23674     * Resolve the text direction.
23675     *
23676     * @return true if resolution has been done, false otherwise.
23677     *
23678     * @hide
23679     */
23680    public boolean resolveTextDirection() {
23681        // Reset any previous text direction resolution
23682        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23683
23684        if (hasRtlSupport()) {
23685            // Set resolved text direction flag depending on text direction flag
23686            final int textDirection = getRawTextDirection();
23687            switch(textDirection) {
23688                case TEXT_DIRECTION_INHERIT:
23689                    if (!canResolveTextDirection()) {
23690                        // We cannot do the resolution if there is no parent, so use the default one
23691                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23692                        // Resolution will need to happen again later
23693                        return false;
23694                    }
23695
23696                    // Parent has not yet resolved, so we still return the default
23697                    try {
23698                        if (!mParent.isTextDirectionResolved()) {
23699                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23700                            // Resolution will need to happen again later
23701                            return false;
23702                        }
23703                    } catch (AbstractMethodError e) {
23704                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23705                                " does not fully implement ViewParent", e);
23706                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23707                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23708                        return true;
23709                    }
23710
23711                    // Set current resolved direction to the same value as the parent's one
23712                    int parentResolvedDirection;
23713                    try {
23714                        parentResolvedDirection = mParent.getTextDirection();
23715                    } catch (AbstractMethodError e) {
23716                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23717                                " does not fully implement ViewParent", e);
23718                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23719                    }
23720                    switch (parentResolvedDirection) {
23721                        case TEXT_DIRECTION_FIRST_STRONG:
23722                        case TEXT_DIRECTION_ANY_RTL:
23723                        case TEXT_DIRECTION_LTR:
23724                        case TEXT_DIRECTION_RTL:
23725                        case TEXT_DIRECTION_LOCALE:
23726                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23727                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23728                            mPrivateFlags2 |=
23729                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23730                            break;
23731                        default:
23732                            // Default resolved direction is "first strong" heuristic
23733                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23734                    }
23735                    break;
23736                case TEXT_DIRECTION_FIRST_STRONG:
23737                case TEXT_DIRECTION_ANY_RTL:
23738                case TEXT_DIRECTION_LTR:
23739                case TEXT_DIRECTION_RTL:
23740                case TEXT_DIRECTION_LOCALE:
23741                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23742                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23743                    // Resolved direction is the same as text direction
23744                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23745                    break;
23746                default:
23747                    // Default resolved direction is "first strong" heuristic
23748                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23749            }
23750        } else {
23751            // Default resolved direction is "first strong" heuristic
23752            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23753        }
23754
23755        // Set to resolved
23756        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23757        return true;
23758    }
23759
23760    /**
23761     * Check if text direction resolution can be done.
23762     *
23763     * @return true if text direction resolution can be done otherwise return false.
23764     */
23765    public boolean canResolveTextDirection() {
23766        switch (getRawTextDirection()) {
23767            case TEXT_DIRECTION_INHERIT:
23768                if (mParent != null) {
23769                    try {
23770                        return mParent.canResolveTextDirection();
23771                    } catch (AbstractMethodError e) {
23772                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23773                                " does not fully implement ViewParent", e);
23774                    }
23775                }
23776                return false;
23777
23778            default:
23779                return true;
23780        }
23781    }
23782
23783    /**
23784     * Reset resolved text direction. Text direction will be resolved during a call to
23785     * {@link #onMeasure(int, int)}.
23786     *
23787     * @hide
23788     */
23789    public void resetResolvedTextDirection() {
23790        // Reset any previous text direction resolution
23791        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23792        // Set to default value
23793        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23794    }
23795
23796    /**
23797     * @return true if text direction is inherited.
23798     *
23799     * @hide
23800     */
23801    public boolean isTextDirectionInherited() {
23802        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23803    }
23804
23805    /**
23806     * @return true if text direction is resolved.
23807     */
23808    public boolean isTextDirectionResolved() {
23809        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23810    }
23811
23812    /**
23813     * Return the value specifying the text alignment or policy that was set with
23814     * {@link #setTextAlignment(int)}.
23815     *
23816     * @return the defined text alignment. It can be one of:
23817     *
23818     * {@link #TEXT_ALIGNMENT_INHERIT},
23819     * {@link #TEXT_ALIGNMENT_GRAVITY},
23820     * {@link #TEXT_ALIGNMENT_CENTER},
23821     * {@link #TEXT_ALIGNMENT_TEXT_START},
23822     * {@link #TEXT_ALIGNMENT_TEXT_END},
23823     * {@link #TEXT_ALIGNMENT_VIEW_START},
23824     * {@link #TEXT_ALIGNMENT_VIEW_END}
23825     *
23826     * @attr ref android.R.styleable#View_textAlignment
23827     *
23828     * @hide
23829     */
23830    @ViewDebug.ExportedProperty(category = "text", mapping = {
23831            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23832            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23833            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23834            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23835            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23836            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23837            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23838    })
23839    @TextAlignment
23840    public int getRawTextAlignment() {
23841        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23842    }
23843
23844    /**
23845     * Set the text alignment.
23846     *
23847     * @param textAlignment The text alignment to set. Should be one of
23848     *
23849     * {@link #TEXT_ALIGNMENT_INHERIT},
23850     * {@link #TEXT_ALIGNMENT_GRAVITY},
23851     * {@link #TEXT_ALIGNMENT_CENTER},
23852     * {@link #TEXT_ALIGNMENT_TEXT_START},
23853     * {@link #TEXT_ALIGNMENT_TEXT_END},
23854     * {@link #TEXT_ALIGNMENT_VIEW_START},
23855     * {@link #TEXT_ALIGNMENT_VIEW_END}
23856     *
23857     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23858     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23859     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23860     *
23861     * @attr ref android.R.styleable#View_textAlignment
23862     */
23863    public void setTextAlignment(@TextAlignment int textAlignment) {
23864        if (textAlignment != getRawTextAlignment()) {
23865            // Reset the current and resolved text alignment
23866            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23867            resetResolvedTextAlignment();
23868            // Set the new text alignment
23869            mPrivateFlags2 |=
23870                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23871            // Do resolution
23872            resolveTextAlignment();
23873            // Notify change
23874            onRtlPropertiesChanged(getLayoutDirection());
23875            // Refresh
23876            requestLayout();
23877            invalidate(true);
23878        }
23879    }
23880
23881    /**
23882     * Return the resolved text alignment.
23883     *
23884     * @return the resolved text alignment. Returns one of:
23885     *
23886     * {@link #TEXT_ALIGNMENT_GRAVITY},
23887     * {@link #TEXT_ALIGNMENT_CENTER},
23888     * {@link #TEXT_ALIGNMENT_TEXT_START},
23889     * {@link #TEXT_ALIGNMENT_TEXT_END},
23890     * {@link #TEXT_ALIGNMENT_VIEW_START},
23891     * {@link #TEXT_ALIGNMENT_VIEW_END}
23892     *
23893     * @attr ref android.R.styleable#View_textAlignment
23894     */
23895    @ViewDebug.ExportedProperty(category = "text", mapping = {
23896            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23897            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23898            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23899            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23900            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23901            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23902            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23903    })
23904    @TextAlignment
23905    public int getTextAlignment() {
23906        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23907                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23908    }
23909
23910    /**
23911     * Resolve the text alignment.
23912     *
23913     * @return true if resolution has been done, false otherwise.
23914     *
23915     * @hide
23916     */
23917    public boolean resolveTextAlignment() {
23918        // Reset any previous text alignment resolution
23919        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23920
23921        if (hasRtlSupport()) {
23922            // Set resolved text alignment flag depending on text alignment flag
23923            final int textAlignment = getRawTextAlignment();
23924            switch (textAlignment) {
23925                case TEXT_ALIGNMENT_INHERIT:
23926                    // Check if we can resolve the text alignment
23927                    if (!canResolveTextAlignment()) {
23928                        // We cannot do the resolution if there is no parent so use the default
23929                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23930                        // Resolution will need to happen again later
23931                        return false;
23932                    }
23933
23934                    // Parent has not yet resolved, so we still return the default
23935                    try {
23936                        if (!mParent.isTextAlignmentResolved()) {
23937                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23938                            // Resolution will need to happen again later
23939                            return false;
23940                        }
23941                    } catch (AbstractMethodError e) {
23942                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23943                                " does not fully implement ViewParent", e);
23944                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23945                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23946                        return true;
23947                    }
23948
23949                    int parentResolvedTextAlignment;
23950                    try {
23951                        parentResolvedTextAlignment = mParent.getTextAlignment();
23952                    } catch (AbstractMethodError e) {
23953                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23954                                " does not fully implement ViewParent", e);
23955                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23956                    }
23957                    switch (parentResolvedTextAlignment) {
23958                        case TEXT_ALIGNMENT_GRAVITY:
23959                        case TEXT_ALIGNMENT_TEXT_START:
23960                        case TEXT_ALIGNMENT_TEXT_END:
23961                        case TEXT_ALIGNMENT_CENTER:
23962                        case TEXT_ALIGNMENT_VIEW_START:
23963                        case TEXT_ALIGNMENT_VIEW_END:
23964                            // Resolved text alignment is the same as the parent resolved
23965                            // text alignment
23966                            mPrivateFlags2 |=
23967                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23968                            break;
23969                        default:
23970                            // Use default resolved text alignment
23971                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23972                    }
23973                    break;
23974                case TEXT_ALIGNMENT_GRAVITY:
23975                case TEXT_ALIGNMENT_TEXT_START:
23976                case TEXT_ALIGNMENT_TEXT_END:
23977                case TEXT_ALIGNMENT_CENTER:
23978                case TEXT_ALIGNMENT_VIEW_START:
23979                case TEXT_ALIGNMENT_VIEW_END:
23980                    // Resolved text alignment is the same as text alignment
23981                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23982                    break;
23983                default:
23984                    // Use default resolved text alignment
23985                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23986            }
23987        } else {
23988            // Use default resolved text alignment
23989            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23990        }
23991
23992        // Set the resolved
23993        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23994        return true;
23995    }
23996
23997    /**
23998     * Check if text alignment resolution can be done.
23999     *
24000     * @return true if text alignment resolution can be done otherwise return false.
24001     */
24002    public boolean canResolveTextAlignment() {
24003        switch (getRawTextAlignment()) {
24004            case TEXT_DIRECTION_INHERIT:
24005                if (mParent != null) {
24006                    try {
24007                        return mParent.canResolveTextAlignment();
24008                    } catch (AbstractMethodError e) {
24009                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24010                                " does not fully implement ViewParent", e);
24011                    }
24012                }
24013                return false;
24014
24015            default:
24016                return true;
24017        }
24018    }
24019
24020    /**
24021     * Reset resolved text alignment. Text alignment will be resolved during a call to
24022     * {@link #onMeasure(int, int)}.
24023     *
24024     * @hide
24025     */
24026    public void resetResolvedTextAlignment() {
24027        // Reset any previous text alignment resolution
24028        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24029        // Set to default
24030        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24031    }
24032
24033    /**
24034     * @return true if text alignment is inherited.
24035     *
24036     * @hide
24037     */
24038    public boolean isTextAlignmentInherited() {
24039        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
24040    }
24041
24042    /**
24043     * @return true if text alignment is resolved.
24044     */
24045    public boolean isTextAlignmentResolved() {
24046        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24047    }
24048
24049    /**
24050     * Generate a value suitable for use in {@link #setId(int)}.
24051     * This value will not collide with ID values generated at build time by aapt for R.id.
24052     *
24053     * @return a generated ID value
24054     */
24055    public static int generateViewId() {
24056        for (;;) {
24057            final int result = sNextGeneratedId.get();
24058            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
24059            int newValue = result + 1;
24060            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
24061            if (sNextGeneratedId.compareAndSet(result, newValue)) {
24062                return result;
24063            }
24064        }
24065    }
24066
24067    private static boolean isViewIdGenerated(int id) {
24068        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
24069    }
24070
24071    /**
24072     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
24073     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
24074     *                           a normal View or a ViewGroup with
24075     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
24076     * @hide
24077     */
24078    public void captureTransitioningViews(List<View> transitioningViews) {
24079        if (getVisibility() == View.VISIBLE) {
24080            transitioningViews.add(this);
24081        }
24082    }
24083
24084    /**
24085     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
24086     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
24087     * @hide
24088     */
24089    public void findNamedViews(Map<String, View> namedElements) {
24090        if (getVisibility() == VISIBLE || mGhostView != null) {
24091            String transitionName = getTransitionName();
24092            if (transitionName != null) {
24093                namedElements.put(transitionName, this);
24094            }
24095        }
24096    }
24097
24098    /**
24099     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
24100     * The default implementation does not care the location or event types, but some subclasses
24101     * may use it (such as WebViews).
24102     * @param event The MotionEvent from a mouse
24103     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
24104     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
24105     * @see PointerIcon
24106     */
24107    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
24108        final float x = event.getX(pointerIndex);
24109        final float y = event.getY(pointerIndex);
24110        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
24111            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
24112        }
24113        return mPointerIcon;
24114    }
24115
24116    /**
24117     * Set the pointer icon for the current view.
24118     * Passing {@code null} will restore the pointer icon to its default value.
24119     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
24120     */
24121    public void setPointerIcon(PointerIcon pointerIcon) {
24122        mPointerIcon = pointerIcon;
24123        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
24124            return;
24125        }
24126        try {
24127            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
24128        } catch (RemoteException e) {
24129        }
24130    }
24131
24132    /**
24133     * Gets the pointer icon for the current view.
24134     */
24135    public PointerIcon getPointerIcon() {
24136        return mPointerIcon;
24137    }
24138
24139    /**
24140     * Checks pointer capture status.
24141     *
24142     * @return true if the view has pointer capture.
24143     * @see #requestPointerCapture()
24144     * @see #hasPointerCapture()
24145     */
24146    public boolean hasPointerCapture() {
24147        final ViewRootImpl viewRootImpl = getViewRootImpl();
24148        if (viewRootImpl == null) {
24149            return false;
24150        }
24151        return viewRootImpl.hasPointerCapture();
24152    }
24153
24154    /**
24155     * Requests pointer capture mode.
24156     * <p>
24157     * When the window has pointer capture, the mouse pointer icon will disappear and will not
24158     * change its position. Further mouse will be dispatched with the source
24159     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
24160     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
24161     * (touchscreens, or stylus) will not be affected.
24162     * <p>
24163     * If the window already has pointer capture, this call does nothing.
24164     * <p>
24165     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
24166     * automatically when the window loses focus.
24167     *
24168     * @see #releasePointerCapture()
24169     * @see #hasPointerCapture()
24170     */
24171    public void requestPointerCapture() {
24172        final ViewRootImpl viewRootImpl = getViewRootImpl();
24173        if (viewRootImpl != null) {
24174            viewRootImpl.requestPointerCapture(true);
24175        }
24176    }
24177
24178
24179    /**
24180     * Releases the pointer capture.
24181     * <p>
24182     * If the window does not have pointer capture, this call will do nothing.
24183     * @see #requestPointerCapture()
24184     * @see #hasPointerCapture()
24185     */
24186    public void releasePointerCapture() {
24187        final ViewRootImpl viewRootImpl = getViewRootImpl();
24188        if (viewRootImpl != null) {
24189            viewRootImpl.requestPointerCapture(false);
24190        }
24191    }
24192
24193    /**
24194     * Called when the window has just acquired or lost pointer capture.
24195     *
24196     * @param hasCapture True if the view now has pointerCapture, false otherwise.
24197     */
24198    @CallSuper
24199    public void onPointerCaptureChange(boolean hasCapture) {
24200    }
24201
24202    /**
24203     * @see #onPointerCaptureChange
24204     */
24205    public void dispatchPointerCaptureChanged(boolean hasCapture) {
24206        onPointerCaptureChange(hasCapture);
24207    }
24208
24209    /**
24210     * Implement this method to handle captured pointer events
24211     *
24212     * @param event The captured pointer event.
24213     * @return True if the event was handled, false otherwise.
24214     * @see #requestPointerCapture()
24215     */
24216    public boolean onCapturedPointerEvent(MotionEvent event) {
24217        return false;
24218    }
24219
24220    /**
24221     * Interface definition for a callback to be invoked when a captured pointer event
24222     * is being dispatched this view. The callback will be invoked before the event is
24223     * given to the view.
24224     */
24225    public interface OnCapturedPointerListener {
24226        /**
24227         * Called when a captured pointer event is dispatched to a view.
24228         * @param view The view this event has been dispatched to.
24229         * @param event The captured event.
24230         * @return True if the listener has consumed the event, false otherwise.
24231         */
24232        boolean onCapturedPointer(View view, MotionEvent event);
24233    }
24234
24235    /**
24236     * Set a listener to receive callbacks when the pointer capture state of a view changes.
24237     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
24238     */
24239    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
24240        getListenerInfo().mOnCapturedPointerListener = l;
24241    }
24242
24243    // Properties
24244    //
24245    /**
24246     * A Property wrapper around the <code>alpha</code> functionality handled by the
24247     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
24248     */
24249    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
24250        @Override
24251        public void setValue(View object, float value) {
24252            object.setAlpha(value);
24253        }
24254
24255        @Override
24256        public Float get(View object) {
24257            return object.getAlpha();
24258        }
24259    };
24260
24261    /**
24262     * A Property wrapper around the <code>translationX</code> functionality handled by the
24263     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
24264     */
24265    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
24266        @Override
24267        public void setValue(View object, float value) {
24268            object.setTranslationX(value);
24269        }
24270
24271                @Override
24272        public Float get(View object) {
24273            return object.getTranslationX();
24274        }
24275    };
24276
24277    /**
24278     * A Property wrapper around the <code>translationY</code> functionality handled by the
24279     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
24280     */
24281    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
24282        @Override
24283        public void setValue(View object, float value) {
24284            object.setTranslationY(value);
24285        }
24286
24287        @Override
24288        public Float get(View object) {
24289            return object.getTranslationY();
24290        }
24291    };
24292
24293    /**
24294     * A Property wrapper around the <code>translationZ</code> functionality handled by the
24295     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
24296     */
24297    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
24298        @Override
24299        public void setValue(View object, float value) {
24300            object.setTranslationZ(value);
24301        }
24302
24303        @Override
24304        public Float get(View object) {
24305            return object.getTranslationZ();
24306        }
24307    };
24308
24309    /**
24310     * A Property wrapper around the <code>x</code> functionality handled by the
24311     * {@link View#setX(float)} and {@link View#getX()} methods.
24312     */
24313    public static final Property<View, Float> X = new FloatProperty<View>("x") {
24314        @Override
24315        public void setValue(View object, float value) {
24316            object.setX(value);
24317        }
24318
24319        @Override
24320        public Float get(View object) {
24321            return object.getX();
24322        }
24323    };
24324
24325    /**
24326     * A Property wrapper around the <code>y</code> functionality handled by the
24327     * {@link View#setY(float)} and {@link View#getY()} methods.
24328     */
24329    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24330        @Override
24331        public void setValue(View object, float value) {
24332            object.setY(value);
24333        }
24334
24335        @Override
24336        public Float get(View object) {
24337            return object.getY();
24338        }
24339    };
24340
24341    /**
24342     * A Property wrapper around the <code>z</code> functionality handled by the
24343     * {@link View#setZ(float)} and {@link View#getZ()} methods.
24344     */
24345    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24346        @Override
24347        public void setValue(View object, float value) {
24348            object.setZ(value);
24349        }
24350
24351        @Override
24352        public Float get(View object) {
24353            return object.getZ();
24354        }
24355    };
24356
24357    /**
24358     * A Property wrapper around the <code>rotation</code> functionality handled by the
24359     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24360     */
24361    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24362        @Override
24363        public void setValue(View object, float value) {
24364            object.setRotation(value);
24365        }
24366
24367        @Override
24368        public Float get(View object) {
24369            return object.getRotation();
24370        }
24371    };
24372
24373    /**
24374     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24375     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24376     */
24377    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24378        @Override
24379        public void setValue(View object, float value) {
24380            object.setRotationX(value);
24381        }
24382
24383        @Override
24384        public Float get(View object) {
24385            return object.getRotationX();
24386        }
24387    };
24388
24389    /**
24390     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24391     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24392     */
24393    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24394        @Override
24395        public void setValue(View object, float value) {
24396            object.setRotationY(value);
24397        }
24398
24399        @Override
24400        public Float get(View object) {
24401            return object.getRotationY();
24402        }
24403    };
24404
24405    /**
24406     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24407     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24408     */
24409    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24410        @Override
24411        public void setValue(View object, float value) {
24412            object.setScaleX(value);
24413        }
24414
24415        @Override
24416        public Float get(View object) {
24417            return object.getScaleX();
24418        }
24419    };
24420
24421    /**
24422     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24423     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24424     */
24425    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24426        @Override
24427        public void setValue(View object, float value) {
24428            object.setScaleY(value);
24429        }
24430
24431        @Override
24432        public Float get(View object) {
24433            return object.getScaleY();
24434        }
24435    };
24436
24437    /**
24438     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24439     * Each MeasureSpec represents a requirement for either the width or the height.
24440     * A MeasureSpec is comprised of a size and a mode. There are three possible
24441     * modes:
24442     * <dl>
24443     * <dt>UNSPECIFIED</dt>
24444     * <dd>
24445     * The parent has not imposed any constraint on the child. It can be whatever size
24446     * it wants.
24447     * </dd>
24448     *
24449     * <dt>EXACTLY</dt>
24450     * <dd>
24451     * The parent has determined an exact size for the child. The child is going to be
24452     * given those bounds regardless of how big it wants to be.
24453     * </dd>
24454     *
24455     * <dt>AT_MOST</dt>
24456     * <dd>
24457     * The child can be as large as it wants up to the specified size.
24458     * </dd>
24459     * </dl>
24460     *
24461     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24462     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24463     */
24464    public static class MeasureSpec {
24465        private static final int MODE_SHIFT = 30;
24466        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24467
24468        /** @hide */
24469        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24470        @Retention(RetentionPolicy.SOURCE)
24471        public @interface MeasureSpecMode {}
24472
24473        /**
24474         * Measure specification mode: The parent has not imposed any constraint
24475         * on the child. It can be whatever size it wants.
24476         */
24477        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24478
24479        /**
24480         * Measure specification mode: The parent has determined an exact size
24481         * for the child. The child is going to be given those bounds regardless
24482         * of how big it wants to be.
24483         */
24484        public static final int EXACTLY     = 1 << MODE_SHIFT;
24485
24486        /**
24487         * Measure specification mode: The child can be as large as it wants up
24488         * to the specified size.
24489         */
24490        public static final int AT_MOST     = 2 << MODE_SHIFT;
24491
24492        /**
24493         * Creates a measure specification based on the supplied size and mode.
24494         *
24495         * The mode must always be one of the following:
24496         * <ul>
24497         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24498         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24499         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24500         * </ul>
24501         *
24502         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24503         * implementation was such that the order of arguments did not matter
24504         * and overflow in either value could impact the resulting MeasureSpec.
24505         * {@link android.widget.RelativeLayout} was affected by this bug.
24506         * Apps targeting API levels greater than 17 will get the fixed, more strict
24507         * behavior.</p>
24508         *
24509         * @param size the size of the measure specification
24510         * @param mode the mode of the measure specification
24511         * @return the measure specification based on size and mode
24512         */
24513        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24514                                          @MeasureSpecMode int mode) {
24515            if (sUseBrokenMakeMeasureSpec) {
24516                return size + mode;
24517            } else {
24518                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24519            }
24520        }
24521
24522        /**
24523         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24524         * will automatically get a size of 0. Older apps expect this.
24525         *
24526         * @hide internal use only for compatibility with system widgets and older apps
24527         */
24528        public static int makeSafeMeasureSpec(int size, int mode) {
24529            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24530                return 0;
24531            }
24532            return makeMeasureSpec(size, mode);
24533        }
24534
24535        /**
24536         * Extracts the mode from the supplied measure specification.
24537         *
24538         * @param measureSpec the measure specification to extract the mode from
24539         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24540         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24541         *         {@link android.view.View.MeasureSpec#EXACTLY}
24542         */
24543        @MeasureSpecMode
24544        public static int getMode(int measureSpec) {
24545            //noinspection ResourceType
24546            return (measureSpec & MODE_MASK);
24547        }
24548
24549        /**
24550         * Extracts the size from the supplied measure specification.
24551         *
24552         * @param measureSpec the measure specification to extract the size from
24553         * @return the size in pixels defined in the supplied measure specification
24554         */
24555        public static int getSize(int measureSpec) {
24556            return (measureSpec & ~MODE_MASK);
24557        }
24558
24559        static int adjust(int measureSpec, int delta) {
24560            final int mode = getMode(measureSpec);
24561            int size = getSize(measureSpec);
24562            if (mode == UNSPECIFIED) {
24563                // No need to adjust size for UNSPECIFIED mode.
24564                return makeMeasureSpec(size, UNSPECIFIED);
24565            }
24566            size += delta;
24567            if (size < 0) {
24568                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24569                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24570                size = 0;
24571            }
24572            return makeMeasureSpec(size, mode);
24573        }
24574
24575        /**
24576         * Returns a String representation of the specified measure
24577         * specification.
24578         *
24579         * @param measureSpec the measure specification to convert to a String
24580         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24581         */
24582        public static String toString(int measureSpec) {
24583            int mode = getMode(measureSpec);
24584            int size = getSize(measureSpec);
24585
24586            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24587
24588            if (mode == UNSPECIFIED)
24589                sb.append("UNSPECIFIED ");
24590            else if (mode == EXACTLY)
24591                sb.append("EXACTLY ");
24592            else if (mode == AT_MOST)
24593                sb.append("AT_MOST ");
24594            else
24595                sb.append(mode).append(" ");
24596
24597            sb.append(size);
24598            return sb.toString();
24599        }
24600    }
24601
24602    private final class CheckForLongPress implements Runnable {
24603        private int mOriginalWindowAttachCount;
24604        private float mX;
24605        private float mY;
24606        private boolean mOriginalPressedState;
24607
24608        @Override
24609        public void run() {
24610            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24611                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24612                if (performLongClick(mX, mY)) {
24613                    mHasPerformedLongPress = true;
24614                }
24615            }
24616        }
24617
24618        public void setAnchor(float x, float y) {
24619            mX = x;
24620            mY = y;
24621        }
24622
24623        public void rememberWindowAttachCount() {
24624            mOriginalWindowAttachCount = mWindowAttachCount;
24625        }
24626
24627        public void rememberPressedState() {
24628            mOriginalPressedState = isPressed();
24629        }
24630    }
24631
24632    private final class CheckForTap implements Runnable {
24633        public float x;
24634        public float y;
24635
24636        @Override
24637        public void run() {
24638            mPrivateFlags &= ~PFLAG_PREPRESSED;
24639            setPressed(true, x, y);
24640            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24641        }
24642    }
24643
24644    private final class PerformClick implements Runnable {
24645        @Override
24646        public void run() {
24647            performClick();
24648        }
24649    }
24650
24651    /**
24652     * This method returns a ViewPropertyAnimator object, which can be used to animate
24653     * specific properties on this View.
24654     *
24655     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24656     */
24657    public ViewPropertyAnimator animate() {
24658        if (mAnimator == null) {
24659            mAnimator = new ViewPropertyAnimator(this);
24660        }
24661        return mAnimator;
24662    }
24663
24664    /**
24665     * Sets the name of the View to be used to identify Views in Transitions.
24666     * Names should be unique in the View hierarchy.
24667     *
24668     * @param transitionName The name of the View to uniquely identify it for Transitions.
24669     */
24670    public final void setTransitionName(String transitionName) {
24671        mTransitionName = transitionName;
24672    }
24673
24674    /**
24675     * Returns the name of the View to be used to identify Views in Transitions.
24676     * Names should be unique in the View hierarchy.
24677     *
24678     * <p>This returns null if the View has not been given a name.</p>
24679     *
24680     * @return The name used of the View to be used to identify Views in Transitions or null
24681     * if no name has been given.
24682     */
24683    @ViewDebug.ExportedProperty
24684    public String getTransitionName() {
24685        return mTransitionName;
24686    }
24687
24688    /**
24689     * @hide
24690     */
24691    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24692        // Do nothing.
24693    }
24694
24695    /**
24696     * Interface definition for a callback to be invoked when a hardware key event is
24697     * dispatched to this view. The callback will be invoked before the key event is
24698     * given to the view. This is only useful for hardware keyboards; a software input
24699     * method has no obligation to trigger this listener.
24700     */
24701    public interface OnKeyListener {
24702        /**
24703         * Called when a hardware key is dispatched to a view. This allows listeners to
24704         * get a chance to respond before the target view.
24705         * <p>Key presses in software keyboards will generally NOT trigger this method,
24706         * although some may elect to do so in some situations. Do not assume a
24707         * software input method has to be key-based; even if it is, it may use key presses
24708         * in a different way than you expect, so there is no way to reliably catch soft
24709         * input key presses.
24710         *
24711         * @param v The view the key has been dispatched to.
24712         * @param keyCode The code for the physical key that was pressed
24713         * @param event The KeyEvent object containing full information about
24714         *        the event.
24715         * @return True if the listener has consumed the event, false otherwise.
24716         */
24717        boolean onKey(View v, int keyCode, KeyEvent event);
24718    }
24719
24720    /**
24721     * Interface definition for a callback to be invoked when a touch event is
24722     * dispatched to this view. The callback will be invoked before the touch
24723     * event is given to the view.
24724     */
24725    public interface OnTouchListener {
24726        /**
24727         * Called when a touch event is dispatched to a view. This allows listeners to
24728         * get a chance to respond before the target view.
24729         *
24730         * @param v The view the touch event has been dispatched to.
24731         * @param event The MotionEvent object containing full information about
24732         *        the event.
24733         * @return True if the listener has consumed the event, false otherwise.
24734         */
24735        boolean onTouch(View v, MotionEvent event);
24736    }
24737
24738    /**
24739     * Interface definition for a callback to be invoked when a hover event is
24740     * dispatched to this view. The callback will be invoked before the hover
24741     * event is given to the view.
24742     */
24743    public interface OnHoverListener {
24744        /**
24745         * Called when a hover event is dispatched to a view. This allows listeners to
24746         * get a chance to respond before the target view.
24747         *
24748         * @param v The view the hover event has been dispatched to.
24749         * @param event The MotionEvent object containing full information about
24750         *        the event.
24751         * @return True if the listener has consumed the event, false otherwise.
24752         */
24753        boolean onHover(View v, MotionEvent event);
24754    }
24755
24756    /**
24757     * Interface definition for a callback to be invoked when a generic motion event is
24758     * dispatched to this view. The callback will be invoked before the generic motion
24759     * event is given to the view.
24760     */
24761    public interface OnGenericMotionListener {
24762        /**
24763         * Called when a generic motion event is dispatched to a view. This allows listeners to
24764         * get a chance to respond before the target view.
24765         *
24766         * @param v The view the generic motion event has been dispatched to.
24767         * @param event The MotionEvent object containing full information about
24768         *        the event.
24769         * @return True if the listener has consumed the event, false otherwise.
24770         */
24771        boolean onGenericMotion(View v, MotionEvent event);
24772    }
24773
24774    /**
24775     * Interface definition for a callback to be invoked when a view has been clicked and held.
24776     */
24777    public interface OnLongClickListener {
24778        /**
24779         * Called when a view has been clicked and held.
24780         *
24781         * @param v The view that was clicked and held.
24782         *
24783         * @return true if the callback consumed the long click, false otherwise.
24784         */
24785        boolean onLongClick(View v);
24786    }
24787
24788    /**
24789     * Interface definition for a callback to be invoked when a drag is being dispatched
24790     * to this view.  The callback will be invoked before the hosting view's own
24791     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24792     * onDrag(event) behavior, it should return 'false' from this callback.
24793     *
24794     * <div class="special reference">
24795     * <h3>Developer Guides</h3>
24796     * <p>For a guide to implementing drag and drop features, read the
24797     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24798     * </div>
24799     */
24800    public interface OnDragListener {
24801        /**
24802         * Called when a drag event is dispatched to a view. This allows listeners
24803         * to get a chance to override base View behavior.
24804         *
24805         * @param v The View that received the drag event.
24806         * @param event The {@link android.view.DragEvent} object for the drag event.
24807         * @return {@code true} if the drag event was handled successfully, or {@code false}
24808         * if the drag event was not handled. Note that {@code false} will trigger the View
24809         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24810         */
24811        boolean onDrag(View v, DragEvent event);
24812    }
24813
24814    /**
24815     * Interface definition for a callback to be invoked when the focus state of
24816     * a view changed.
24817     */
24818    public interface OnFocusChangeListener {
24819        /**
24820         * Called when the focus state of a view has changed.
24821         *
24822         * @param v The view whose state has changed.
24823         * @param hasFocus The new focus state of v.
24824         */
24825        void onFocusChange(View v, boolean hasFocus);
24826    }
24827
24828    /**
24829     * Interface definition for a callback to be invoked when a view is clicked.
24830     */
24831    public interface OnClickListener {
24832        /**
24833         * Called when a view has been clicked.
24834         *
24835         * @param v The view that was clicked.
24836         */
24837        void onClick(View v);
24838    }
24839
24840    /**
24841     * Interface definition for a callback to be invoked when a view is context clicked.
24842     */
24843    public interface OnContextClickListener {
24844        /**
24845         * Called when a view is context clicked.
24846         *
24847         * @param v The view that has been context clicked.
24848         * @return true if the callback consumed the context click, false otherwise.
24849         */
24850        boolean onContextClick(View v);
24851    }
24852
24853    /**
24854     * Interface definition for a callback to be invoked when the context menu
24855     * for this view is being built.
24856     */
24857    public interface OnCreateContextMenuListener {
24858        /**
24859         * Called when the context menu for this view is being built. It is not
24860         * safe to hold onto the menu after this method returns.
24861         *
24862         * @param menu The context menu that is being built
24863         * @param v The view for which the context menu is being built
24864         * @param menuInfo Extra information about the item for which the
24865         *            context menu should be shown. This information will vary
24866         *            depending on the class of v.
24867         */
24868        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24869    }
24870
24871    /**
24872     * Interface definition for a callback to be invoked when the status bar changes
24873     * visibility.  This reports <strong>global</strong> changes to the system UI
24874     * state, not what the application is requesting.
24875     *
24876     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24877     */
24878    public interface OnSystemUiVisibilityChangeListener {
24879        /**
24880         * Called when the status bar changes visibility because of a call to
24881         * {@link View#setSystemUiVisibility(int)}.
24882         *
24883         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24884         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24885         * This tells you the <strong>global</strong> state of these UI visibility
24886         * flags, not what your app is currently applying.
24887         */
24888        public void onSystemUiVisibilityChange(int visibility);
24889    }
24890
24891    /**
24892     * Interface definition for a callback to be invoked when this view is attached
24893     * or detached from its window.
24894     */
24895    public interface OnAttachStateChangeListener {
24896        /**
24897         * Called when the view is attached to a window.
24898         * @param v The view that was attached
24899         */
24900        public void onViewAttachedToWindow(View v);
24901        /**
24902         * Called when the view is detached from a window.
24903         * @param v The view that was detached
24904         */
24905        public void onViewDetachedFromWindow(View v);
24906    }
24907
24908    /**
24909     * Listener for applying window insets on a view in a custom way.
24910     *
24911     * <p>Apps may choose to implement this interface if they want to apply custom policy
24912     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24913     * is set, its
24914     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24915     * method will be called instead of the View's own
24916     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24917     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24918     * the View's normal behavior as part of its own.</p>
24919     */
24920    public interface OnApplyWindowInsetsListener {
24921        /**
24922         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24923         * on a View, this listener method will be called instead of the view's own
24924         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24925         *
24926         * @param v The view applying window insets
24927         * @param insets The insets to apply
24928         * @return The insets supplied, minus any insets that were consumed
24929         */
24930        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24931    }
24932
24933    private final class UnsetPressedState implements Runnable {
24934        @Override
24935        public void run() {
24936            setPressed(false);
24937        }
24938    }
24939
24940    /**
24941     * When a view becomes invisible checks if autofill considers the view invisible too. This
24942     * happens after the regular removal operation to make sure the operation is finished by the
24943     * time this is called.
24944     */
24945    private static class VisibilityChangeForAutofillHandler extends Handler {
24946        private final AutofillManager mAfm;
24947        private final View mView;
24948
24949        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
24950                @NonNull View view) {
24951            mAfm = afm;
24952            mView = view;
24953        }
24954
24955        @Override
24956        public void handleMessage(Message msg) {
24957            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
24958        }
24959    }
24960
24961    /**
24962     * Base class for derived classes that want to save and restore their own
24963     * state in {@link android.view.View#onSaveInstanceState()}.
24964     */
24965    public static class BaseSavedState extends AbsSavedState {
24966        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24967        static final int IS_AUTOFILLED = 0b10;
24968        static final int ACCESSIBILITY_ID = 0b100;
24969
24970        // Flags that describe what data in this state is valid
24971        int mSavedData;
24972        String mStartActivityRequestWhoSaved;
24973        boolean mIsAutofilled;
24974        int mAccessibilityViewId;
24975
24976        /**
24977         * Constructor used when reading from a parcel. Reads the state of the superclass.
24978         *
24979         * @param source parcel to read from
24980         */
24981        public BaseSavedState(Parcel source) {
24982            this(source, null);
24983        }
24984
24985        /**
24986         * Constructor used when reading from a parcel using a given class loader.
24987         * Reads the state of the superclass.
24988         *
24989         * @param source parcel to read from
24990         * @param loader ClassLoader to use for reading
24991         */
24992        public BaseSavedState(Parcel source, ClassLoader loader) {
24993            super(source, loader);
24994            mSavedData = source.readInt();
24995            mStartActivityRequestWhoSaved = source.readString();
24996            mIsAutofilled = source.readBoolean();
24997            mAccessibilityViewId = source.readInt();
24998        }
24999
25000        /**
25001         * Constructor called by derived classes when creating their SavedState objects
25002         *
25003         * @param superState The state of the superclass of this view
25004         */
25005        public BaseSavedState(Parcelable superState) {
25006            super(superState);
25007        }
25008
25009        @Override
25010        public void writeToParcel(Parcel out, int flags) {
25011            super.writeToParcel(out, flags);
25012
25013            out.writeInt(mSavedData);
25014            out.writeString(mStartActivityRequestWhoSaved);
25015            out.writeBoolean(mIsAutofilled);
25016            out.writeInt(mAccessibilityViewId);
25017        }
25018
25019        public static final Parcelable.Creator<BaseSavedState> CREATOR
25020                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
25021            @Override
25022            public BaseSavedState createFromParcel(Parcel in) {
25023                return new BaseSavedState(in);
25024            }
25025
25026            @Override
25027            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
25028                return new BaseSavedState(in, loader);
25029            }
25030
25031            @Override
25032            public BaseSavedState[] newArray(int size) {
25033                return new BaseSavedState[size];
25034            }
25035        };
25036    }
25037
25038    /**
25039     * A set of information given to a view when it is attached to its parent
25040     * window.
25041     */
25042    final static class AttachInfo {
25043        interface Callbacks {
25044            void playSoundEffect(int effectId);
25045            boolean performHapticFeedback(int effectId, boolean always);
25046        }
25047
25048        /**
25049         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
25050         * to a Handler. This class contains the target (View) to invalidate and
25051         * the coordinates of the dirty rectangle.
25052         *
25053         * For performance purposes, this class also implements a pool of up to
25054         * POOL_LIMIT objects that get reused. This reduces memory allocations
25055         * whenever possible.
25056         */
25057        static class InvalidateInfo {
25058            private static final int POOL_LIMIT = 10;
25059
25060            private static final SynchronizedPool<InvalidateInfo> sPool =
25061                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
25062
25063            View target;
25064
25065            int left;
25066            int top;
25067            int right;
25068            int bottom;
25069
25070            public static InvalidateInfo obtain() {
25071                InvalidateInfo instance = sPool.acquire();
25072                return (instance != null) ? instance : new InvalidateInfo();
25073            }
25074
25075            public void recycle() {
25076                target = null;
25077                sPool.release(this);
25078            }
25079        }
25080
25081        final IWindowSession mSession;
25082
25083        final IWindow mWindow;
25084
25085        final IBinder mWindowToken;
25086
25087        Display mDisplay;
25088
25089        final Callbacks mRootCallbacks;
25090
25091        IWindowId mIWindowId;
25092        WindowId mWindowId;
25093
25094        /**
25095         * The top view of the hierarchy.
25096         */
25097        View mRootView;
25098
25099        IBinder mPanelParentWindowToken;
25100
25101        boolean mHardwareAccelerated;
25102        boolean mHardwareAccelerationRequested;
25103        ThreadedRenderer mThreadedRenderer;
25104        List<RenderNode> mPendingAnimatingRenderNodes;
25105
25106        /**
25107         * The state of the display to which the window is attached, as reported
25108         * by {@link Display#getState()}.  Note that the display state constants
25109         * declared by {@link Display} do not exactly line up with the screen state
25110         * constants declared by {@link View} (there are more display states than
25111         * screen states).
25112         */
25113        int mDisplayState = Display.STATE_UNKNOWN;
25114
25115        /**
25116         * Scale factor used by the compatibility mode
25117         */
25118        float mApplicationScale;
25119
25120        /**
25121         * Indicates whether the application is in compatibility mode
25122         */
25123        boolean mScalingRequired;
25124
25125        /**
25126         * Left position of this view's window
25127         */
25128        int mWindowLeft;
25129
25130        /**
25131         * Top position of this view's window
25132         */
25133        int mWindowTop;
25134
25135        /**
25136         * Indicates whether views need to use 32-bit drawing caches
25137         */
25138        boolean mUse32BitDrawingCache;
25139
25140        /**
25141         * For windows that are full-screen but using insets to layout inside
25142         * of the screen areas, these are the current insets to appear inside
25143         * the overscan area of the display.
25144         */
25145        final Rect mOverscanInsets = new Rect();
25146
25147        /**
25148         * For windows that are full-screen but using insets to layout inside
25149         * of the screen decorations, these are the current insets for the
25150         * content of the window.
25151         */
25152        final Rect mContentInsets = new Rect();
25153
25154        /**
25155         * For windows that are full-screen but using insets to layout inside
25156         * of the screen decorations, these are the current insets for the
25157         * actual visible parts of the window.
25158         */
25159        final Rect mVisibleInsets = new Rect();
25160
25161        /**
25162         * For windows that are full-screen but using insets to layout inside
25163         * of the screen decorations, these are the current insets for the
25164         * stable system windows.
25165         */
25166        final Rect mStableInsets = new Rect();
25167
25168        /**
25169         * For windows that include areas that are not covered by real surface these are the outsets
25170         * for real surface.
25171         */
25172        final Rect mOutsets = new Rect();
25173
25174        /**
25175         * In multi-window we force show the navigation bar. Because we don't want that the surface
25176         * size changes in this mode, we instead have a flag whether the navigation bar size should
25177         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
25178         */
25179        boolean mAlwaysConsumeNavBar;
25180
25181        /**
25182         * The internal insets given by this window.  This value is
25183         * supplied by the client (through
25184         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
25185         * be given to the window manager when changed to be used in laying
25186         * out windows behind it.
25187         */
25188        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
25189                = new ViewTreeObserver.InternalInsetsInfo();
25190
25191        /**
25192         * Set to true when mGivenInternalInsets is non-empty.
25193         */
25194        boolean mHasNonEmptyGivenInternalInsets;
25195
25196        /**
25197         * All views in the window's hierarchy that serve as scroll containers,
25198         * used to determine if the window can be resized or must be panned
25199         * to adjust for a soft input area.
25200         */
25201        final ArrayList<View> mScrollContainers = new ArrayList<View>();
25202
25203        final KeyEvent.DispatcherState mKeyDispatchState
25204                = new KeyEvent.DispatcherState();
25205
25206        /**
25207         * Indicates whether the view's window currently has the focus.
25208         */
25209        boolean mHasWindowFocus;
25210
25211        /**
25212         * The current visibility of the window.
25213         */
25214        int mWindowVisibility;
25215
25216        /**
25217         * Indicates the time at which drawing started to occur.
25218         */
25219        long mDrawingTime;
25220
25221        /**
25222         * Indicates whether or not ignoring the DIRTY_MASK flags.
25223         */
25224        boolean mIgnoreDirtyState;
25225
25226        /**
25227         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
25228         * to avoid clearing that flag prematurely.
25229         */
25230        boolean mSetIgnoreDirtyState = false;
25231
25232        /**
25233         * Indicates whether the view's window is currently in touch mode.
25234         */
25235        boolean mInTouchMode;
25236
25237        /**
25238         * Indicates whether the view has requested unbuffered input dispatching for the current
25239         * event stream.
25240         */
25241        boolean mUnbufferedDispatchRequested;
25242
25243        /**
25244         * Indicates that ViewAncestor should trigger a global layout change
25245         * the next time it performs a traversal
25246         */
25247        boolean mRecomputeGlobalAttributes;
25248
25249        /**
25250         * Always report new attributes at next traversal.
25251         */
25252        boolean mForceReportNewAttributes;
25253
25254        /**
25255         * Set during a traveral if any views want to keep the screen on.
25256         */
25257        boolean mKeepScreenOn;
25258
25259        /**
25260         * Set during a traveral if the light center needs to be updated.
25261         */
25262        boolean mNeedsUpdateLightCenter;
25263
25264        /**
25265         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
25266         */
25267        int mSystemUiVisibility;
25268
25269        /**
25270         * Hack to force certain system UI visibility flags to be cleared.
25271         */
25272        int mDisabledSystemUiVisibility;
25273
25274        /**
25275         * Last global system UI visibility reported by the window manager.
25276         */
25277        int mGlobalSystemUiVisibility = -1;
25278
25279        /**
25280         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
25281         * attached.
25282         */
25283        boolean mHasSystemUiListeners;
25284
25285        /**
25286         * Set if the window has requested to extend into the overscan region
25287         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
25288         */
25289        boolean mOverscanRequested;
25290
25291        /**
25292         * Set if the visibility of any views has changed.
25293         */
25294        boolean mViewVisibilityChanged;
25295
25296        /**
25297         * Set to true if a view has been scrolled.
25298         */
25299        boolean mViewScrollChanged;
25300
25301        /**
25302         * Set to true if high contrast mode enabled
25303         */
25304        boolean mHighContrastText;
25305
25306        /**
25307         * Set to true if a pointer event is currently being handled.
25308         */
25309        boolean mHandlingPointerEvent;
25310
25311        /**
25312         * Global to the view hierarchy used as a temporary for dealing with
25313         * x/y points in the transparent region computations.
25314         */
25315        final int[] mTransparentLocation = new int[2];
25316
25317        /**
25318         * Global to the view hierarchy used as a temporary for dealing with
25319         * x/y points in the ViewGroup.invalidateChild implementation.
25320         */
25321        final int[] mInvalidateChildLocation = new int[2];
25322
25323        /**
25324         * Global to the view hierarchy used as a temporary for dealing with
25325         * computing absolute on-screen location.
25326         */
25327        final int[] mTmpLocation = new int[2];
25328
25329        /**
25330         * Global to the view hierarchy used as a temporary for dealing with
25331         * x/y location when view is transformed.
25332         */
25333        final float[] mTmpTransformLocation = new float[2];
25334
25335        /**
25336         * The view tree observer used to dispatch global events like
25337         * layout, pre-draw, touch mode change, etc.
25338         */
25339        final ViewTreeObserver mTreeObserver;
25340
25341        /**
25342         * A Canvas used by the view hierarchy to perform bitmap caching.
25343         */
25344        Canvas mCanvas;
25345
25346        /**
25347         * The view root impl.
25348         */
25349        final ViewRootImpl mViewRootImpl;
25350
25351        /**
25352         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25353         * handler can be used to pump events in the UI events queue.
25354         */
25355        final Handler mHandler;
25356
25357        /**
25358         * Temporary for use in computing invalidate rectangles while
25359         * calling up the hierarchy.
25360         */
25361        final Rect mTmpInvalRect = new Rect();
25362
25363        /**
25364         * Temporary for use in computing hit areas with transformed views
25365         */
25366        final RectF mTmpTransformRect = new RectF();
25367
25368        /**
25369         * Temporary for use in computing hit areas with transformed views
25370         */
25371        final RectF mTmpTransformRect1 = new RectF();
25372
25373        /**
25374         * Temporary list of rectanges.
25375         */
25376        final List<RectF> mTmpRectList = new ArrayList<>();
25377
25378        /**
25379         * Temporary for use in transforming invalidation rect
25380         */
25381        final Matrix mTmpMatrix = new Matrix();
25382
25383        /**
25384         * Temporary for use in transforming invalidation rect
25385         */
25386        final Transformation mTmpTransformation = new Transformation();
25387
25388        /**
25389         * Temporary for use in querying outlines from OutlineProviders
25390         */
25391        final Outline mTmpOutline = new Outline();
25392
25393        /**
25394         * Temporary list for use in collecting focusable descendents of a view.
25395         */
25396        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25397
25398        /**
25399         * The id of the window for accessibility purposes.
25400         */
25401        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25402
25403        /**
25404         * Flags related to accessibility processing.
25405         *
25406         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25407         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25408         */
25409        int mAccessibilityFetchFlags;
25410
25411        /**
25412         * The drawable for highlighting accessibility focus.
25413         */
25414        Drawable mAccessibilityFocusDrawable;
25415
25416        /**
25417         * The drawable for highlighting autofilled views.
25418         *
25419         * @see #isAutofilled()
25420         */
25421        Drawable mAutofilledDrawable;
25422
25423        /**
25424         * Show where the margins, bounds and layout bounds are for each view.
25425         */
25426        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25427
25428        /**
25429         * Point used to compute visible regions.
25430         */
25431        final Point mPoint = new Point();
25432
25433        /**
25434         * Used to track which View originated a requestLayout() call, used when
25435         * requestLayout() is called during layout.
25436         */
25437        View mViewRequestingLayout;
25438
25439        /**
25440         * Used to track views that need (at least) a partial relayout at their current size
25441         * during the next traversal.
25442         */
25443        List<View> mPartialLayoutViews = new ArrayList<>();
25444
25445        /**
25446         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25447         * modification. Lazily assigned during ViewRootImpl layout.
25448         */
25449        List<View> mEmptyPartialLayoutViews;
25450
25451        /**
25452         * Used to track the identity of the current drag operation.
25453         */
25454        IBinder mDragToken;
25455
25456        /**
25457         * The drag shadow surface for the current drag operation.
25458         */
25459        public Surface mDragSurface;
25460
25461
25462        /**
25463         * The view that currently has a tooltip displayed.
25464         */
25465        View mTooltipHost;
25466
25467        /**
25468         * Creates a new set of attachment information with the specified
25469         * events handler and thread.
25470         *
25471         * @param handler the events handler the view must use
25472         */
25473        AttachInfo(IWindowSession session, IWindow window, Display display,
25474                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25475                Context context) {
25476            mSession = session;
25477            mWindow = window;
25478            mWindowToken = window.asBinder();
25479            mDisplay = display;
25480            mViewRootImpl = viewRootImpl;
25481            mHandler = handler;
25482            mRootCallbacks = effectPlayer;
25483            mTreeObserver = new ViewTreeObserver(context);
25484        }
25485    }
25486
25487    /**
25488     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25489     * is supported. This avoids keeping too many unused fields in most
25490     * instances of View.</p>
25491     */
25492    private static class ScrollabilityCache implements Runnable {
25493
25494        /**
25495         * Scrollbars are not visible
25496         */
25497        public static final int OFF = 0;
25498
25499        /**
25500         * Scrollbars are visible
25501         */
25502        public static final int ON = 1;
25503
25504        /**
25505         * Scrollbars are fading away
25506         */
25507        public static final int FADING = 2;
25508
25509        public boolean fadeScrollBars;
25510
25511        public int fadingEdgeLength;
25512        public int scrollBarDefaultDelayBeforeFade;
25513        public int scrollBarFadeDuration;
25514
25515        public int scrollBarSize;
25516        public int scrollBarMinTouchTarget;
25517        public ScrollBarDrawable scrollBar;
25518        public float[] interpolatorValues;
25519        public View host;
25520
25521        public final Paint paint;
25522        public final Matrix matrix;
25523        public Shader shader;
25524
25525        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25526
25527        private static final float[] OPAQUE = { 255 };
25528        private static final float[] TRANSPARENT = { 0.0f };
25529
25530        /**
25531         * When fading should start. This time moves into the future every time
25532         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25533         */
25534        public long fadeStartTime;
25535
25536
25537        /**
25538         * The current state of the scrollbars: ON, OFF, or FADING
25539         */
25540        public int state = OFF;
25541
25542        private int mLastColor;
25543
25544        public final Rect mScrollBarBounds = new Rect();
25545        public final Rect mScrollBarTouchBounds = new Rect();
25546
25547        public static final int NOT_DRAGGING = 0;
25548        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25549        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25550        public int mScrollBarDraggingState = NOT_DRAGGING;
25551
25552        public float mScrollBarDraggingPos = 0;
25553
25554        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25555            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25556            scrollBarSize = configuration.getScaledScrollBarSize();
25557            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25558            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25559            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25560
25561            paint = new Paint();
25562            matrix = new Matrix();
25563            // use use a height of 1, and then wack the matrix each time we
25564            // actually use it.
25565            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25566            paint.setShader(shader);
25567            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25568
25569            this.host = host;
25570        }
25571
25572        public void setFadeColor(int color) {
25573            if (color != mLastColor) {
25574                mLastColor = color;
25575
25576                if (color != 0) {
25577                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25578                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25579                    paint.setShader(shader);
25580                    // Restore the default transfer mode (src_over)
25581                    paint.setXfermode(null);
25582                } else {
25583                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25584                    paint.setShader(shader);
25585                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25586                }
25587            }
25588        }
25589
25590        public void run() {
25591            long now = AnimationUtils.currentAnimationTimeMillis();
25592            if (now >= fadeStartTime) {
25593
25594                // the animation fades the scrollbars out by changing
25595                // the opacity (alpha) from fully opaque to fully
25596                // transparent
25597                int nextFrame = (int) now;
25598                int framesCount = 0;
25599
25600                Interpolator interpolator = scrollBarInterpolator;
25601
25602                // Start opaque
25603                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25604
25605                // End transparent
25606                nextFrame += scrollBarFadeDuration;
25607                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25608
25609                state = FADING;
25610
25611                // Kick off the fade animation
25612                host.invalidate(true);
25613            }
25614        }
25615    }
25616
25617    /**
25618     * Resuable callback for sending
25619     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25620     */
25621    private class SendViewScrolledAccessibilityEvent implements Runnable {
25622        public volatile boolean mIsPending;
25623
25624        public void run() {
25625            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25626            mIsPending = false;
25627        }
25628    }
25629
25630    /**
25631     * <p>
25632     * This class represents a delegate that can be registered in a {@link View}
25633     * to enhance accessibility support via composition rather via inheritance.
25634     * It is specifically targeted to widget developers that extend basic View
25635     * classes i.e. classes in package android.view, that would like their
25636     * applications to be backwards compatible.
25637     * </p>
25638     * <div class="special reference">
25639     * <h3>Developer Guides</h3>
25640     * <p>For more information about making applications accessible, read the
25641     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25642     * developer guide.</p>
25643     * </div>
25644     * <p>
25645     * A scenario in which a developer would like to use an accessibility delegate
25646     * is overriding a method introduced in a later API version than the minimal API
25647     * version supported by the application. For example, the method
25648     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25649     * in API version 4 when the accessibility APIs were first introduced. If a
25650     * developer would like his application to run on API version 4 devices (assuming
25651     * all other APIs used by the application are version 4 or lower) and take advantage
25652     * of this method, instead of overriding the method which would break the application's
25653     * backwards compatibility, he can override the corresponding method in this
25654     * delegate and register the delegate in the target View if the API version of
25655     * the system is high enough, i.e. the API version is the same as or higher than the API
25656     * version that introduced
25657     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25658     * </p>
25659     * <p>
25660     * Here is an example implementation:
25661     * </p>
25662     * <code><pre><p>
25663     * if (Build.VERSION.SDK_INT >= 14) {
25664     *     // If the API version is equal of higher than the version in
25665     *     // which onInitializeAccessibilityNodeInfo was introduced we
25666     *     // register a delegate with a customized implementation.
25667     *     View view = findViewById(R.id.view_id);
25668     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25669     *         public void onInitializeAccessibilityNodeInfo(View host,
25670     *                 AccessibilityNodeInfo info) {
25671     *             // Let the default implementation populate the info.
25672     *             super.onInitializeAccessibilityNodeInfo(host, info);
25673     *             // Set some other information.
25674     *             info.setEnabled(host.isEnabled());
25675     *         }
25676     *     });
25677     * }
25678     * </code></pre></p>
25679     * <p>
25680     * This delegate contains methods that correspond to the accessibility methods
25681     * in View. If a delegate has been specified the implementation in View hands
25682     * off handling to the corresponding method in this delegate. The default
25683     * implementation the delegate methods behaves exactly as the corresponding
25684     * method in View for the case of no accessibility delegate been set. Hence,
25685     * to customize the behavior of a View method, clients can override only the
25686     * corresponding delegate method without altering the behavior of the rest
25687     * accessibility related methods of the host view.
25688     * </p>
25689     * <p>
25690     * <strong>Note:</strong> On platform versions prior to
25691     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25692     * views in the {@code android.widget.*} package are called <i>before</i>
25693     * host methods. This prevents certain properties such as class name from
25694     * being modified by overriding
25695     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25696     * as any changes will be overwritten by the host class.
25697     * <p>
25698     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25699     * methods are called <i>after</i> host methods, which all properties to be
25700     * modified without being overwritten by the host class.
25701     */
25702    public static class AccessibilityDelegate {
25703
25704        /**
25705         * Sends an accessibility event of the given type. If accessibility is not
25706         * enabled this method has no effect.
25707         * <p>
25708         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25709         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25710         * been set.
25711         * </p>
25712         *
25713         * @param host The View hosting the delegate.
25714         * @param eventType The type of the event to send.
25715         *
25716         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25717         */
25718        public void sendAccessibilityEvent(View host, int eventType) {
25719            host.sendAccessibilityEventInternal(eventType);
25720        }
25721
25722        /**
25723         * Performs the specified accessibility action on the view. For
25724         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25725         * <p>
25726         * The default implementation behaves as
25727         * {@link View#performAccessibilityAction(int, Bundle)
25728         *  View#performAccessibilityAction(int, Bundle)} for the case of
25729         *  no accessibility delegate been set.
25730         * </p>
25731         *
25732         * @param action The action to perform.
25733         * @return Whether the action was performed.
25734         *
25735         * @see View#performAccessibilityAction(int, Bundle)
25736         *      View#performAccessibilityAction(int, Bundle)
25737         */
25738        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25739            return host.performAccessibilityActionInternal(action, args);
25740        }
25741
25742        /**
25743         * Sends an accessibility event. This method behaves exactly as
25744         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25745         * empty {@link AccessibilityEvent} and does not perform a check whether
25746         * accessibility is enabled.
25747         * <p>
25748         * The default implementation behaves as
25749         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25750         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25751         * the case of no accessibility delegate been set.
25752         * </p>
25753         *
25754         * @param host The View hosting the delegate.
25755         * @param event The event to send.
25756         *
25757         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25758         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25759         */
25760        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25761            host.sendAccessibilityEventUncheckedInternal(event);
25762        }
25763
25764        /**
25765         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25766         * to its children for adding their text content to the event.
25767         * <p>
25768         * The default implementation behaves as
25769         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25770         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25771         * the case of no accessibility delegate been set.
25772         * </p>
25773         *
25774         * @param host The View hosting the delegate.
25775         * @param event The event.
25776         * @return True if the event population was completed.
25777         *
25778         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25779         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25780         */
25781        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25782            return host.dispatchPopulateAccessibilityEventInternal(event);
25783        }
25784
25785        /**
25786         * Gives a chance to the host View to populate the accessibility event with its
25787         * text content.
25788         * <p>
25789         * The default implementation behaves as
25790         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25791         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25792         * the case of no accessibility delegate been set.
25793         * </p>
25794         *
25795         * @param host The View hosting the delegate.
25796         * @param event The accessibility event which to populate.
25797         *
25798         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25799         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25800         */
25801        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25802            host.onPopulateAccessibilityEventInternal(event);
25803        }
25804
25805        /**
25806         * Initializes an {@link AccessibilityEvent} with information about the
25807         * the host View which is the event source.
25808         * <p>
25809         * The default implementation behaves as
25810         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25811         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25812         * the case of no accessibility delegate been set.
25813         * </p>
25814         *
25815         * @param host The View hosting the delegate.
25816         * @param event The event to initialize.
25817         *
25818         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25819         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25820         */
25821        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25822            host.onInitializeAccessibilityEventInternal(event);
25823        }
25824
25825        /**
25826         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25827         * <p>
25828         * The default implementation behaves as
25829         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25830         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25831         * the case of no accessibility delegate been set.
25832         * </p>
25833         *
25834         * @param host The View hosting the delegate.
25835         * @param info The instance to initialize.
25836         *
25837         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25838         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25839         */
25840        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25841            host.onInitializeAccessibilityNodeInfoInternal(info);
25842        }
25843
25844        /**
25845         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25846         * additional data.
25847         * <p>
25848         * This method only needs to be implemented if the View offers to provide additional data.
25849         * </p>
25850         * <p>
25851         * The default implementation behaves as
25852         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25853         * the case where no accessibility delegate is set.
25854         * </p>
25855         *
25856         * @param host The View hosting the delegate. Never {@code null}.
25857         * @param info The info to which to add the extra data. Never {@code null}.
25858         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25859         *                     extra data should be added to the {@link Bundle} returned by
25860         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25861         *                     {@code null}.
25862         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25863         *                  May be {@code null} if the if the service provided no arguments.
25864         *
25865         * @see AccessibilityNodeInfo#setExtraAvailableData
25866         */
25867        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25868                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25869                @Nullable Bundle arguments) {
25870            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25871        }
25872
25873        /**
25874         * Called when a child of the host View has requested sending an
25875         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25876         * to augment the event.
25877         * <p>
25878         * The default implementation behaves as
25879         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25880         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25881         * the case of no accessibility delegate been set.
25882         * </p>
25883         *
25884         * @param host The View hosting the delegate.
25885         * @param child The child which requests sending the event.
25886         * @param event The event to be sent.
25887         * @return True if the event should be sent
25888         *
25889         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25890         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25891         */
25892        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25893                AccessibilityEvent event) {
25894            return host.onRequestSendAccessibilityEventInternal(child, event);
25895        }
25896
25897        /**
25898         * Gets the provider for managing a virtual view hierarchy rooted at this View
25899         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25900         * that explore the window content.
25901         * <p>
25902         * The default implementation behaves as
25903         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25904         * the case of no accessibility delegate been set.
25905         * </p>
25906         *
25907         * @return The provider.
25908         *
25909         * @see AccessibilityNodeProvider
25910         */
25911        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25912            return null;
25913        }
25914
25915        /**
25916         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25917         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25918         * This method is responsible for obtaining an accessibility node info from a
25919         * pool of reusable instances and calling
25920         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25921         * view to initialize the former.
25922         * <p>
25923         * <strong>Note:</strong> The client is responsible for recycling the obtained
25924         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25925         * creation.
25926         * </p>
25927         * <p>
25928         * The default implementation behaves as
25929         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25930         * the case of no accessibility delegate been set.
25931         * </p>
25932         * @return A populated {@link AccessibilityNodeInfo}.
25933         *
25934         * @see AccessibilityNodeInfo
25935         *
25936         * @hide
25937         */
25938        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25939            return host.createAccessibilityNodeInfoInternal();
25940        }
25941    }
25942
25943    private static class MatchIdPredicate implements Predicate<View> {
25944        public int mId;
25945
25946        @Override
25947        public boolean test(View view) {
25948            return (view.mID == mId);
25949        }
25950    }
25951
25952    private static class MatchLabelForPredicate implements Predicate<View> {
25953        private int mLabeledId;
25954
25955        @Override
25956        public boolean test(View view) {
25957            return (view.mLabelForId == mLabeledId);
25958        }
25959    }
25960
25961    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25962        private int mChangeTypes = 0;
25963        private boolean mPosted;
25964        private boolean mPostedWithDelay;
25965        private long mLastEventTimeMillis;
25966
25967        @Override
25968        public void run() {
25969            mPosted = false;
25970            mPostedWithDelay = false;
25971            mLastEventTimeMillis = SystemClock.uptimeMillis();
25972            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25973                final AccessibilityEvent event = AccessibilityEvent.obtain();
25974                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25975                event.setContentChangeTypes(mChangeTypes);
25976                sendAccessibilityEventUnchecked(event);
25977            }
25978            mChangeTypes = 0;
25979        }
25980
25981        public void runOrPost(int changeType) {
25982            mChangeTypes |= changeType;
25983
25984            // If this is a live region or the child of a live region, collect
25985            // all events from this frame and send them on the next frame.
25986            if (inLiveRegion()) {
25987                // If we're already posted with a delay, remove that.
25988                if (mPostedWithDelay) {
25989                    removeCallbacks(this);
25990                    mPostedWithDelay = false;
25991                }
25992                // Only post if we're not already posted.
25993                if (!mPosted) {
25994                    post(this);
25995                    mPosted = true;
25996                }
25997                return;
25998            }
25999
26000            if (mPosted) {
26001                return;
26002            }
26003
26004            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
26005            final long minEventIntevalMillis =
26006                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
26007            if (timeSinceLastMillis >= minEventIntevalMillis) {
26008                removeCallbacks(this);
26009                run();
26010            } else {
26011                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
26012                mPostedWithDelay = true;
26013            }
26014        }
26015    }
26016
26017    private boolean inLiveRegion() {
26018        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
26019            return true;
26020        }
26021
26022        ViewParent parent = getParent();
26023        while (parent instanceof View) {
26024            if (((View) parent).getAccessibilityLiveRegion()
26025                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
26026                return true;
26027            }
26028            parent = parent.getParent();
26029        }
26030
26031        return false;
26032    }
26033
26034    /**
26035     * Dump all private flags in readable format, useful for documentation and
26036     * sanity checking.
26037     */
26038    private static void dumpFlags() {
26039        final HashMap<String, String> found = Maps.newHashMap();
26040        try {
26041            for (Field field : View.class.getDeclaredFields()) {
26042                final int modifiers = field.getModifiers();
26043                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
26044                    if (field.getType().equals(int.class)) {
26045                        final int value = field.getInt(null);
26046                        dumpFlag(found, field.getName(), value);
26047                    } else if (field.getType().equals(int[].class)) {
26048                        final int[] values = (int[]) field.get(null);
26049                        for (int i = 0; i < values.length; i++) {
26050                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
26051                        }
26052                    }
26053                }
26054            }
26055        } catch (IllegalAccessException e) {
26056            throw new RuntimeException(e);
26057        }
26058
26059        final ArrayList<String> keys = Lists.newArrayList();
26060        keys.addAll(found.keySet());
26061        Collections.sort(keys);
26062        for (String key : keys) {
26063            Log.d(VIEW_LOG_TAG, found.get(key));
26064        }
26065    }
26066
26067    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
26068        // Sort flags by prefix, then by bits, always keeping unique keys
26069        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
26070        final int prefix = name.indexOf('_');
26071        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
26072        final String output = bits + " " + name;
26073        found.put(key, output);
26074    }
26075
26076    /** {@hide} */
26077    public void encode(@NonNull ViewHierarchyEncoder stream) {
26078        stream.beginObject(this);
26079        encodeProperties(stream);
26080        stream.endObject();
26081    }
26082
26083    /** {@hide} */
26084    @CallSuper
26085    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
26086        Object resolveId = ViewDebug.resolveId(getContext(), mID);
26087        if (resolveId instanceof String) {
26088            stream.addProperty("id", (String) resolveId);
26089        } else {
26090            stream.addProperty("id", mID);
26091        }
26092
26093        stream.addProperty("misc:transformation.alpha",
26094                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
26095        stream.addProperty("misc:transitionName", getTransitionName());
26096
26097        // layout
26098        stream.addProperty("layout:left", mLeft);
26099        stream.addProperty("layout:right", mRight);
26100        stream.addProperty("layout:top", mTop);
26101        stream.addProperty("layout:bottom", mBottom);
26102        stream.addProperty("layout:width", getWidth());
26103        stream.addProperty("layout:height", getHeight());
26104        stream.addProperty("layout:layoutDirection", getLayoutDirection());
26105        stream.addProperty("layout:layoutRtl", isLayoutRtl());
26106        stream.addProperty("layout:hasTransientState", hasTransientState());
26107        stream.addProperty("layout:baseline", getBaseline());
26108
26109        // layout params
26110        ViewGroup.LayoutParams layoutParams = getLayoutParams();
26111        if (layoutParams != null) {
26112            stream.addPropertyKey("layoutParams");
26113            layoutParams.encode(stream);
26114        }
26115
26116        // scrolling
26117        stream.addProperty("scrolling:scrollX", mScrollX);
26118        stream.addProperty("scrolling:scrollY", mScrollY);
26119
26120        // padding
26121        stream.addProperty("padding:paddingLeft", mPaddingLeft);
26122        stream.addProperty("padding:paddingRight", mPaddingRight);
26123        stream.addProperty("padding:paddingTop", mPaddingTop);
26124        stream.addProperty("padding:paddingBottom", mPaddingBottom);
26125        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
26126        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
26127        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
26128        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
26129        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
26130
26131        // measurement
26132        stream.addProperty("measurement:minHeight", mMinHeight);
26133        stream.addProperty("measurement:minWidth", mMinWidth);
26134        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
26135        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
26136
26137        // drawing
26138        stream.addProperty("drawing:elevation", getElevation());
26139        stream.addProperty("drawing:translationX", getTranslationX());
26140        stream.addProperty("drawing:translationY", getTranslationY());
26141        stream.addProperty("drawing:translationZ", getTranslationZ());
26142        stream.addProperty("drawing:rotation", getRotation());
26143        stream.addProperty("drawing:rotationX", getRotationX());
26144        stream.addProperty("drawing:rotationY", getRotationY());
26145        stream.addProperty("drawing:scaleX", getScaleX());
26146        stream.addProperty("drawing:scaleY", getScaleY());
26147        stream.addProperty("drawing:pivotX", getPivotX());
26148        stream.addProperty("drawing:pivotY", getPivotY());
26149        stream.addProperty("drawing:opaque", isOpaque());
26150        stream.addProperty("drawing:alpha", getAlpha());
26151        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
26152        stream.addProperty("drawing:shadow", hasShadow());
26153        stream.addProperty("drawing:solidColor", getSolidColor());
26154        stream.addProperty("drawing:layerType", mLayerType);
26155        stream.addProperty("drawing:willNotDraw", willNotDraw());
26156        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
26157        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
26158        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
26159        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
26160
26161        // focus
26162        stream.addProperty("focus:hasFocus", hasFocus());
26163        stream.addProperty("focus:isFocused", isFocused());
26164        stream.addProperty("focus:focusable", getFocusable());
26165        stream.addProperty("focus:isFocusable", isFocusable());
26166        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
26167
26168        stream.addProperty("misc:clickable", isClickable());
26169        stream.addProperty("misc:pressed", isPressed());
26170        stream.addProperty("misc:selected", isSelected());
26171        stream.addProperty("misc:touchMode", isInTouchMode());
26172        stream.addProperty("misc:hovered", isHovered());
26173        stream.addProperty("misc:activated", isActivated());
26174
26175        stream.addProperty("misc:visibility", getVisibility());
26176        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
26177        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
26178
26179        stream.addProperty("misc:enabled", isEnabled());
26180        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
26181        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
26182
26183        // theme attributes
26184        Resources.Theme theme = getContext().getTheme();
26185        if (theme != null) {
26186            stream.addPropertyKey("theme");
26187            theme.encode(stream);
26188        }
26189
26190        // view attribute information
26191        int n = mAttributes != null ? mAttributes.length : 0;
26192        stream.addProperty("meta:__attrCount__", n/2);
26193        for (int i = 0; i < n; i += 2) {
26194            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
26195        }
26196
26197        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
26198
26199        // text
26200        stream.addProperty("text:textDirection", getTextDirection());
26201        stream.addProperty("text:textAlignment", getTextAlignment());
26202
26203        // accessibility
26204        CharSequence contentDescription = getContentDescription();
26205        stream.addProperty("accessibility:contentDescription",
26206                contentDescription == null ? "" : contentDescription.toString());
26207        stream.addProperty("accessibility:labelFor", getLabelFor());
26208        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
26209    }
26210
26211    /**
26212     * Determine if this view is rendered on a round wearable device and is the main view
26213     * on the screen.
26214     */
26215    boolean shouldDrawRoundScrollbar() {
26216        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
26217            return false;
26218        }
26219
26220        final View rootView = getRootView();
26221        final WindowInsets insets = getRootWindowInsets();
26222
26223        int height = getHeight();
26224        int width = getWidth();
26225        int displayHeight = rootView.getHeight();
26226        int displayWidth = rootView.getWidth();
26227
26228        if (height != displayHeight || width != displayWidth) {
26229            return false;
26230        }
26231
26232        getLocationInWindow(mAttachInfo.mTmpLocation);
26233        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
26234                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
26235    }
26236
26237    /**
26238     * Sets the tooltip text which will be displayed in a small popup next to the view.
26239     * <p>
26240     * The tooltip will be displayed:
26241     * <ul>
26242     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
26243     * menu). </li>
26244     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
26245     * </ul>
26246     * <p>
26247     * <strong>Note:</strong> Do not override this method, as it will have no
26248     * effect on the text displayed in the tooltip.
26249     *
26250     * @param tooltipText the tooltip text, or null if no tooltip is required
26251     * @see #getTooltipText()
26252     * @attr ref android.R.styleable#View_tooltipText
26253     */
26254    public void setTooltipText(@Nullable CharSequence tooltipText) {
26255        if (TextUtils.isEmpty(tooltipText)) {
26256            setFlags(0, TOOLTIP);
26257            hideTooltip();
26258            mTooltipInfo = null;
26259        } else {
26260            setFlags(TOOLTIP, TOOLTIP);
26261            if (mTooltipInfo == null) {
26262                mTooltipInfo = new TooltipInfo();
26263                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
26264                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
26265            }
26266            mTooltipInfo.mTooltipText = tooltipText;
26267            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
26268                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
26269            }
26270        }
26271    }
26272
26273    /**
26274     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26275     */
26276    public void setTooltip(@Nullable CharSequence tooltipText) {
26277        setTooltipText(tooltipText);
26278    }
26279
26280    /**
26281     * Returns the view's tooltip text.
26282     *
26283     * <strong>Note:</strong> Do not override this method, as it will have no
26284     * effect on the text displayed in the tooltip. You must call
26285     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
26286     *
26287     * @return the tooltip text
26288     * @see #setTooltipText(CharSequence)
26289     * @attr ref android.R.styleable#View_tooltipText
26290     */
26291    @Nullable
26292    public CharSequence getTooltipText() {
26293        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
26294    }
26295
26296    /**
26297     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26298     */
26299    @Nullable
26300    public CharSequence getTooltip() {
26301        return getTooltipText();
26302    }
26303
26304    private boolean showTooltip(int x, int y, boolean fromLongClick) {
26305        if (mAttachInfo == null || mTooltipInfo == null) {
26306            return false;
26307        }
26308        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
26309            return false;
26310        }
26311        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
26312            return false;
26313        }
26314        hideTooltip();
26315        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
26316        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
26317        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
26318        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
26319        mAttachInfo.mTooltipHost = this;
26320        return true;
26321    }
26322
26323    void hideTooltip() {
26324        if (mTooltipInfo == null) {
26325            return;
26326        }
26327        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26328        if (mTooltipInfo.mTooltipPopup == null) {
26329            return;
26330        }
26331        mTooltipInfo.mTooltipPopup.hide();
26332        mTooltipInfo.mTooltipPopup = null;
26333        mTooltipInfo.mTooltipFromLongClick = false;
26334        if (mAttachInfo != null) {
26335            mAttachInfo.mTooltipHost = null;
26336        }
26337    }
26338
26339    private boolean showLongClickTooltip(int x, int y) {
26340        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26341        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26342        return showTooltip(x, y, true);
26343    }
26344
26345    private void showHoverTooltip() {
26346        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
26347    }
26348
26349    boolean dispatchTooltipHoverEvent(MotionEvent event) {
26350        if (mTooltipInfo == null) {
26351            return false;
26352        }
26353        switch(event.getAction()) {
26354            case MotionEvent.ACTION_HOVER_MOVE:
26355                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
26356                    break;
26357                }
26358                if (!mTooltipInfo.mTooltipFromLongClick) {
26359                    if (mTooltipInfo.mTooltipPopup == null) {
26360                        // Schedule showing the tooltip after a timeout.
26361                        mTooltipInfo.mAnchorX = (int) event.getX();
26362                        mTooltipInfo.mAnchorY = (int) event.getY();
26363                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26364                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
26365                                ViewConfiguration.getHoverTooltipShowTimeout());
26366                    }
26367
26368                    // Hide hover-triggered tooltip after a period of inactivity.
26369                    // Match the timeout used by NativeInputManager to hide the mouse pointer
26370                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26371                    final int timeout;
26372                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26373                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
26374                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26375                    } else {
26376                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26377                    }
26378                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26379                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26380                }
26381                return true;
26382
26383            case MotionEvent.ACTION_HOVER_EXIT:
26384                if (!mTooltipInfo.mTooltipFromLongClick) {
26385                    hideTooltip();
26386                }
26387                break;
26388        }
26389        return false;
26390    }
26391
26392    void handleTooltipKey(KeyEvent event) {
26393        switch (event.getAction()) {
26394            case KeyEvent.ACTION_DOWN:
26395                if (event.getRepeatCount() == 0) {
26396                    hideTooltip();
26397                }
26398                break;
26399
26400            case KeyEvent.ACTION_UP:
26401                handleTooltipUp();
26402                break;
26403        }
26404    }
26405
26406    private void handleTooltipUp() {
26407        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26408            return;
26409        }
26410        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26411        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26412                ViewConfiguration.getLongPressTooltipHideTimeout());
26413    }
26414
26415    private int getFocusableAttribute(TypedArray attributes) {
26416        TypedValue val = new TypedValue();
26417        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26418            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26419                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26420            } else {
26421                return val.data;
26422            }
26423        } else {
26424            return FOCUSABLE_AUTO;
26425        }
26426    }
26427
26428    /**
26429     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26430     * is not showing.
26431     * @hide
26432     */
26433    @TestApi
26434    public View getTooltipView() {
26435        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26436            return null;
26437        }
26438        return mTooltipInfo.mTooltipPopup.getContentView();
26439    }
26440}
26441