View.java revision b7daaf8b5f9a41f92da58d86bf4be758ac27df6c
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.Parcel;
70import android.os.Parcelable;
71import android.os.RemoteException;
72import android.os.SystemClock;
73import android.os.SystemProperties;
74import android.os.Trace;
75import android.text.TextUtils;
76import android.util.AttributeSet;
77import android.util.FloatProperty;
78import android.util.LayoutDirection;
79import android.util.Log;
80import android.util.LongSparseLongArray;
81import android.util.Pools.SynchronizedPool;
82import android.util.Property;
83import android.util.SparseArray;
84import android.util.StateSet;
85import android.util.SuperNotCalledException;
86import android.util.TypedValue;
87import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
88import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
89import android.view.AccessibilityIterators.TextSegmentIterator;
90import android.view.AccessibilityIterators.WordTextSegmentIterator;
91import android.view.ContextMenu.ContextMenuInfo;
92import android.view.accessibility.AccessibilityEvent;
93import android.view.accessibility.AccessibilityEventSource;
94import android.view.accessibility.AccessibilityManager;
95import android.view.accessibility.AccessibilityNodeInfo;
96import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
97import android.view.accessibility.AccessibilityNodeProvider;
98import android.view.accessibility.AccessibilityWindowInfo;
99import android.view.animation.Animation;
100import android.view.animation.AnimationUtils;
101import android.view.animation.Transformation;
102import android.view.autofill.AutofillManager;
103import android.view.autofill.AutofillValue;
104import android.view.inputmethod.EditorInfo;
105import android.view.inputmethod.InputConnection;
106import android.view.inputmethod.InputMethodManager;
107import android.widget.Checkable;
108import android.widget.FrameLayout;
109import android.widget.ScrollBarDrawable;
110
111import com.android.internal.R;
112import com.android.internal.util.Preconditions;
113import com.android.internal.view.TooltipPopup;
114import com.android.internal.view.menu.MenuBuilder;
115import com.android.internal.widget.ScrollBarUtils;
116
117import com.google.android.collect.Lists;
118import com.google.android.collect.Maps;
119
120import java.lang.annotation.Retention;
121import java.lang.annotation.RetentionPolicy;
122import java.lang.ref.WeakReference;
123import java.lang.reflect.Field;
124import java.lang.reflect.InvocationTargetException;
125import java.lang.reflect.Method;
126import java.lang.reflect.Modifier;
127import java.util.ArrayList;
128import java.util.Arrays;
129import java.util.Collection;
130import java.util.Collections;
131import java.util.HashMap;
132import java.util.List;
133import java.util.Locale;
134import java.util.Map;
135import java.util.concurrent.CopyOnWriteArrayList;
136import java.util.concurrent.atomic.AtomicInteger;
137import java.util.function.Predicate;
138
139/**
140 * <p>
141 * This class represents the basic building block for user interface components. A View
142 * occupies a rectangular area on the screen and is responsible for drawing and
143 * event handling. View is the base class for <em>widgets</em>, which are
144 * used to create interactive UI components (buttons, text fields, etc.). The
145 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
146 * are invisible containers that hold other Views (or other ViewGroups) and define
147 * their layout properties.
148 * </p>
149 *
150 * <div class="special reference">
151 * <h3>Developer Guides</h3>
152 * <p>For information about using this class to develop your application's user interface,
153 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
154 * </div>
155 *
156 * <a name="Using"></a>
157 * <h3>Using Views</h3>
158 * <p>
159 * All of the views in a window are arranged in a single tree. You can add views
160 * either from code or by specifying a tree of views in one or more XML layout
161 * files. There are many specialized subclasses of views that act as controls or
162 * are capable of displaying text, images, or other content.
163 * </p>
164 * <p>
165 * Once you have created a tree of views, there are typically a few types of
166 * common operations you may wish to perform:
167 * <ul>
168 * <li><strong>Set properties:</strong> for example setting the text of a
169 * {@link android.widget.TextView}. The available properties and the methods
170 * that set them will vary among the different subclasses of views. Note that
171 * properties that are known at build time can be set in the XML layout
172 * files.</li>
173 * <li><strong>Set focus:</strong> The framework will handle moving focus in
174 * response to user input. To force focus to a specific view, call
175 * {@link #requestFocus}.</li>
176 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
177 * that will be notified when something interesting happens to the view. For
178 * example, all views will let you set a listener to be notified when the view
179 * gains or loses focus. You can register such a listener using
180 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
181 * Other view subclasses offer more specialized listeners. For example, a Button
182 * exposes a listener to notify clients when the button is clicked.</li>
183 * <li><strong>Set visibility:</strong> You can hide or show views using
184 * {@link #setVisibility(int)}.</li>
185 * </ul>
186 * </p>
187 * <p><em>
188 * Note: The Android framework is responsible for measuring, laying out and
189 * drawing views. You should not call methods that perform these actions on
190 * views yourself unless you are actually implementing a
191 * {@link android.view.ViewGroup}.
192 * </em></p>
193 *
194 * <a name="Lifecycle"></a>
195 * <h3>Implementing a Custom View</h3>
196 *
197 * <p>
198 * To implement a custom view, you will usually begin by providing overrides for
199 * some of the standard methods that the framework calls on all views. You do
200 * not need to override all of these methods. In fact, you can start by just
201 * overriding {@link #onDraw(android.graphics.Canvas)}.
202 * <table border="2" width="85%" align="center" cellpadding="5">
203 *     <thead>
204 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
205 *     </thead>
206 *
207 *     <tbody>
208 *     <tr>
209 *         <td rowspan="2">Creation</td>
210 *         <td>Constructors</td>
211 *         <td>There is a form of the constructor that are called when the view
212 *         is created from code and a form that is called when the view is
213 *         inflated from a layout file. The second form should parse and apply
214 *         any attributes defined in the layout file.
215 *         </td>
216 *     </tr>
217 *     <tr>
218 *         <td><code>{@link #onFinishInflate()}</code></td>
219 *         <td>Called after a view and all of its children has been inflated
220 *         from XML.</td>
221 *     </tr>
222 *
223 *     <tr>
224 *         <td rowspan="3">Layout</td>
225 *         <td><code>{@link #onMeasure(int, int)}</code></td>
226 *         <td>Called to determine the size requirements for this view and all
227 *         of its children.
228 *         </td>
229 *     </tr>
230 *     <tr>
231 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
232 *         <td>Called when this view should assign a size and position to all
233 *         of its children.
234 *         </td>
235 *     </tr>
236 *     <tr>
237 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
238 *         <td>Called when the size of this view has changed.
239 *         </td>
240 *     </tr>
241 *
242 *     <tr>
243 *         <td>Drawing</td>
244 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
245 *         <td>Called when the view should render its content.
246 *         </td>
247 *     </tr>
248 *
249 *     <tr>
250 *         <td rowspan="4">Event processing</td>
251 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
252 *         <td>Called when a new hardware key event occurs.
253 *         </td>
254 *     </tr>
255 *     <tr>
256 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
257 *         <td>Called when a hardware key up event occurs.
258 *         </td>
259 *     </tr>
260 *     <tr>
261 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
262 *         <td>Called when a trackball motion event occurs.
263 *         </td>
264 *     </tr>
265 *     <tr>
266 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
267 *         <td>Called when a touch screen motion event occurs.
268 *         </td>
269 *     </tr>
270 *
271 *     <tr>
272 *         <td rowspan="2">Focus</td>
273 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
274 *         <td>Called when the view gains or loses focus.
275 *         </td>
276 *     </tr>
277 *
278 *     <tr>
279 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
280 *         <td>Called when the window containing the view gains or loses focus.
281 *         </td>
282 *     </tr>
283 *
284 *     <tr>
285 *         <td rowspan="3">Attaching</td>
286 *         <td><code>{@link #onAttachedToWindow()}</code></td>
287 *         <td>Called when the view is attached to a window.
288 *         </td>
289 *     </tr>
290 *
291 *     <tr>
292 *         <td><code>{@link #onDetachedFromWindow}</code></td>
293 *         <td>Called when the view is detached from its window.
294 *         </td>
295 *     </tr>
296 *
297 *     <tr>
298 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
299 *         <td>Called when the visibility of the window containing the view
300 *         has changed.
301 *         </td>
302 *     </tr>
303 *     </tbody>
304 *
305 * </table>
306 * </p>
307 *
308 * <a name="IDs"></a>
309 * <h3>IDs</h3>
310 * Views may have an integer id associated with them. These ids are typically
311 * assigned in the layout XML files, and are used to find specific views within
312 * the view tree. A common pattern is to:
313 * <ul>
314 * <li>Define a Button in the layout file and assign it a unique ID.
315 * <pre>
316 * &lt;Button
317 *     android:id="@+id/my_button"
318 *     android:layout_width="wrap_content"
319 *     android:layout_height="wrap_content"
320 *     android:text="@string/my_button_text"/&gt;
321 * </pre></li>
322 * <li>From the onCreate method of an Activity, find the Button
323 * <pre class="prettyprint">
324 *      Button myButton = (Button) findViewById(R.id.my_button);
325 * </pre></li>
326 * </ul>
327 * <p>
328 * View IDs need not be unique throughout the tree, but it is good practice to
329 * ensure that they are at least unique within the part of the tree you are
330 * searching.
331 * </p>
332 *
333 * <a name="Position"></a>
334 * <h3>Position</h3>
335 * <p>
336 * The geometry of a view is that of a rectangle. A view has a location,
337 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
338 * two dimensions, expressed as a width and a height. The unit for location
339 * and dimensions is the pixel.
340 * </p>
341 *
342 * <p>
343 * It is possible to retrieve the location of a view by invoking the methods
344 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
345 * coordinate of the rectangle representing the view. The latter returns the
346 * top, or Y, coordinate of the rectangle representing the view. These methods
347 * both return the location of the view relative to its parent. For instance,
348 * when getLeft() returns 20, that means the view is located 20 pixels to the
349 * right of the left edge of its direct parent.
350 * </p>
351 *
352 * <p>
353 * In addition, several convenience methods are offered to avoid unnecessary
354 * computations, namely {@link #getRight()} and {@link #getBottom()}.
355 * These methods return the coordinates of the right and bottom edges of the
356 * rectangle representing the view. For instance, calling {@link #getRight()}
357 * is similar to the following computation: <code>getLeft() + getWidth()</code>
358 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
359 * </p>
360 *
361 * <a name="SizePaddingMargins"></a>
362 * <h3>Size, padding and margins</h3>
363 * <p>
364 * The size of a view is expressed with a width and a height. A view actually
365 * possess two pairs of width and height values.
366 * </p>
367 *
368 * <p>
369 * The first pair is known as <em>measured width</em> and
370 * <em>measured height</em>. These dimensions define how big a view wants to be
371 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
372 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
373 * and {@link #getMeasuredHeight()}.
374 * </p>
375 *
376 * <p>
377 * The second pair is simply known as <em>width</em> and <em>height</em>, or
378 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
379 * dimensions define the actual size of the view on screen, at drawing time and
380 * after layout. These values may, but do not have to, be different from the
381 * measured width and height. The width and height can be obtained by calling
382 * {@link #getWidth()} and {@link #getHeight()}.
383 * </p>
384 *
385 * <p>
386 * To measure its dimensions, a view takes into account its padding. The padding
387 * is expressed in pixels for the left, top, right and bottom parts of the view.
388 * Padding can be used to offset the content of the view by a specific amount of
389 * pixels. For instance, a left padding of 2 will push the view's content by
390 * 2 pixels to the right of the left edge. Padding can be set using the
391 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
392 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
393 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
394 * {@link #getPaddingEnd()}.
395 * </p>
396 *
397 * <p>
398 * Even though a view can define a padding, it does not provide any support for
399 * margins. However, view groups provide such a support. Refer to
400 * {@link android.view.ViewGroup} and
401 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
402 * </p>
403 *
404 * <a name="Layout"></a>
405 * <h3>Layout</h3>
406 * <p>
407 * Layout is a two pass process: a measure pass and a layout pass. The measuring
408 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
409 * of the view tree. Each view pushes dimension specifications down the tree
410 * during the recursion. At the end of the measure pass, every view has stored
411 * its measurements. The second pass happens in
412 * {@link #layout(int,int,int,int)} and is also top-down. During
413 * this pass each parent is responsible for positioning all of its children
414 * using the sizes computed in the measure pass.
415 * </p>
416 *
417 * <p>
418 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
419 * {@link #getMeasuredHeight()} values must be set, along with those for all of
420 * that view's descendants. A view's measured width and measured height values
421 * must respect the constraints imposed by the view's parents. This guarantees
422 * that at the end of the measure pass, all parents accept all of their
423 * children's measurements. A parent view may call measure() more than once on
424 * its children. For example, the parent may measure each child once with
425 * unspecified dimensions to find out how big they want to be, then call
426 * measure() on them again with actual numbers if the sum of all the children's
427 * unconstrained sizes is too big or too small.
428 * </p>
429 *
430 * <p>
431 * The measure pass uses two classes to communicate dimensions. The
432 * {@link MeasureSpec} class is used by views to tell their parents how they
433 * want to be measured and positioned. The base LayoutParams class just
434 * describes how big the view wants to be for both width and height. For each
435 * dimension, it can specify one of:
436 * <ul>
437 * <li> an exact number
438 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
439 * (minus padding)
440 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
441 * enclose its content (plus padding).
442 * </ul>
443 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
444 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
445 * an X and Y value.
446 * </p>
447 *
448 * <p>
449 * MeasureSpecs are used to push requirements down the tree from parent to
450 * child. A MeasureSpec can be in one of three modes:
451 * <ul>
452 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
453 * of a child view. For example, a LinearLayout may call measure() on its child
454 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
455 * tall the child view wants to be given a width of 240 pixels.
456 * <li>EXACTLY: This is used by the parent to impose an exact size on the
457 * child. The child must use this size, and guarantee that all of its
458 * descendants will fit within this size.
459 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
460 * child. The child must guarantee that it and all of its descendants will fit
461 * within this size.
462 * </ul>
463 * </p>
464 *
465 * <p>
466 * To initiate a layout, call {@link #requestLayout}. This method is typically
467 * called by a view on itself when it believes that is can no longer fit within
468 * its current bounds.
469 * </p>
470 *
471 * <a name="Drawing"></a>
472 * <h3>Drawing</h3>
473 * <p>
474 * Drawing is handled by walking the tree and recording the drawing commands of
475 * any View that needs to update. After this, the drawing commands of the
476 * entire tree are issued to screen, clipped to the newly damaged area.
477 * </p>
478 *
479 * <p>
480 * The tree is largely recorded and drawn in order, with parents drawn before
481 * (i.e., behind) their children, with siblings drawn in the order they appear
482 * in the tree. If you set a background drawable for a View, then the View will
483 * draw it before calling back to its <code>onDraw()</code> method. The child
484 * drawing order can be overridden with
485 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
486 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
487 * </p>
488 *
489 * <p>
490 * To force a view to draw, call {@link #invalidate()}.
491 * </p>
492 *
493 * <a name="EventHandlingThreading"></a>
494 * <h3>Event Handling and Threading</h3>
495 * <p>
496 * The basic cycle of a view is as follows:
497 * <ol>
498 * <li>An event comes in and is dispatched to the appropriate view. The view
499 * handles the event and notifies any listeners.</li>
500 * <li>If in the course of processing the event, the view's bounds may need
501 * to be changed, the view will call {@link #requestLayout()}.</li>
502 * <li>Similarly, if in the course of processing the event the view's appearance
503 * may need to be changed, the view will call {@link #invalidate()}.</li>
504 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
505 * the framework will take care of measuring, laying out, and drawing the tree
506 * as appropriate.</li>
507 * </ol>
508 * </p>
509 *
510 * <p><em>Note: The entire view tree is single threaded. You must always be on
511 * the UI thread when calling any method on any view.</em>
512 * If you are doing work on other threads and want to update the state of a view
513 * from that thread, you should use a {@link Handler}.
514 * </p>
515 *
516 * <a name="FocusHandling"></a>
517 * <h3>Focus Handling</h3>
518 * <p>
519 * The framework will handle routine focus movement in response to user input.
520 * This includes changing the focus as views are removed or hidden, or as new
521 * views become available. Views indicate their willingness to take focus
522 * through the {@link #isFocusable} method. To change whether a view can take
523 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
524 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
525 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
526 * </p>
527 * <p>
528 * Focus movement is based on an algorithm which finds the nearest neighbor in a
529 * given direction. In rare cases, the default algorithm may not match the
530 * intended behavior of the developer. In these situations, you can provide
531 * explicit overrides by using these XML attributes in the layout file:
532 * <pre>
533 * nextFocusDown
534 * nextFocusLeft
535 * nextFocusRight
536 * nextFocusUp
537 * </pre>
538 * </p>
539 *
540 *
541 * <p>
542 * To get a particular view to take focus, call {@link #requestFocus()}.
543 * </p>
544 *
545 * <a name="TouchMode"></a>
546 * <h3>Touch Mode</h3>
547 * <p>
548 * When a user is navigating a user interface via directional keys such as a D-pad, it is
549 * necessary to give focus to actionable items such as buttons so the user can see
550 * what will take input.  If the device has touch capabilities, however, and the user
551 * begins interacting with the interface by touching it, it is no longer necessary to
552 * always highlight, or give focus to, a particular view.  This motivates a mode
553 * for interaction named 'touch mode'.
554 * </p>
555 * <p>
556 * For a touch capable device, once the user touches the screen, the device
557 * will enter touch mode.  From this point onward, only views for which
558 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
559 * Other views that are touchable, like buttons, will not take focus when touched; they will
560 * only fire the on click listeners.
561 * </p>
562 * <p>
563 * Any time a user hits a directional key, such as a D-pad direction, the view device will
564 * exit touch mode, and find a view to take focus, so that the user may resume interacting
565 * with the user interface without touching the screen again.
566 * </p>
567 * <p>
568 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
569 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
570 * </p>
571 *
572 * <a name="Scrolling"></a>
573 * <h3>Scrolling</h3>
574 * <p>
575 * The framework provides basic support for views that wish to internally
576 * scroll their content. This includes keeping track of the X and Y scroll
577 * offset as well as mechanisms for drawing scrollbars. See
578 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
579 * {@link #awakenScrollBars()} for more details.
580 * </p>
581 *
582 * <a name="Tags"></a>
583 * <h3>Tags</h3>
584 * <p>
585 * Unlike IDs, tags are not used to identify views. Tags are essentially an
586 * extra piece of information that can be associated with a view. They are most
587 * often used as a convenience to store data related to views in the views
588 * themselves rather than by putting them in a separate structure.
589 * </p>
590 * <p>
591 * Tags may be specified with character sequence values in layout XML as either
592 * a single tag using the {@link android.R.styleable#View_tag android:tag}
593 * attribute or multiple tags using the {@code <tag>} child element:
594 * <pre>
595 *     &ltView ...
596 *           android:tag="@string/mytag_value" /&gt;
597 *     &ltView ...&gt;
598 *         &lttag android:id="@+id/mytag"
599 *              android:value="@string/mytag_value" /&gt;
600 *     &lt/View>
601 * </pre>
602 * </p>
603 * <p>
604 * Tags may also be specified with arbitrary objects from code using
605 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
606 * </p>
607 *
608 * <a name="Themes"></a>
609 * <h3>Themes</h3>
610 * <p>
611 * By default, Views are created using the theme of the Context object supplied
612 * to their constructor; however, a different theme may be specified by using
613 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
614 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
615 * code.
616 * </p>
617 * <p>
618 * When the {@link android.R.styleable#View_theme android:theme} attribute is
619 * used in XML, the specified theme is applied on top of the inflation
620 * context's theme (see {@link LayoutInflater}) and used for the view itself as
621 * well as any child elements.
622 * </p>
623 * <p>
624 * In the following example, both views will be created using the Material dark
625 * color scheme; however, because an overlay theme is used which only defines a
626 * subset of attributes, the value of
627 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
628 * the inflation context's theme (e.g. the Activity theme) will be preserved.
629 * <pre>
630 *     &ltLinearLayout
631 *             ...
632 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
633 *         &ltView ...&gt;
634 *     &lt/LinearLayout&gt;
635 * </pre>
636 * </p>
637 *
638 * <a name="Properties"></a>
639 * <h3>Properties</h3>
640 * <p>
641 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
642 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
643 * available both in the {@link Property} form as well as in similarly-named setter/getter
644 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
645 * be used to set persistent state associated with these rendering-related properties on the view.
646 * The properties and methods can also be used in conjunction with
647 * {@link android.animation.Animator Animator}-based animations, described more in the
648 * <a href="#Animation">Animation</a> section.
649 * </p>
650 *
651 * <a name="Animation"></a>
652 * <h3>Animation</h3>
653 * <p>
654 * Starting with Android 3.0, the preferred way of animating views is to use the
655 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
656 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
657 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
658 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
659 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
660 * makes animating these View properties particularly easy and efficient.
661 * </p>
662 * <p>
663 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
664 * You can attach an {@link Animation} object to a view using
665 * {@link #setAnimation(Animation)} or
666 * {@link #startAnimation(Animation)}. The animation can alter the scale,
667 * rotation, translation and alpha of a view over time. If the animation is
668 * attached to a view that has children, the animation will affect the entire
669 * subtree rooted by that node. When an animation is started, the framework will
670 * take care of redrawing the appropriate views until the animation completes.
671 * </p>
672 *
673 * <a name="Security"></a>
674 * <h3>Security</h3>
675 * <p>
676 * Sometimes it is essential that an application be able to verify that an action
677 * is being performed with the full knowledge and consent of the user, such as
678 * granting a permission request, making a purchase or clicking on an advertisement.
679 * Unfortunately, a malicious application could try to spoof the user into
680 * performing these actions, unaware, by concealing the intended purpose of the view.
681 * As a remedy, the framework offers a touch filtering mechanism that can be used to
682 * improve the security of views that provide access to sensitive functionality.
683 * </p><p>
684 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
685 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
686 * will discard touches that are received whenever the view's window is obscured by
687 * another visible window.  As a result, the view will not receive touches whenever a
688 * toast, dialog or other window appears above the view's window.
689 * </p><p>
690 * For more fine-grained control over security, consider overriding the
691 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
692 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
693 * </p>
694 *
695 * @attr ref android.R.styleable#View_alpha
696 * @attr ref android.R.styleable#View_background
697 * @attr ref android.R.styleable#View_clickable
698 * @attr ref android.R.styleable#View_contentDescription
699 * @attr ref android.R.styleable#View_drawingCacheQuality
700 * @attr ref android.R.styleable#View_duplicateParentState
701 * @attr ref android.R.styleable#View_id
702 * @attr ref android.R.styleable#View_requiresFadingEdge
703 * @attr ref android.R.styleable#View_fadeScrollbars
704 * @attr ref android.R.styleable#View_fadingEdgeLength
705 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
706 * @attr ref android.R.styleable#View_fitsSystemWindows
707 * @attr ref android.R.styleable#View_isScrollContainer
708 * @attr ref android.R.styleable#View_focusable
709 * @attr ref android.R.styleable#View_focusableInTouchMode
710 * @attr ref android.R.styleable#View_focusedByDefault
711 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
712 * @attr ref android.R.styleable#View_keepScreenOn
713 * @attr ref android.R.styleable#View_keyboardNavigationCluster
714 * @attr ref android.R.styleable#View_layerType
715 * @attr ref android.R.styleable#View_layoutDirection
716 * @attr ref android.R.styleable#View_longClickable
717 * @attr ref android.R.styleable#View_minHeight
718 * @attr ref android.R.styleable#View_minWidth
719 * @attr ref android.R.styleable#View_nextClusterForward
720 * @attr ref android.R.styleable#View_nextFocusDown
721 * @attr ref android.R.styleable#View_nextFocusLeft
722 * @attr ref android.R.styleable#View_nextFocusRight
723 * @attr ref android.R.styleable#View_nextFocusUp
724 * @attr ref android.R.styleable#View_onClick
725 * @attr ref android.R.styleable#View_padding
726 * @attr ref android.R.styleable#View_paddingBottom
727 * @attr ref android.R.styleable#View_paddingLeft
728 * @attr ref android.R.styleable#View_paddingRight
729 * @attr ref android.R.styleable#View_paddingTop
730 * @attr ref android.R.styleable#View_paddingStart
731 * @attr ref android.R.styleable#View_paddingEnd
732 * @attr ref android.R.styleable#View_saveEnabled
733 * @attr ref android.R.styleable#View_rotation
734 * @attr ref android.R.styleable#View_rotationX
735 * @attr ref android.R.styleable#View_rotationY
736 * @attr ref android.R.styleable#View_scaleX
737 * @attr ref android.R.styleable#View_scaleY
738 * @attr ref android.R.styleable#View_scrollX
739 * @attr ref android.R.styleable#View_scrollY
740 * @attr ref android.R.styleable#View_scrollbarSize
741 * @attr ref android.R.styleable#View_scrollbarStyle
742 * @attr ref android.R.styleable#View_scrollbars
743 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
744 * @attr ref android.R.styleable#View_scrollbarFadeDuration
745 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
746 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
747 * @attr ref android.R.styleable#View_scrollbarThumbVertical
748 * @attr ref android.R.styleable#View_scrollbarTrackVertical
749 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
750 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
751 * @attr ref android.R.styleable#View_stateListAnimator
752 * @attr ref android.R.styleable#View_transitionName
753 * @attr ref android.R.styleable#View_soundEffectsEnabled
754 * @attr ref android.R.styleable#View_tag
755 * @attr ref android.R.styleable#View_textAlignment
756 * @attr ref android.R.styleable#View_textDirection
757 * @attr ref android.R.styleable#View_transformPivotX
758 * @attr ref android.R.styleable#View_transformPivotY
759 * @attr ref android.R.styleable#View_translationX
760 * @attr ref android.R.styleable#View_translationY
761 * @attr ref android.R.styleable#View_translationZ
762 * @attr ref android.R.styleable#View_visibility
763 * @attr ref android.R.styleable#View_theme
764 *
765 * @see android.view.ViewGroup
766 */
767@UiThread
768public class View implements Drawable.Callback, KeyEvent.Callback,
769        AccessibilityEventSource {
770    private static final boolean DBG = false;
771
772    /** @hide */
773    public static boolean DEBUG_DRAW = false;
774
775    /**
776     * The logging tag used by this class with android.util.Log.
777     */
778    protected static final String VIEW_LOG_TAG = "View";
779
780    /**
781     * When set to true, apps will draw debugging information about their layouts.
782     *
783     * @hide
784     */
785    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
786
787    /**
788     * When set to true, this view will save its attribute data.
789     *
790     * @hide
791     */
792    public static boolean mDebugViewAttributes = false;
793
794    /**
795     * Used to mark a View that has no ID.
796     */
797    public static final int NO_ID = -1;
798
799    /**
800     * Last ID that is given to Views that are no part of activities.
801     *
802     * {@hide}
803     */
804    public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
805
806    /**
807     * Signals that compatibility booleans have been initialized according to
808     * target SDK versions.
809     */
810    private static boolean sCompatibilityDone = false;
811
812    /**
813     * Use the old (broken) way of building MeasureSpecs.
814     */
815    private static boolean sUseBrokenMakeMeasureSpec = false;
816
817    /**
818     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
819     */
820    static boolean sUseZeroUnspecifiedMeasureSpec = false;
821
822    /**
823     * Ignore any optimizations using the measure cache.
824     */
825    private static boolean sIgnoreMeasureCache = false;
826
827    /**
828     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
829     */
830    private static boolean sAlwaysRemeasureExactly = false;
831
832    /**
833     * Relax constraints around whether setLayoutParams() must be called after
834     * modifying the layout params.
835     */
836    private static boolean sLayoutParamsAlwaysChanged = false;
837
838    /**
839     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
840     * without throwing
841     */
842    static boolean sTextureViewIgnoresDrawableSetters = false;
843
844    /**
845     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
846     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
847     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
848     * check is implemented for backwards compatibility.
849     *
850     * {@hide}
851     */
852    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
853
854    /**
855     * Prior to N, when drag enters into child of a view that has already received an
856     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
857     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
858     * false from its event handler for these events.
859     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
860     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
861     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
862     */
863    static boolean sCascadedDragDrop;
864
865    /**
866     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
867     * to determine things like whether or not to permit item click events. We can't break
868     * apps that do this just because more things (clickable things) are now auto-focusable
869     * and they would get different results, so give old behavior to old apps.
870     */
871    static boolean sHasFocusableExcludeAutoFocusable;
872
873    /**
874     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
875     * made focusable by default. As a result, apps could (incorrectly) change the clickable
876     * setting of views off the UI thread. Now that clickable can effect the focusable state,
877     * changing the clickable attribute off the UI thread will cause an exception (since changing
878     * the focusable state checks). In order to prevent apps from crashing, we will handle this
879     * specific case and just not notify parents on new focusables resulting from marking views
880     * clickable from outside the UI thread.
881     */
882    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
883
884    /** @hide */
885    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
886    @Retention(RetentionPolicy.SOURCE)
887    public @interface Focusable {}
888
889    /**
890     * This view does not want keystrokes.
891     * <p>
892     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
893     * android:focusable}.
894     */
895    public static final int NOT_FOCUSABLE = 0x00000000;
896
897    /**
898     * This view wants keystrokes.
899     * <p>
900     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
901     * android:focusable}.
902     */
903    public static final int FOCUSABLE = 0x00000001;
904
905    /**
906     * This view determines focusability automatically. This is the default.
907     * <p>
908     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
909     * android:focusable}.
910     */
911    public static final int FOCUSABLE_AUTO = 0x00000010;
912
913    /**
914     * Mask for use with setFlags indicating bits used for focus.
915     */
916    private static final int FOCUSABLE_MASK = 0x00000011;
917
918    /**
919     * This view will adjust its padding to fit sytem windows (e.g. status bar)
920     */
921    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
922
923    /** @hide */
924    @IntDef({VISIBLE, INVISIBLE, GONE})
925    @Retention(RetentionPolicy.SOURCE)
926    public @interface Visibility {}
927
928    /**
929     * This view is visible.
930     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
931     * android:visibility}.
932     */
933    public static final int VISIBLE = 0x00000000;
934
935    /**
936     * This view is invisible, but it still takes up space for layout purposes.
937     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
938     * android:visibility}.
939     */
940    public static final int INVISIBLE = 0x00000004;
941
942    /**
943     * This view is invisible, and it doesn't take any space for layout
944     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
945     * android:visibility}.
946     */
947    public static final int GONE = 0x00000008;
948
949    /**
950     * Mask for use with setFlags indicating bits used for visibility.
951     * {@hide}
952     */
953    static final int VISIBILITY_MASK = 0x0000000C;
954
955    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
956
957    /** @hide */
958    @IntDef({
959            AUTOFILL_MODE_INHERIT,
960            AUTOFILL_MODE_AUTO,
961            AUTOFILL_MODE_MANUAL
962    })
963    @Retention(RetentionPolicy.SOURCE)
964    public @interface AutofillMode {}
965
966    /**
967     * This view inherits the autofill state from it's parent. If there is no parent it is
968     * {@link #AUTOFILL_MODE_AUTO}.
969     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
970     * {@code android:autofillMode}.
971     */
972    public static final int AUTOFILL_MODE_INHERIT = 0;
973
974    /**
975     * Allows this view to automatically trigger an autofill request when it get focus.
976     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
977     * {@code android:autofillMode}.
978     */
979    public static final int AUTOFILL_MODE_AUTO = 1;
980
981    /**
982     * Do not trigger an autofill request if this view is focused. The user can still force
983     * an autofill request.
984     * <p>This does not prevent this field from being autofilled if an autofill operation is
985     * triggered from a different view.</p>
986     *
987     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code
988     * android:autofillMode}.
989     */
990    public static final int AUTOFILL_MODE_MANUAL = 2;
991
992    /**
993     * This view contains an email address.
994     *
995     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_EMAIL_ADDRESS}"
996     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
997     */
998    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
999
1000    /**
1001     * The view contains a real name.
1002     *
1003     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_NAME}" to
1004     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1005     */
1006    public static final String AUTOFILL_HINT_NAME = "name";
1007
1008    /**
1009     * The view contains a user name.
1010     *
1011     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_USERNAME}" to
1012     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1013     */
1014    public static final String AUTOFILL_HINT_USERNAME = "username";
1015
1016    /**
1017     * The view contains a password.
1018     *
1019     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PASSWORD}" to
1020     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1021     */
1022    public static final String AUTOFILL_HINT_PASSWORD = "password";
1023
1024    /**
1025     * The view contains a phone number.
1026     *
1027     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PHONE}" to
1028     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1029     */
1030    public static final String AUTOFILL_HINT_PHONE = "phone";
1031
1032    /**
1033     * The view contains a postal address.
1034     *
1035     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_ADDRESS}"
1036     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1037     */
1038    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1039
1040    /**
1041     * The view contains a postal code.
1042     *
1043     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_CODE}" to
1044     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1045     */
1046    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1047
1048    /**
1049     * The view contains a credit card number.
1050     *
1051     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1052     * #AUTOFILL_HINT_CREDIT_CARD_NUMBER}" to <a href="#attr_android:autofillHint"> {@code
1053     * android:autofillHint}.
1054     */
1055    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1056
1057    /**
1058     * The view contains a credit card security code.
1059     *
1060     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1061     * #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}" to <a href="#attr_android:autofillHint"> {@code
1062     * android:autofillHint}.
1063     */
1064    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1065
1066    /**
1067     * The view contains a credit card expiration date.
1068     *
1069     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1070     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}" to <a href="#attr_android:autofillHint"> {@code
1071     * android:autofillHint}.
1072     */
1073    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1074            "creditCardExpirationDate";
1075
1076    /**
1077     * The view contains the month a credit card expires.
1078     *
1079     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1080     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}" to <a href="#attr_android:autofillHint"> {@code
1081     * android:autofillHint}.
1082     */
1083    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1084            "creditCardExpirationMonth";
1085
1086    /**
1087     * The view contains the year a credit card expires.
1088     *
1089     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1090     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}" to <a href="#attr_android:autofillHint"> {@code
1091     * android:autofillHint}.
1092     */
1093    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1094            "creditCardExpirationYear";
1095
1096    /**
1097     * The view contains the day a credit card expires.
1098     *
1099     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1100     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}" to <a href="#attr_android:autofillHint"> {@code
1101     * android:autofillHint}.
1102     */
1103    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1104
1105    /**
1106     * Hintd for the autofill services that describes the content of the view.
1107     */
1108    private @Nullable String[] mAutofillHints;
1109
1110    /** @hide */
1111    @IntDef({
1112            AUTOFILL_TYPE_NONE,
1113            AUTOFILL_TYPE_TEXT,
1114            AUTOFILL_TYPE_TOGGLE,
1115            AUTOFILL_TYPE_LIST,
1116            AUTOFILL_TYPE_DATE
1117    })
1118    @Retention(RetentionPolicy.SOURCE)
1119    public @interface AutofillType {}
1120
1121    /**
1122     * Autofill type for views that cannot be autofilled.
1123     */
1124    public static final int AUTOFILL_TYPE_NONE = 0;
1125
1126    /**
1127     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1128     *
1129     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1130     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1131     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1132     */
1133    public static final int AUTOFILL_TYPE_TEXT = 1;
1134
1135    /**
1136     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1137     *
1138     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1139     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1140     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1141     */
1142    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1143
1144    /**
1145     * Autofill type for a selection list field, which is filled by an {@code int}
1146     * representing the element index inside the list (starting at {@code 0}).
1147     *
1148     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1149     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1150     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1151     *
1152     * <p>The available options in the selection list are typically provided by
1153     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1154     */
1155    public static final int AUTOFILL_TYPE_LIST = 3;
1156
1157
1158    /**
1159     * Autofill type for a field that contains a date, which is represented by a long representing
1160     * the number of milliseconds since the standard base time known as "the epoch", namely
1161     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1162     *
1163     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1164     * {@link AutofillValue#forDate(long)}, and the values passed to
1165     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1166     */
1167    public static final int AUTOFILL_TYPE_DATE = 4;
1168
1169    /** @hide */
1170    @IntDef({
1171            IMPORTANT_FOR_AUTOFILL_AUTO,
1172            IMPORTANT_FOR_AUTOFILL_YES,
1173            IMPORTANT_FOR_AUTOFILL_NO
1174    })
1175    @Retention(RetentionPolicy.SOURCE)
1176    public @interface AutofillImportance {}
1177
1178    /**
1179     * Automatically determine whether a view is important for auto-fill.
1180     */
1181    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1182
1183    /**
1184     * The view is important for important for auto-fill.
1185     */
1186    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1187
1188    /**
1189     * The view is not important for auto-fill.
1190     */
1191    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1192
1193    /**
1194     * This view is enabled. Interpretation varies by subclass.
1195     * Use with ENABLED_MASK when calling setFlags.
1196     * {@hide}
1197     */
1198    static final int ENABLED = 0x00000000;
1199
1200    /**
1201     * This view is disabled. Interpretation varies by subclass.
1202     * Use with ENABLED_MASK when calling setFlags.
1203     * {@hide}
1204     */
1205    static final int DISABLED = 0x00000020;
1206
1207   /**
1208    * Mask for use with setFlags indicating bits used for indicating whether
1209    * this view is enabled
1210    * {@hide}
1211    */
1212    static final int ENABLED_MASK = 0x00000020;
1213
1214    /**
1215     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1216     * called and further optimizations will be performed. It is okay to have
1217     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1218     * {@hide}
1219     */
1220    static final int WILL_NOT_DRAW = 0x00000080;
1221
1222    /**
1223     * Mask for use with setFlags indicating bits used for indicating whether
1224     * this view is will draw
1225     * {@hide}
1226     */
1227    static final int DRAW_MASK = 0x00000080;
1228
1229    /**
1230     * <p>This view doesn't show scrollbars.</p>
1231     * {@hide}
1232     */
1233    static final int SCROLLBARS_NONE = 0x00000000;
1234
1235    /**
1236     * <p>This view shows horizontal scrollbars.</p>
1237     * {@hide}
1238     */
1239    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1240
1241    /**
1242     * <p>This view shows vertical scrollbars.</p>
1243     * {@hide}
1244     */
1245    static final int SCROLLBARS_VERTICAL = 0x00000200;
1246
1247    /**
1248     * <p>Mask for use with setFlags indicating bits used for indicating which
1249     * scrollbars are enabled.</p>
1250     * {@hide}
1251     */
1252    static final int SCROLLBARS_MASK = 0x00000300;
1253
1254    /**
1255     * Indicates that the view should filter touches when its window is obscured.
1256     * Refer to the class comments for more information about this security feature.
1257     * {@hide}
1258     */
1259    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1260
1261    /**
1262     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1263     * that they are optional and should be skipped if the window has
1264     * requested system UI flags that ignore those insets for layout.
1265     */
1266    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1267
1268    /**
1269     * <p>This view doesn't show fading edges.</p>
1270     * {@hide}
1271     */
1272    static final int FADING_EDGE_NONE = 0x00000000;
1273
1274    /**
1275     * <p>This view shows horizontal fading edges.</p>
1276     * {@hide}
1277     */
1278    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1279
1280    /**
1281     * <p>This view shows vertical fading edges.</p>
1282     * {@hide}
1283     */
1284    static final int FADING_EDGE_VERTICAL = 0x00002000;
1285
1286    /**
1287     * <p>Mask for use with setFlags indicating bits used for indicating which
1288     * fading edges are enabled.</p>
1289     * {@hide}
1290     */
1291    static final int FADING_EDGE_MASK = 0x00003000;
1292
1293    /**
1294     * <p>Indicates this view can be clicked. When clickable, a View reacts
1295     * to clicks by notifying the OnClickListener.<p>
1296     * {@hide}
1297     */
1298    static final int CLICKABLE = 0x00004000;
1299
1300    /**
1301     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1302     * {@hide}
1303     */
1304    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1305
1306    /**
1307     * <p>Indicates that no icicle should be saved for this view.<p>
1308     * {@hide}
1309     */
1310    static final int SAVE_DISABLED = 0x000010000;
1311
1312    /**
1313     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1314     * property.</p>
1315     * {@hide}
1316     */
1317    static final int SAVE_DISABLED_MASK = 0x000010000;
1318
1319    /**
1320     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1321     * {@hide}
1322     */
1323    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1324
1325    /**
1326     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1327     * {@hide}
1328     */
1329    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1330
1331    /** @hide */
1332    @Retention(RetentionPolicy.SOURCE)
1333    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1334    public @interface DrawingCacheQuality {}
1335
1336    /**
1337     * <p>Enables low quality mode for the drawing cache.</p>
1338     */
1339    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1340
1341    /**
1342     * <p>Enables high quality mode for the drawing cache.</p>
1343     */
1344    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1345
1346    /**
1347     * <p>Enables automatic quality mode for the drawing cache.</p>
1348     */
1349    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1350
1351    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1352            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1353    };
1354
1355    /**
1356     * <p>Mask for use with setFlags indicating bits used for the cache
1357     * quality property.</p>
1358     * {@hide}
1359     */
1360    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1361
1362    /**
1363     * <p>
1364     * Indicates this view can be long clicked. When long clickable, a View
1365     * reacts to long clicks by notifying the OnLongClickListener or showing a
1366     * context menu.
1367     * </p>
1368     * {@hide}
1369     */
1370    static final int LONG_CLICKABLE = 0x00200000;
1371
1372    /**
1373     * <p>Indicates that this view gets its drawable states from its direct parent
1374     * and ignores its original internal states.</p>
1375     *
1376     * @hide
1377     */
1378    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1379
1380    /**
1381     * <p>
1382     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1383     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1384     * OnContextClickListener.
1385     * </p>
1386     * {@hide}
1387     */
1388    static final int CONTEXT_CLICKABLE = 0x00800000;
1389
1390
1391    /** @hide */
1392    @IntDef({
1393        SCROLLBARS_INSIDE_OVERLAY,
1394        SCROLLBARS_INSIDE_INSET,
1395        SCROLLBARS_OUTSIDE_OVERLAY,
1396        SCROLLBARS_OUTSIDE_INSET
1397    })
1398    @Retention(RetentionPolicy.SOURCE)
1399    public @interface ScrollBarStyle {}
1400
1401    /**
1402     * The scrollbar style to display the scrollbars inside the content area,
1403     * without increasing the padding. The scrollbars will be overlaid with
1404     * translucency on the view's content.
1405     */
1406    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1407
1408    /**
1409     * The scrollbar style to display the scrollbars inside the padded area,
1410     * increasing the padding of the view. The scrollbars will not overlap the
1411     * content area of the view.
1412     */
1413    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1414
1415    /**
1416     * The scrollbar style to display the scrollbars at the edge of the view,
1417     * without increasing the padding. The scrollbars will be overlaid with
1418     * translucency.
1419     */
1420    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1421
1422    /**
1423     * The scrollbar style to display the scrollbars at the edge of the view,
1424     * increasing the padding of the view. The scrollbars will only overlap the
1425     * background, if any.
1426     */
1427    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1428
1429    /**
1430     * Mask to check if the scrollbar style is overlay or inset.
1431     * {@hide}
1432     */
1433    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1434
1435    /**
1436     * Mask to check if the scrollbar style is inside or outside.
1437     * {@hide}
1438     */
1439    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1440
1441    /**
1442     * Mask for scrollbar style.
1443     * {@hide}
1444     */
1445    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1446
1447    /**
1448     * View flag indicating that the screen should remain on while the
1449     * window containing this view is visible to the user.  This effectively
1450     * takes care of automatically setting the WindowManager's
1451     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1452     */
1453    public static final int KEEP_SCREEN_ON = 0x04000000;
1454
1455    /**
1456     * View flag indicating whether this view should have sound effects enabled
1457     * for events such as clicking and touching.
1458     */
1459    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1460
1461    /**
1462     * View flag indicating whether this view should have haptic feedback
1463     * enabled for events such as long presses.
1464     */
1465    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1466
1467    /**
1468     * <p>Indicates that the view hierarchy should stop saving state when
1469     * it reaches this view.  If state saving is initiated immediately at
1470     * the view, it will be allowed.
1471     * {@hide}
1472     */
1473    static final int PARENT_SAVE_DISABLED = 0x20000000;
1474
1475    /**
1476     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1477     * {@hide}
1478     */
1479    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1480
1481    private static Paint sDebugPaint;
1482
1483    /**
1484     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1485     * {@hide}
1486     */
1487    static final int TOOLTIP = 0x40000000;
1488
1489    /** @hide */
1490    @IntDef(flag = true,
1491            value = {
1492                FOCUSABLES_ALL,
1493                FOCUSABLES_TOUCH_MODE
1494            })
1495    @Retention(RetentionPolicy.SOURCE)
1496    public @interface FocusableMode {}
1497
1498    /**
1499     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1500     * should add all focusable Views regardless if they are focusable in touch mode.
1501     */
1502    public static final int FOCUSABLES_ALL = 0x00000000;
1503
1504    /**
1505     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1506     * should add only Views focusable in touch mode.
1507     */
1508    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1509
1510    /** @hide */
1511    @IntDef({
1512            FOCUS_BACKWARD,
1513            FOCUS_FORWARD,
1514            FOCUS_LEFT,
1515            FOCUS_UP,
1516            FOCUS_RIGHT,
1517            FOCUS_DOWN
1518    })
1519    @Retention(RetentionPolicy.SOURCE)
1520    public @interface FocusDirection {}
1521
1522    /** @hide */
1523    @IntDef({
1524            FOCUS_LEFT,
1525            FOCUS_UP,
1526            FOCUS_RIGHT,
1527            FOCUS_DOWN
1528    })
1529    @Retention(RetentionPolicy.SOURCE)
1530    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1531
1532    /**
1533     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1534     * item.
1535     */
1536    public static final int FOCUS_BACKWARD = 0x00000001;
1537
1538    /**
1539     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1540     * item.
1541     */
1542    public static final int FOCUS_FORWARD = 0x00000002;
1543
1544    /**
1545     * Use with {@link #focusSearch(int)}. Move focus to the left.
1546     */
1547    public static final int FOCUS_LEFT = 0x00000011;
1548
1549    /**
1550     * Use with {@link #focusSearch(int)}. Move focus up.
1551     */
1552    public static final int FOCUS_UP = 0x00000021;
1553
1554    /**
1555     * Use with {@link #focusSearch(int)}. Move focus to the right.
1556     */
1557    public static final int FOCUS_RIGHT = 0x00000042;
1558
1559    /**
1560     * Use with {@link #focusSearch(int)}. Move focus down.
1561     */
1562    public static final int FOCUS_DOWN = 0x00000082;
1563
1564    /**
1565     * Bits of {@link #getMeasuredWidthAndState()} and
1566     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1567     */
1568    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1569
1570    /**
1571     * Bits of {@link #getMeasuredWidthAndState()} and
1572     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1573     */
1574    public static final int MEASURED_STATE_MASK = 0xff000000;
1575
1576    /**
1577     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1578     * for functions that combine both width and height into a single int,
1579     * such as {@link #getMeasuredState()} and the childState argument of
1580     * {@link #resolveSizeAndState(int, int, int)}.
1581     */
1582    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1583
1584    /**
1585     * Bit of {@link #getMeasuredWidthAndState()} and
1586     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1587     * is smaller that the space the view would like to have.
1588     */
1589    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1590
1591    /**
1592     * Base View state sets
1593     */
1594    // Singles
1595    /**
1596     * Indicates the view has no states set. States are used with
1597     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1598     * view depending on its state.
1599     *
1600     * @see android.graphics.drawable.Drawable
1601     * @see #getDrawableState()
1602     */
1603    protected static final int[] EMPTY_STATE_SET;
1604    /**
1605     * Indicates the view is enabled. States are used with
1606     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1607     * view depending on its state.
1608     *
1609     * @see android.graphics.drawable.Drawable
1610     * @see #getDrawableState()
1611     */
1612    protected static final int[] ENABLED_STATE_SET;
1613    /**
1614     * Indicates the view is focused. States are used with
1615     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1616     * view depending on its state.
1617     *
1618     * @see android.graphics.drawable.Drawable
1619     * @see #getDrawableState()
1620     */
1621    protected static final int[] FOCUSED_STATE_SET;
1622    /**
1623     * Indicates the view is selected. States are used with
1624     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1625     * view depending on its state.
1626     *
1627     * @see android.graphics.drawable.Drawable
1628     * @see #getDrawableState()
1629     */
1630    protected static final int[] SELECTED_STATE_SET;
1631    /**
1632     * Indicates the view is pressed. States are used with
1633     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1634     * view depending on its state.
1635     *
1636     * @see android.graphics.drawable.Drawable
1637     * @see #getDrawableState()
1638     */
1639    protected static final int[] PRESSED_STATE_SET;
1640    /**
1641     * Indicates the view's window has focus. States are used with
1642     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1643     * view depending on its state.
1644     *
1645     * @see android.graphics.drawable.Drawable
1646     * @see #getDrawableState()
1647     */
1648    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1649    // Doubles
1650    /**
1651     * Indicates the view is enabled and has the focus.
1652     *
1653     * @see #ENABLED_STATE_SET
1654     * @see #FOCUSED_STATE_SET
1655     */
1656    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1657    /**
1658     * Indicates the view is enabled and selected.
1659     *
1660     * @see #ENABLED_STATE_SET
1661     * @see #SELECTED_STATE_SET
1662     */
1663    protected static final int[] ENABLED_SELECTED_STATE_SET;
1664    /**
1665     * Indicates the view is enabled and that its window has focus.
1666     *
1667     * @see #ENABLED_STATE_SET
1668     * @see #WINDOW_FOCUSED_STATE_SET
1669     */
1670    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1671    /**
1672     * Indicates the view is focused and selected.
1673     *
1674     * @see #FOCUSED_STATE_SET
1675     * @see #SELECTED_STATE_SET
1676     */
1677    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1678    /**
1679     * Indicates the view has the focus and that its window has the focus.
1680     *
1681     * @see #FOCUSED_STATE_SET
1682     * @see #WINDOW_FOCUSED_STATE_SET
1683     */
1684    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1685    /**
1686     * Indicates the view is selected and that its window has the focus.
1687     *
1688     * @see #SELECTED_STATE_SET
1689     * @see #WINDOW_FOCUSED_STATE_SET
1690     */
1691    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1692    // Triples
1693    /**
1694     * Indicates the view is enabled, focused and selected.
1695     *
1696     * @see #ENABLED_STATE_SET
1697     * @see #FOCUSED_STATE_SET
1698     * @see #SELECTED_STATE_SET
1699     */
1700    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1701    /**
1702     * Indicates the view is enabled, focused and its window has the focus.
1703     *
1704     * @see #ENABLED_STATE_SET
1705     * @see #FOCUSED_STATE_SET
1706     * @see #WINDOW_FOCUSED_STATE_SET
1707     */
1708    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1709    /**
1710     * Indicates the view is enabled, selected and its window has the focus.
1711     *
1712     * @see #ENABLED_STATE_SET
1713     * @see #SELECTED_STATE_SET
1714     * @see #WINDOW_FOCUSED_STATE_SET
1715     */
1716    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1717    /**
1718     * Indicates the view is focused, selected and its window has the focus.
1719     *
1720     * @see #FOCUSED_STATE_SET
1721     * @see #SELECTED_STATE_SET
1722     * @see #WINDOW_FOCUSED_STATE_SET
1723     */
1724    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1725    /**
1726     * Indicates the view is enabled, focused, selected and its window
1727     * has the focus.
1728     *
1729     * @see #ENABLED_STATE_SET
1730     * @see #FOCUSED_STATE_SET
1731     * @see #SELECTED_STATE_SET
1732     * @see #WINDOW_FOCUSED_STATE_SET
1733     */
1734    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1735    /**
1736     * Indicates the view is pressed and its window has the focus.
1737     *
1738     * @see #PRESSED_STATE_SET
1739     * @see #WINDOW_FOCUSED_STATE_SET
1740     */
1741    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1742    /**
1743     * Indicates the view is pressed and selected.
1744     *
1745     * @see #PRESSED_STATE_SET
1746     * @see #SELECTED_STATE_SET
1747     */
1748    protected static final int[] PRESSED_SELECTED_STATE_SET;
1749    /**
1750     * Indicates the view is pressed, selected and its window has the focus.
1751     *
1752     * @see #PRESSED_STATE_SET
1753     * @see #SELECTED_STATE_SET
1754     * @see #WINDOW_FOCUSED_STATE_SET
1755     */
1756    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1757    /**
1758     * Indicates the view is pressed and focused.
1759     *
1760     * @see #PRESSED_STATE_SET
1761     * @see #FOCUSED_STATE_SET
1762     */
1763    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1764    /**
1765     * Indicates the view is pressed, focused and its window has the focus.
1766     *
1767     * @see #PRESSED_STATE_SET
1768     * @see #FOCUSED_STATE_SET
1769     * @see #WINDOW_FOCUSED_STATE_SET
1770     */
1771    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1772    /**
1773     * Indicates the view is pressed, focused and selected.
1774     *
1775     * @see #PRESSED_STATE_SET
1776     * @see #SELECTED_STATE_SET
1777     * @see #FOCUSED_STATE_SET
1778     */
1779    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1780    /**
1781     * Indicates the view is pressed, focused, selected and its window has the focus.
1782     *
1783     * @see #PRESSED_STATE_SET
1784     * @see #FOCUSED_STATE_SET
1785     * @see #SELECTED_STATE_SET
1786     * @see #WINDOW_FOCUSED_STATE_SET
1787     */
1788    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1789    /**
1790     * Indicates the view is pressed and enabled.
1791     *
1792     * @see #PRESSED_STATE_SET
1793     * @see #ENABLED_STATE_SET
1794     */
1795    protected static final int[] PRESSED_ENABLED_STATE_SET;
1796    /**
1797     * Indicates the view is pressed, enabled and its window has the focus.
1798     *
1799     * @see #PRESSED_STATE_SET
1800     * @see #ENABLED_STATE_SET
1801     * @see #WINDOW_FOCUSED_STATE_SET
1802     */
1803    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1804    /**
1805     * Indicates the view is pressed, enabled and selected.
1806     *
1807     * @see #PRESSED_STATE_SET
1808     * @see #ENABLED_STATE_SET
1809     * @see #SELECTED_STATE_SET
1810     */
1811    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1812    /**
1813     * Indicates the view is pressed, enabled, selected and its window has the
1814     * focus.
1815     *
1816     * @see #PRESSED_STATE_SET
1817     * @see #ENABLED_STATE_SET
1818     * @see #SELECTED_STATE_SET
1819     * @see #WINDOW_FOCUSED_STATE_SET
1820     */
1821    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1822    /**
1823     * Indicates the view is pressed, enabled and focused.
1824     *
1825     * @see #PRESSED_STATE_SET
1826     * @see #ENABLED_STATE_SET
1827     * @see #FOCUSED_STATE_SET
1828     */
1829    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1830    /**
1831     * Indicates the view is pressed, enabled, focused and its window has the
1832     * focus.
1833     *
1834     * @see #PRESSED_STATE_SET
1835     * @see #ENABLED_STATE_SET
1836     * @see #FOCUSED_STATE_SET
1837     * @see #WINDOW_FOCUSED_STATE_SET
1838     */
1839    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1840    /**
1841     * Indicates the view is pressed, enabled, focused and selected.
1842     *
1843     * @see #PRESSED_STATE_SET
1844     * @see #ENABLED_STATE_SET
1845     * @see #SELECTED_STATE_SET
1846     * @see #FOCUSED_STATE_SET
1847     */
1848    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1849    /**
1850     * Indicates the view is pressed, enabled, focused, selected and its window
1851     * has the focus.
1852     *
1853     * @see #PRESSED_STATE_SET
1854     * @see #ENABLED_STATE_SET
1855     * @see #SELECTED_STATE_SET
1856     * @see #FOCUSED_STATE_SET
1857     * @see #WINDOW_FOCUSED_STATE_SET
1858     */
1859    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1860
1861    static {
1862        EMPTY_STATE_SET = StateSet.get(0);
1863
1864        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1865
1866        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1867        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1868                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1869
1870        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1871        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1872                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1873        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1874                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1875        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1876                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1877                        | StateSet.VIEW_STATE_FOCUSED);
1878
1879        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1880        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1881                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1882        ENABLED_SELECTED_STATE_SET = StateSet.get(
1883                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1884        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1885                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1886                        | StateSet.VIEW_STATE_ENABLED);
1887        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1888                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1889        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1890                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1891                        | StateSet.VIEW_STATE_ENABLED);
1892        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1893                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1894                        | StateSet.VIEW_STATE_ENABLED);
1895        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1896                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1897                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1898
1899        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1900        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1901                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1902        PRESSED_SELECTED_STATE_SET = StateSet.get(
1903                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1904        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1905                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1906                        | StateSet.VIEW_STATE_PRESSED);
1907        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1908                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1909        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1910                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1911                        | StateSet.VIEW_STATE_PRESSED);
1912        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1913                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1914                        | StateSet.VIEW_STATE_PRESSED);
1915        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1916                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1917                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1918        PRESSED_ENABLED_STATE_SET = StateSet.get(
1919                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1920        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1921                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1922                        | StateSet.VIEW_STATE_PRESSED);
1923        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1924                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1925                        | StateSet.VIEW_STATE_PRESSED);
1926        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1927                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1928                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1929        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1930                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1931                        | StateSet.VIEW_STATE_PRESSED);
1932        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1933                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1934                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1935        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1936                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1937                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1938        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1939                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1940                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1941                        | StateSet.VIEW_STATE_PRESSED);
1942    }
1943
1944    /**
1945     * Accessibility event types that are dispatched for text population.
1946     */
1947    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1948            AccessibilityEvent.TYPE_VIEW_CLICKED
1949            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1950            | AccessibilityEvent.TYPE_VIEW_SELECTED
1951            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1952            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1953            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1954            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1955            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1956            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1957            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1958            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1959
1960    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1961
1962    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1963
1964    /**
1965     * Temporary Rect currently for use in setBackground().  This will probably
1966     * be extended in the future to hold our own class with more than just
1967     * a Rect. :)
1968     */
1969    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1970
1971    /**
1972     * Map used to store views' tags.
1973     */
1974    private SparseArray<Object> mKeyedTags;
1975
1976    /**
1977     * The animation currently associated with this view.
1978     * @hide
1979     */
1980    protected Animation mCurrentAnimation = null;
1981
1982    /**
1983     * Width as measured during measure pass.
1984     * {@hide}
1985     */
1986    @ViewDebug.ExportedProperty(category = "measurement")
1987    int mMeasuredWidth;
1988
1989    /**
1990     * Height as measured during measure pass.
1991     * {@hide}
1992     */
1993    @ViewDebug.ExportedProperty(category = "measurement")
1994    int mMeasuredHeight;
1995
1996    /**
1997     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1998     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1999     * its display list. This flag, used only when hw accelerated, allows us to clear the
2000     * flag while retaining this information until it's needed (at getDisplayList() time and
2001     * in drawChild(), when we decide to draw a view's children's display lists into our own).
2002     *
2003     * {@hide}
2004     */
2005    boolean mRecreateDisplayList = false;
2006
2007    /**
2008     * The view's identifier.
2009     * {@hide}
2010     *
2011     * @see #setId(int)
2012     * @see #getId()
2013     */
2014    @IdRes
2015    @ViewDebug.ExportedProperty(resolveId = true)
2016    int mID = NO_ID;
2017
2018    /** The ID of this view for accessibility and autofill purposes.
2019     * <ul>
2020     *     <li>== {@link #NO_ID}: ID has not been assigned yet
2021     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
2022     *                                                  unique in the process. This might change
2023     *                                                  over activity lifecycle events.
2024     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
2025     *                                                  unique in the activity. This stays the same
2026     *                                                  over activity lifecycle events.
2027     */
2028    private int mAccessibilityViewId = NO_ID;
2029
2030    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2031
2032    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2033
2034    /**
2035     * The view's tag.
2036     * {@hide}
2037     *
2038     * @see #setTag(Object)
2039     * @see #getTag()
2040     */
2041    protected Object mTag = null;
2042
2043    // for mPrivateFlags:
2044    /** {@hide} */
2045    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2046    /** {@hide} */
2047    static final int PFLAG_FOCUSED                     = 0x00000002;
2048    /** {@hide} */
2049    static final int PFLAG_SELECTED                    = 0x00000004;
2050    /** {@hide} */
2051    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2052    /** {@hide} */
2053    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2054    /** {@hide} */
2055    static final int PFLAG_DRAWN                       = 0x00000020;
2056    /**
2057     * When this flag is set, this view is running an animation on behalf of its
2058     * children and should therefore not cancel invalidate requests, even if they
2059     * lie outside of this view's bounds.
2060     *
2061     * {@hide}
2062     */
2063    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2064    /** {@hide} */
2065    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2066    /** {@hide} */
2067    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2068    /** {@hide} */
2069    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2070    /** {@hide} */
2071    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2072    /** {@hide} */
2073    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2074    /** {@hide} */
2075    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2076
2077    private static final int PFLAG_PRESSED             = 0x00004000;
2078
2079    /** {@hide} */
2080    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2081    /**
2082     * Flag used to indicate that this view should be drawn once more (and only once
2083     * more) after its animation has completed.
2084     * {@hide}
2085     */
2086    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2087
2088    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2089
2090    /**
2091     * Indicates that the View returned true when onSetAlpha() was called and that
2092     * the alpha must be restored.
2093     * {@hide}
2094     */
2095    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2096
2097    /**
2098     * Set by {@link #setScrollContainer(boolean)}.
2099     */
2100    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2101
2102    /**
2103     * Set by {@link #setScrollContainer(boolean)}.
2104     */
2105    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2106
2107    /**
2108     * View flag indicating whether this view was invalidated (fully or partially.)
2109     *
2110     * @hide
2111     */
2112    static final int PFLAG_DIRTY                       = 0x00200000;
2113
2114    /**
2115     * View flag indicating whether this view was invalidated by an opaque
2116     * invalidate request.
2117     *
2118     * @hide
2119     */
2120    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2121
2122    /**
2123     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2124     *
2125     * @hide
2126     */
2127    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2128
2129    /**
2130     * Indicates whether the background is opaque.
2131     *
2132     * @hide
2133     */
2134    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2135
2136    /**
2137     * Indicates whether the scrollbars are opaque.
2138     *
2139     * @hide
2140     */
2141    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2142
2143    /**
2144     * Indicates whether the view is opaque.
2145     *
2146     * @hide
2147     */
2148    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2149
2150    /**
2151     * Indicates a prepressed state;
2152     * the short time between ACTION_DOWN and recognizing
2153     * a 'real' press. Prepressed is used to recognize quick taps
2154     * even when they are shorter than ViewConfiguration.getTapTimeout().
2155     *
2156     * @hide
2157     */
2158    private static final int PFLAG_PREPRESSED          = 0x02000000;
2159
2160    /**
2161     * Indicates whether the view is temporarily detached.
2162     *
2163     * @hide
2164     */
2165    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2166
2167    /**
2168     * Indicates that we should awaken scroll bars once attached
2169     *
2170     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2171     * during window attachment and it is no longer needed. Feel free to repurpose it.
2172     *
2173     * @hide
2174     */
2175    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2176
2177    /**
2178     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2179     * @hide
2180     */
2181    private static final int PFLAG_HOVERED             = 0x10000000;
2182
2183    /**
2184     * no longer needed, should be reused
2185     */
2186    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2187
2188    /** {@hide} */
2189    static final int PFLAG_ACTIVATED                   = 0x40000000;
2190
2191    /**
2192     * Indicates that this view was specifically invalidated, not just dirtied because some
2193     * child view was invalidated. The flag is used to determine when we need to recreate
2194     * a view's display list (as opposed to just returning a reference to its existing
2195     * display list).
2196     *
2197     * @hide
2198     */
2199    static final int PFLAG_INVALIDATED                 = 0x80000000;
2200
2201    /**
2202     * Masks for mPrivateFlags2, as generated by dumpFlags():
2203     *
2204     * |-------|-------|-------|-------|
2205     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2206     *                                1  PFLAG2_DRAG_HOVERED
2207     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2208     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2209     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2210     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2211     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2212     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2213     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2214     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2215     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2216     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2217     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2218     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2219     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2220     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2221     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2222     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2223     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2224     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2225     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2226     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2227     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2228     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2229     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2230     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2231     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2232     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2233     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2234     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2235     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2236     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2237     *    1                              PFLAG2_PADDING_RESOLVED
2238     *   1                               PFLAG2_DRAWABLE_RESOLVED
2239     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2240     * |-------|-------|-------|-------|
2241     */
2242
2243    /**
2244     * Indicates that this view has reported that it can accept the current drag's content.
2245     * Cleared when the drag operation concludes.
2246     * @hide
2247     */
2248    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2249
2250    /**
2251     * Indicates that this view is currently directly under the drag location in a
2252     * drag-and-drop operation involving content that it can accept.  Cleared when
2253     * the drag exits the view, or when the drag operation concludes.
2254     * @hide
2255     */
2256    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2257
2258    /** @hide */
2259    @IntDef({
2260        LAYOUT_DIRECTION_LTR,
2261        LAYOUT_DIRECTION_RTL,
2262        LAYOUT_DIRECTION_INHERIT,
2263        LAYOUT_DIRECTION_LOCALE
2264    })
2265    @Retention(RetentionPolicy.SOURCE)
2266    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2267    public @interface LayoutDir {}
2268
2269    /** @hide */
2270    @IntDef({
2271        LAYOUT_DIRECTION_LTR,
2272        LAYOUT_DIRECTION_RTL
2273    })
2274    @Retention(RetentionPolicy.SOURCE)
2275    public @interface ResolvedLayoutDir {}
2276
2277    /**
2278     * A flag to indicate that the layout direction of this view has not been defined yet.
2279     * @hide
2280     */
2281    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2282
2283    /**
2284     * Horizontal layout direction of this view is from Left to Right.
2285     * Use with {@link #setLayoutDirection}.
2286     */
2287    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2288
2289    /**
2290     * Horizontal layout direction of this view is from Right to Left.
2291     * Use with {@link #setLayoutDirection}.
2292     */
2293    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2294
2295    /**
2296     * Horizontal layout direction of this view is inherited from its parent.
2297     * Use with {@link #setLayoutDirection}.
2298     */
2299    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2300
2301    /**
2302     * Horizontal layout direction of this view is from deduced from the default language
2303     * script for the locale. Use with {@link #setLayoutDirection}.
2304     */
2305    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2306
2307    /**
2308     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2309     * @hide
2310     */
2311    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2312
2313    /**
2314     * Mask for use with private flags indicating bits used for horizontal layout direction.
2315     * @hide
2316     */
2317    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2318
2319    /**
2320     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2321     * right-to-left direction.
2322     * @hide
2323     */
2324    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2325
2326    /**
2327     * Indicates whether the view horizontal layout direction has been resolved.
2328     * @hide
2329     */
2330    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2331
2332    /**
2333     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2334     * @hide
2335     */
2336    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2337            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2338
2339    /*
2340     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2341     * flag value.
2342     * @hide
2343     */
2344    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2345            LAYOUT_DIRECTION_LTR,
2346            LAYOUT_DIRECTION_RTL,
2347            LAYOUT_DIRECTION_INHERIT,
2348            LAYOUT_DIRECTION_LOCALE
2349    };
2350
2351    /**
2352     * Default horizontal layout direction.
2353     */
2354    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2355
2356    /**
2357     * Default horizontal layout direction.
2358     * @hide
2359     */
2360    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2361
2362    /**
2363     * Text direction is inherited through {@link ViewGroup}
2364     */
2365    public static final int TEXT_DIRECTION_INHERIT = 0;
2366
2367    /**
2368     * Text direction is using "first strong algorithm". The first strong directional character
2369     * determines the paragraph direction. If there is no strong directional character, the
2370     * paragraph direction is the view's resolved layout direction.
2371     */
2372    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2373
2374    /**
2375     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2376     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2377     * If there are neither, the paragraph direction is the view's resolved layout direction.
2378     */
2379    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2380
2381    /**
2382     * Text direction is forced to LTR.
2383     */
2384    public static final int TEXT_DIRECTION_LTR = 3;
2385
2386    /**
2387     * Text direction is forced to RTL.
2388     */
2389    public static final int TEXT_DIRECTION_RTL = 4;
2390
2391    /**
2392     * Text direction is coming from the system Locale.
2393     */
2394    public static final int TEXT_DIRECTION_LOCALE = 5;
2395
2396    /**
2397     * Text direction is using "first strong algorithm". The first strong directional character
2398     * determines the paragraph direction. If there is no strong directional character, the
2399     * paragraph direction is LTR.
2400     */
2401    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2402
2403    /**
2404     * Text direction is using "first strong algorithm". The first strong directional character
2405     * determines the paragraph direction. If there is no strong directional character, the
2406     * paragraph direction is RTL.
2407     */
2408    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2409
2410    /**
2411     * Default text direction is inherited
2412     */
2413    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2414
2415    /**
2416     * Default resolved text direction
2417     * @hide
2418     */
2419    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2420
2421    /**
2422     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2423     * @hide
2424     */
2425    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2426
2427    /**
2428     * Mask for use with private flags indicating bits used for text direction.
2429     * @hide
2430     */
2431    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2432            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2433
2434    /**
2435     * Array of text direction flags for mapping attribute "textDirection" to correct
2436     * flag value.
2437     * @hide
2438     */
2439    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2440            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2441            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2442            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2443            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2444            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2445            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2446            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2447            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2448    };
2449
2450    /**
2451     * Indicates whether the view text direction has been resolved.
2452     * @hide
2453     */
2454    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2455            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2456
2457    /**
2458     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2459     * @hide
2460     */
2461    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2462
2463    /**
2464     * Mask for use with private flags indicating bits used for resolved text direction.
2465     * @hide
2466     */
2467    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2468            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2469
2470    /**
2471     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2472     * @hide
2473     */
2474    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2475            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2476
2477    /** @hide */
2478    @IntDef({
2479        TEXT_ALIGNMENT_INHERIT,
2480        TEXT_ALIGNMENT_GRAVITY,
2481        TEXT_ALIGNMENT_CENTER,
2482        TEXT_ALIGNMENT_TEXT_START,
2483        TEXT_ALIGNMENT_TEXT_END,
2484        TEXT_ALIGNMENT_VIEW_START,
2485        TEXT_ALIGNMENT_VIEW_END
2486    })
2487    @Retention(RetentionPolicy.SOURCE)
2488    public @interface TextAlignment {}
2489
2490    /**
2491     * Default text alignment. The text alignment of this View is inherited from its parent.
2492     * Use with {@link #setTextAlignment(int)}
2493     */
2494    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2495
2496    /**
2497     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2498     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2499     *
2500     * Use with {@link #setTextAlignment(int)}
2501     */
2502    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2503
2504    /**
2505     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2506     *
2507     * Use with {@link #setTextAlignment(int)}
2508     */
2509    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2510
2511    /**
2512     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2513     *
2514     * Use with {@link #setTextAlignment(int)}
2515     */
2516    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2517
2518    /**
2519     * Center the paragraph, e.g. ALIGN_CENTER.
2520     *
2521     * Use with {@link #setTextAlignment(int)}
2522     */
2523    public static final int TEXT_ALIGNMENT_CENTER = 4;
2524
2525    /**
2526     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2527     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2528     *
2529     * Use with {@link #setTextAlignment(int)}
2530     */
2531    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2532
2533    /**
2534     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2535     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2536     *
2537     * Use with {@link #setTextAlignment(int)}
2538     */
2539    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2540
2541    /**
2542     * Default text alignment is inherited
2543     */
2544    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2545
2546    /**
2547     * Default resolved text alignment
2548     * @hide
2549     */
2550    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2551
2552    /**
2553      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2554      * @hide
2555      */
2556    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2557
2558    /**
2559      * Mask for use with private flags indicating bits used for text alignment.
2560      * @hide
2561      */
2562    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2563
2564    /**
2565     * Array of text direction flags for mapping attribute "textAlignment" to correct
2566     * flag value.
2567     * @hide
2568     */
2569    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2570            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2571            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2572            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2573            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2574            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2575            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2576            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2577    };
2578
2579    /**
2580     * Indicates whether the view text alignment has been resolved.
2581     * @hide
2582     */
2583    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2584
2585    /**
2586     * Bit shift to get the resolved text alignment.
2587     * @hide
2588     */
2589    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2590
2591    /**
2592     * Mask for use with private flags indicating bits used for text alignment.
2593     * @hide
2594     */
2595    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2596            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2597
2598    /**
2599     * Indicates whether if the view text alignment has been resolved to gravity
2600     */
2601    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2602            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2603
2604    // Accessiblity constants for mPrivateFlags2
2605
2606    /**
2607     * Shift for the bits in {@link #mPrivateFlags2} related to the
2608     * "importantForAccessibility" attribute.
2609     */
2610    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2611
2612    /**
2613     * Automatically determine whether a view is important for accessibility.
2614     */
2615    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2616
2617    /**
2618     * The view is important for accessibility.
2619     */
2620    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2621
2622    /**
2623     * The view is not important for accessibility.
2624     */
2625    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2626
2627    /**
2628     * The view is not important for accessibility, nor are any of its
2629     * descendant views.
2630     */
2631    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2632
2633    /**
2634     * The default whether the view is important for accessibility.
2635     */
2636    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2637
2638    /**
2639     * Mask for obtaining the bits which specify how to determine
2640     * whether a view is important for accessibility.
2641     */
2642    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2643        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2644        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2645        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2646
2647    /**
2648     * Shift for the bits in {@link #mPrivateFlags2} related to the
2649     * "accessibilityLiveRegion" attribute.
2650     */
2651    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2652
2653    /**
2654     * Live region mode specifying that accessibility services should not
2655     * automatically announce changes to this view. This is the default live
2656     * region mode for most views.
2657     * <p>
2658     * Use with {@link #setAccessibilityLiveRegion(int)}.
2659     */
2660    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2661
2662    /**
2663     * Live region mode specifying that accessibility services should announce
2664     * changes to this view.
2665     * <p>
2666     * Use with {@link #setAccessibilityLiveRegion(int)}.
2667     */
2668    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2669
2670    /**
2671     * Live region mode specifying that accessibility services should interrupt
2672     * ongoing speech to immediately announce changes to this view.
2673     * <p>
2674     * Use with {@link #setAccessibilityLiveRegion(int)}.
2675     */
2676    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2677
2678    /**
2679     * The default whether the view is important for accessibility.
2680     */
2681    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2682
2683    /**
2684     * Mask for obtaining the bits which specify a view's accessibility live
2685     * region mode.
2686     */
2687    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2688            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2689            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2690
2691    /**
2692     * Flag indicating whether a view has accessibility focus.
2693     */
2694    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2695
2696    /**
2697     * Flag whether the accessibility state of the subtree rooted at this view changed.
2698     */
2699    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2700
2701    /**
2702     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2703     * is used to check whether later changes to the view's transform should invalidate the
2704     * view to force the quickReject test to run again.
2705     */
2706    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2707
2708    /**
2709     * Flag indicating that start/end padding has been resolved into left/right padding
2710     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2711     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2712     * during measurement. In some special cases this is required such as when an adapter-based
2713     * view measures prospective children without attaching them to a window.
2714     */
2715    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2716
2717    /**
2718     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2719     */
2720    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2721
2722    /**
2723     * Indicates that the view is tracking some sort of transient state
2724     * that the app should not need to be aware of, but that the framework
2725     * should take special care to preserve.
2726     */
2727    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2728
2729    /**
2730     * Group of bits indicating that RTL properties resolution is done.
2731     */
2732    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2733            PFLAG2_TEXT_DIRECTION_RESOLVED |
2734            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2735            PFLAG2_PADDING_RESOLVED |
2736            PFLAG2_DRAWABLE_RESOLVED;
2737
2738    // There are a couple of flags left in mPrivateFlags2
2739
2740    /* End of masks for mPrivateFlags2 */
2741
2742    /**
2743     * Masks for mPrivateFlags3, as generated by dumpFlags():
2744     *
2745     * |-------|-------|-------|-------|
2746     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2747     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2748     *                               1   PFLAG3_IS_LAID_OUT
2749     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2750     *                             1     PFLAG3_CALLED_SUPER
2751     *                            1      PFLAG3_APPLYING_INSETS
2752     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2753     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2754     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2755     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2756     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2757     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2758     *                     1             PFLAG3_SCROLL_INDICATOR_START
2759     *                    1              PFLAG3_SCROLL_INDICATOR_END
2760     *                   1               PFLAG3_ASSIST_BLOCKED
2761     *                  1                PFLAG3_CLUSTER
2762     *                 1                 PFLAG3_IS_AUTOFILLED
2763     *                1                  PFLAG3_FINGER_DOWN
2764     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2765     *             11                    PFLAG3_AUTO_FILL_MODE_MASK
2766     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
2767     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2768     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2769     *        1                          PFLAG3_TEMPORARY_DETACH
2770     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2771     * |-------|-------|-------|-------|
2772     */
2773
2774    /**
2775     * Flag indicating that view has a transform animation set on it. This is used to track whether
2776     * an animation is cleared between successive frames, in order to tell the associated
2777     * DisplayList to clear its animation matrix.
2778     */
2779    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2780
2781    /**
2782     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2783     * animation is cleared between successive frames, in order to tell the associated
2784     * DisplayList to restore its alpha value.
2785     */
2786    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2787
2788    /**
2789     * Flag indicating that the view has been through at least one layout since it
2790     * was last attached to a window.
2791     */
2792    static final int PFLAG3_IS_LAID_OUT = 0x4;
2793
2794    /**
2795     * Flag indicating that a call to measure() was skipped and should be done
2796     * instead when layout() is invoked.
2797     */
2798    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2799
2800    /**
2801     * Flag indicating that an overridden method correctly called down to
2802     * the superclass implementation as required by the API spec.
2803     */
2804    static final int PFLAG3_CALLED_SUPER = 0x10;
2805
2806    /**
2807     * Flag indicating that we're in the process of applying window insets.
2808     */
2809    static final int PFLAG3_APPLYING_INSETS = 0x20;
2810
2811    /**
2812     * Flag indicating that we're in the process of fitting system windows using the old method.
2813     */
2814    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2815
2816    /**
2817     * Flag indicating that nested scrolling is enabled for this view.
2818     * The view will optionally cooperate with views up its parent chain to allow for
2819     * integrated nested scrolling along the same axis.
2820     */
2821    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2822
2823    /**
2824     * Flag indicating that the bottom scroll indicator should be displayed
2825     * when this view can scroll up.
2826     */
2827    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2828
2829    /**
2830     * Flag indicating that the bottom scroll indicator should be displayed
2831     * when this view can scroll down.
2832     */
2833    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2834
2835    /**
2836     * Flag indicating that the left scroll indicator should be displayed
2837     * when this view can scroll left.
2838     */
2839    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2840
2841    /**
2842     * Flag indicating that the right scroll indicator should be displayed
2843     * when this view can scroll right.
2844     */
2845    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2846
2847    /**
2848     * Flag indicating that the start scroll indicator should be displayed
2849     * when this view can scroll in the start direction.
2850     */
2851    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2852
2853    /**
2854     * Flag indicating that the end scroll indicator should be displayed
2855     * when this view can scroll in the end direction.
2856     */
2857    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2858
2859    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2860
2861    static final int SCROLL_INDICATORS_NONE = 0x0000;
2862
2863    /**
2864     * Mask for use with setFlags indicating bits used for indicating which
2865     * scroll indicators are enabled.
2866     */
2867    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2868            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2869            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2870            | PFLAG3_SCROLL_INDICATOR_END;
2871
2872    /**
2873     * Left-shift required to translate between public scroll indicator flags
2874     * and internal PFLAGS3 flags. When used as a right-shift, translates
2875     * PFLAGS3 flags to public flags.
2876     */
2877    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2878
2879    /** @hide */
2880    @Retention(RetentionPolicy.SOURCE)
2881    @IntDef(flag = true,
2882            value = {
2883                    SCROLL_INDICATOR_TOP,
2884                    SCROLL_INDICATOR_BOTTOM,
2885                    SCROLL_INDICATOR_LEFT,
2886                    SCROLL_INDICATOR_RIGHT,
2887                    SCROLL_INDICATOR_START,
2888                    SCROLL_INDICATOR_END,
2889            })
2890    public @interface ScrollIndicators {}
2891
2892    /**
2893     * Scroll indicator direction for the top edge of the view.
2894     *
2895     * @see #setScrollIndicators(int)
2896     * @see #setScrollIndicators(int, int)
2897     * @see #getScrollIndicators()
2898     */
2899    public static final int SCROLL_INDICATOR_TOP =
2900            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2901
2902    /**
2903     * Scroll indicator direction for the bottom edge of the view.
2904     *
2905     * @see #setScrollIndicators(int)
2906     * @see #setScrollIndicators(int, int)
2907     * @see #getScrollIndicators()
2908     */
2909    public static final int SCROLL_INDICATOR_BOTTOM =
2910            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2911
2912    /**
2913     * Scroll indicator direction for the left edge of the view.
2914     *
2915     * @see #setScrollIndicators(int)
2916     * @see #setScrollIndicators(int, int)
2917     * @see #getScrollIndicators()
2918     */
2919    public static final int SCROLL_INDICATOR_LEFT =
2920            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2921
2922    /**
2923     * Scroll indicator direction for the right edge of the view.
2924     *
2925     * @see #setScrollIndicators(int)
2926     * @see #setScrollIndicators(int, int)
2927     * @see #getScrollIndicators()
2928     */
2929    public static final int SCROLL_INDICATOR_RIGHT =
2930            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2931
2932    /**
2933     * Scroll indicator direction for the starting edge of the view.
2934     * <p>
2935     * Resolved according to the view's layout direction, see
2936     * {@link #getLayoutDirection()} for more information.
2937     *
2938     * @see #setScrollIndicators(int)
2939     * @see #setScrollIndicators(int, int)
2940     * @see #getScrollIndicators()
2941     */
2942    public static final int SCROLL_INDICATOR_START =
2943            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2944
2945    /**
2946     * Scroll indicator direction for the ending edge of the view.
2947     * <p>
2948     * Resolved according to the view's layout direction, see
2949     * {@link #getLayoutDirection()} for more information.
2950     *
2951     * @see #setScrollIndicators(int)
2952     * @see #setScrollIndicators(int, int)
2953     * @see #getScrollIndicators()
2954     */
2955    public static final int SCROLL_INDICATOR_END =
2956            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2957
2958    /**
2959     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2960     * into this view.<p>
2961     */
2962    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2963
2964    /**
2965     * Flag indicating that the view is a root of a keyboard navigation cluster.
2966     *
2967     * @see #isKeyboardNavigationCluster()
2968     * @see #setKeyboardNavigationCluster(boolean)
2969     */
2970    private static final int PFLAG3_CLUSTER = 0x8000;
2971
2972    /**
2973     * Flag indicating that the view is autofilled
2974     *
2975     * @see #isAutofilled()
2976     * @see #setAutofilled(boolean)
2977     */
2978    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
2979
2980    /**
2981     * Indicates that the user is currently touching the screen.
2982     * Currently used for the tooltip positioning only.
2983     */
2984    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2985
2986    /**
2987     * Flag indicating that this view is the default-focus view.
2988     *
2989     * @see #isFocusedByDefault()
2990     * @see #setFocusedByDefault(boolean)
2991     */
2992    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2993
2994    /**
2995     * Shift for the place where the autofill mode is stored in the pflags
2996     *
2997     * @see #getAutofillMode()
2998     * @see #setAutofillMode(int)
2999     */
3000    private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
3001
3002    /**
3003     * Mask for autofill modes
3004     *
3005     * @see #getAutofillMode()
3006     * @see #setAutofillMode(int)
3007     */
3008    private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
3009            | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
3010
3011    /**
3012     * Shift for the bits in {@link #mPrivateFlags3} related to the
3013     * "importantForAutofill" attribute.
3014     */
3015    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
3016
3017    /**
3018     * Mask for obtaining the bits which specify how to determine
3019     * whether a view is important for autofill.
3020     */
3021    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3022            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
3023            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3024
3025    /**
3026     * Whether this view has rendered elements that overlap (see {@link
3027     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3028     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3029     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3030     * determined by whatever {@link #hasOverlappingRendering()} returns.
3031     */
3032    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3033
3034    /**
3035     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3036     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3037     */
3038    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3039
3040    /**
3041     * Flag indicating that the view is temporarily detached from the parent view.
3042     *
3043     * @see #onStartTemporaryDetach()
3044     * @see #onFinishTemporaryDetach()
3045     */
3046    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3047
3048    /**
3049     * Flag indicating that the view does not wish to be revealed within its parent
3050     * hierarchy when it gains focus. Expressed in the negative since the historical
3051     * default behavior is to reveal on focus; this flag suppresses that behavior.
3052     *
3053     * @see #setRevealOnFocusHint(boolean)
3054     * @see #getRevealOnFocusHint()
3055     */
3056    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3057
3058    /* End of masks for mPrivateFlags3 */
3059
3060    /**
3061     * Always allow a user to over-scroll this view, provided it is a
3062     * view that can scroll.
3063     *
3064     * @see #getOverScrollMode()
3065     * @see #setOverScrollMode(int)
3066     */
3067    public static final int OVER_SCROLL_ALWAYS = 0;
3068
3069    /**
3070     * Allow a user to over-scroll this view only if the content is large
3071     * enough to meaningfully scroll, provided it is a view that can scroll.
3072     *
3073     * @see #getOverScrollMode()
3074     * @see #setOverScrollMode(int)
3075     */
3076    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3077
3078    /**
3079     * Never allow a user to over-scroll this view.
3080     *
3081     * @see #getOverScrollMode()
3082     * @see #setOverScrollMode(int)
3083     */
3084    public static final int OVER_SCROLL_NEVER = 2;
3085
3086    /**
3087     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3088     * requested the system UI (status bar) to be visible (the default).
3089     *
3090     * @see #setSystemUiVisibility(int)
3091     */
3092    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3093
3094    /**
3095     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3096     * system UI to enter an unobtrusive "low profile" mode.
3097     *
3098     * <p>This is for use in games, book readers, video players, or any other
3099     * "immersive" application where the usual system chrome is deemed too distracting.
3100     *
3101     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3102     *
3103     * @see #setSystemUiVisibility(int)
3104     */
3105    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3106
3107    /**
3108     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3109     * system navigation be temporarily hidden.
3110     *
3111     * <p>This is an even less obtrusive state than that called for by
3112     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3113     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3114     * those to disappear. This is useful (in conjunction with the
3115     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3116     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3117     * window flags) for displaying content using every last pixel on the display.
3118     *
3119     * <p>There is a limitation: because navigation controls are so important, the least user
3120     * interaction will cause them to reappear immediately.  When this happens, both
3121     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3122     * so that both elements reappear at the same time.
3123     *
3124     * @see #setSystemUiVisibility(int)
3125     */
3126    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3127
3128    /**
3129     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3130     * into the normal fullscreen mode so that its content can take over the screen
3131     * while still allowing the user to interact with the application.
3132     *
3133     * <p>This has the same visual effect as
3134     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3135     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3136     * meaning that non-critical screen decorations (such as the status bar) will be
3137     * hidden while the user is in the View's window, focusing the experience on
3138     * that content.  Unlike the window flag, if you are using ActionBar in
3139     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3140     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3141     * hide the action bar.
3142     *
3143     * <p>This approach to going fullscreen is best used over the window flag when
3144     * it is a transient state -- that is, the application does this at certain
3145     * points in its user interaction where it wants to allow the user to focus
3146     * on content, but not as a continuous state.  For situations where the application
3147     * would like to simply stay full screen the entire time (such as a game that
3148     * wants to take over the screen), the
3149     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3150     * is usually a better approach.  The state set here will be removed by the system
3151     * in various situations (such as the user moving to another application) like
3152     * the other system UI states.
3153     *
3154     * <p>When using this flag, the application should provide some easy facility
3155     * for the user to go out of it.  A common example would be in an e-book
3156     * reader, where tapping on the screen brings back whatever screen and UI
3157     * decorations that had been hidden while the user was immersed in reading
3158     * the book.
3159     *
3160     * @see #setSystemUiVisibility(int)
3161     */
3162    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3163
3164    /**
3165     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3166     * flags, we would like a stable view of the content insets given to
3167     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3168     * will always represent the worst case that the application can expect
3169     * as a continuous state.  In the stock Android UI this is the space for
3170     * the system bar, nav bar, and status bar, but not more transient elements
3171     * such as an input method.
3172     *
3173     * The stable layout your UI sees is based on the system UI modes you can
3174     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3175     * then you will get a stable layout for changes of the
3176     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3177     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3178     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3179     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3180     * with a stable layout.  (Note that you should avoid using
3181     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3182     *
3183     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3184     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3185     * then a hidden status bar will be considered a "stable" state for purposes
3186     * here.  This allows your UI to continually hide the status bar, while still
3187     * using the system UI flags to hide the action bar while still retaining
3188     * a stable layout.  Note that changing the window fullscreen flag will never
3189     * provide a stable layout for a clean transition.
3190     *
3191     * <p>If you are using ActionBar in
3192     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3193     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3194     * insets it adds to those given to the application.
3195     */
3196    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3197
3198    /**
3199     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3200     * to be laid out as if it has requested
3201     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3202     * allows it to avoid artifacts when switching in and out of that mode, at
3203     * the expense that some of its user interface may be covered by screen
3204     * decorations when they are shown.  You can perform layout of your inner
3205     * UI elements to account for the navigation system UI through the
3206     * {@link #fitSystemWindows(Rect)} method.
3207     */
3208    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3209
3210    /**
3211     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3212     * to be laid out as if it has requested
3213     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3214     * allows it to avoid artifacts when switching in and out of that mode, at
3215     * the expense that some of its user interface may be covered by screen
3216     * decorations when they are shown.  You can perform layout of your inner
3217     * UI elements to account for non-fullscreen system UI through the
3218     * {@link #fitSystemWindows(Rect)} method.
3219     */
3220    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3221
3222    /**
3223     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3224     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3225     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3226     * user interaction.
3227     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3228     * has an effect when used in combination with that flag.</p>
3229     */
3230    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3231
3232    /**
3233     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3234     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3235     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3236     * experience while also hiding the system bars.  If this flag is not set,
3237     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3238     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3239     * if the user swipes from the top of the screen.
3240     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3241     * system gestures, such as swiping from the top of the screen.  These transient system bars
3242     * will overlay app’s content, may have some degree of transparency, and will automatically
3243     * hide after a short timeout.
3244     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3245     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3246     * with one or both of those flags.</p>
3247     */
3248    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3249
3250    /**
3251     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3252     * is compatible with light status bar backgrounds.
3253     *
3254     * <p>For this to take effect, the window must request
3255     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3256     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3257     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3258     *         FLAG_TRANSLUCENT_STATUS}.
3259     *
3260     * @see android.R.attr#windowLightStatusBar
3261     */
3262    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3263
3264    /**
3265     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3266     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3267     */
3268    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3269
3270    /**
3271     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3272     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3273     */
3274    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3275
3276    /**
3277     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3278     * that is compatible with light navigation bar backgrounds.
3279     *
3280     * <p>For this to take effect, the window must request
3281     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3282     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3283     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3284     *         FLAG_TRANSLUCENT_NAVIGATION}.
3285     */
3286    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3287
3288    /**
3289     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3290     */
3291    @Deprecated
3292    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3293
3294    /**
3295     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3296     */
3297    @Deprecated
3298    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3299
3300    /**
3301     * @hide
3302     *
3303     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3304     * out of the public fields to keep the undefined bits out of the developer's way.
3305     *
3306     * Flag to make the status bar not expandable.  Unless you also
3307     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3308     */
3309    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3310
3311    /**
3312     * @hide
3313     *
3314     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3315     * out of the public fields to keep the undefined bits out of the developer's way.
3316     *
3317     * Flag to hide notification icons and scrolling ticker text.
3318     */
3319    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3320
3321    /**
3322     * @hide
3323     *
3324     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3325     * out of the public fields to keep the undefined bits out of the developer's way.
3326     *
3327     * Flag to disable incoming notification alerts.  This will not block
3328     * icons, but it will block sound, vibrating and other visual or aural notifications.
3329     */
3330    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3331
3332    /**
3333     * @hide
3334     *
3335     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3336     * out of the public fields to keep the undefined bits out of the developer's way.
3337     *
3338     * Flag to hide only the scrolling ticker.  Note that
3339     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3340     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3341     */
3342    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3343
3344    /**
3345     * @hide
3346     *
3347     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3348     * out of the public fields to keep the undefined bits out of the developer's way.
3349     *
3350     * Flag to hide the center system info area.
3351     */
3352    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3353
3354    /**
3355     * @hide
3356     *
3357     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3358     * out of the public fields to keep the undefined bits out of the developer's way.
3359     *
3360     * Flag to hide only the home button.  Don't use this
3361     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3362     */
3363    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3364
3365    /**
3366     * @hide
3367     *
3368     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3369     * out of the public fields to keep the undefined bits out of the developer's way.
3370     *
3371     * Flag to hide only the back button. Don't use this
3372     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3373     */
3374    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3375
3376    /**
3377     * @hide
3378     *
3379     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3380     * out of the public fields to keep the undefined bits out of the developer's way.
3381     *
3382     * Flag to hide only the clock.  You might use this if your activity has
3383     * its own clock making the status bar's clock redundant.
3384     */
3385    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3386
3387    /**
3388     * @hide
3389     *
3390     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3391     * out of the public fields to keep the undefined bits out of the developer's way.
3392     *
3393     * Flag to hide only the recent apps button. Don't use this
3394     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3395     */
3396    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3397
3398    /**
3399     * @hide
3400     *
3401     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3402     * out of the public fields to keep the undefined bits out of the developer's way.
3403     *
3404     * Flag to disable the global search gesture. Don't use this
3405     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3406     */
3407    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3408
3409    /**
3410     * @hide
3411     *
3412     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3413     * out of the public fields to keep the undefined bits out of the developer's way.
3414     *
3415     * Flag to specify that the status bar is displayed in transient mode.
3416     */
3417    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3418
3419    /**
3420     * @hide
3421     *
3422     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3423     * out of the public fields to keep the undefined bits out of the developer's way.
3424     *
3425     * Flag to specify that the navigation bar is displayed in transient mode.
3426     */
3427    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
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 specify that the hidden status bar would like to be shown.
3436     */
3437    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3438
3439    /**
3440     * @hide
3441     *
3442     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3443     * out of the public fields to keep the undefined bits out of the developer's way.
3444     *
3445     * Flag to specify that the hidden navigation bar would like to be shown.
3446     */
3447    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3448
3449    /**
3450     * @hide
3451     *
3452     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3453     * out of the public fields to keep the undefined bits out of the developer's way.
3454     *
3455     * Flag to specify that the status bar is displayed in translucent mode.
3456     */
3457    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3458
3459    /**
3460     * @hide
3461     *
3462     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3463     * out of the public fields to keep the undefined bits out of the developer's way.
3464     *
3465     * Flag to specify that the navigation bar is displayed in translucent mode.
3466     */
3467    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3468
3469    /**
3470     * @hide
3471     *
3472     * Makes navigation bar transparent (but not the status bar).
3473     */
3474    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3475
3476    /**
3477     * @hide
3478     *
3479     * Makes status bar transparent (but not the navigation bar).
3480     */
3481    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3482
3483    /**
3484     * @hide
3485     *
3486     * Makes both status bar and navigation bar transparent.
3487     */
3488    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3489            | STATUS_BAR_TRANSPARENT;
3490
3491    /**
3492     * @hide
3493     */
3494    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3495
3496    /**
3497     * These are the system UI flags that can be cleared by events outside
3498     * of an application.  Currently this is just the ability to tap on the
3499     * screen while hiding the navigation bar to have it return.
3500     * @hide
3501     */
3502    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3503            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3504            | SYSTEM_UI_FLAG_FULLSCREEN;
3505
3506    /**
3507     * Flags that can impact the layout in relation to system UI.
3508     */
3509    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3510            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3511            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3512
3513    /** @hide */
3514    @IntDef(flag = true,
3515            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3516    @Retention(RetentionPolicy.SOURCE)
3517    public @interface FindViewFlags {}
3518
3519    /**
3520     * Find views that render the specified text.
3521     *
3522     * @see #findViewsWithText(ArrayList, CharSequence, int)
3523     */
3524    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3525
3526    /**
3527     * Find find views that contain the specified content description.
3528     *
3529     * @see #findViewsWithText(ArrayList, CharSequence, int)
3530     */
3531    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3532
3533    /**
3534     * Find views that contain {@link AccessibilityNodeProvider}. Such
3535     * a View is a root of virtual view hierarchy and may contain the searched
3536     * text. If this flag is set Views with providers are automatically
3537     * added and it is a responsibility of the client to call the APIs of
3538     * the provider to determine whether the virtual tree rooted at this View
3539     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3540     * representing the virtual views with this text.
3541     *
3542     * @see #findViewsWithText(ArrayList, CharSequence, int)
3543     *
3544     * @hide
3545     */
3546    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3547
3548    /**
3549     * The undefined cursor position.
3550     *
3551     * @hide
3552     */
3553    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3554
3555    /**
3556     * Indicates that the screen has changed state and is now off.
3557     *
3558     * @see #onScreenStateChanged(int)
3559     */
3560    public static final int SCREEN_STATE_OFF = 0x0;
3561
3562    /**
3563     * Indicates that the screen has changed state and is now on.
3564     *
3565     * @see #onScreenStateChanged(int)
3566     */
3567    public static final int SCREEN_STATE_ON = 0x1;
3568
3569    /**
3570     * Indicates no axis of view scrolling.
3571     */
3572    public static final int SCROLL_AXIS_NONE = 0;
3573
3574    /**
3575     * Indicates scrolling along the horizontal axis.
3576     */
3577    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3578
3579    /**
3580     * Indicates scrolling along the vertical axis.
3581     */
3582    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3583
3584    /**
3585     * Controls the over-scroll mode for this view.
3586     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3587     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3588     * and {@link #OVER_SCROLL_NEVER}.
3589     */
3590    private int mOverScrollMode;
3591
3592    /**
3593     * The parent this view is attached to.
3594     * {@hide}
3595     *
3596     * @see #getParent()
3597     */
3598    protected ViewParent mParent;
3599
3600    /**
3601     * {@hide}
3602     */
3603    AttachInfo mAttachInfo;
3604
3605    /**
3606     * {@hide}
3607     */
3608    @ViewDebug.ExportedProperty(flagMapping = {
3609        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3610                name = "FORCE_LAYOUT"),
3611        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3612                name = "LAYOUT_REQUIRED"),
3613        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3614            name = "DRAWING_CACHE_INVALID", outputIf = false),
3615        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3616        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3617        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3618        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3619    }, formatToHexString = true)
3620
3621    /* @hide */
3622    public int mPrivateFlags;
3623    int mPrivateFlags2;
3624    int mPrivateFlags3;
3625
3626    /**
3627     * This view's request for the visibility of the status bar.
3628     * @hide
3629     */
3630    @ViewDebug.ExportedProperty(flagMapping = {
3631        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3632                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3633                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3634        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3635                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3636                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3637        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3638                                equals = SYSTEM_UI_FLAG_VISIBLE,
3639                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3640    }, formatToHexString = true)
3641    int mSystemUiVisibility;
3642
3643    /**
3644     * Reference count for transient state.
3645     * @see #setHasTransientState(boolean)
3646     */
3647    int mTransientStateCount = 0;
3648
3649    /**
3650     * Count of how many windows this view has been attached to.
3651     */
3652    int mWindowAttachCount;
3653
3654    /**
3655     * The layout parameters associated with this view and used by the parent
3656     * {@link android.view.ViewGroup} to determine how this view should be
3657     * laid out.
3658     * {@hide}
3659     */
3660    protected ViewGroup.LayoutParams mLayoutParams;
3661
3662    /**
3663     * The view flags hold various views states.
3664     * {@hide}
3665     */
3666    @ViewDebug.ExportedProperty(formatToHexString = true)
3667    int mViewFlags;
3668
3669    static class TransformationInfo {
3670        /**
3671         * The transform matrix for the View. This transform is calculated internally
3672         * based on the translation, rotation, and scale properties.
3673         *
3674         * Do *not* use this variable directly; instead call getMatrix(), which will
3675         * load the value from the View's RenderNode.
3676         */
3677        private final Matrix mMatrix = new Matrix();
3678
3679        /**
3680         * The inverse transform matrix for the View. This transform is calculated
3681         * internally based on the translation, rotation, and scale properties.
3682         *
3683         * Do *not* use this variable directly; instead call getInverseMatrix(),
3684         * which will load the value from the View's RenderNode.
3685         */
3686        private Matrix mInverseMatrix;
3687
3688        /**
3689         * The opacity of the View. This is a value from 0 to 1, where 0 means
3690         * completely transparent and 1 means completely opaque.
3691         */
3692        @ViewDebug.ExportedProperty
3693        float mAlpha = 1f;
3694
3695        /**
3696         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3697         * property only used by transitions, which is composited with the other alpha
3698         * values to calculate the final visual alpha value.
3699         */
3700        float mTransitionAlpha = 1f;
3701    }
3702
3703    /** @hide */
3704    public TransformationInfo mTransformationInfo;
3705
3706    /**
3707     * Current clip bounds. to which all drawing of this view are constrained.
3708     */
3709    Rect mClipBounds = null;
3710
3711    private boolean mLastIsOpaque;
3712
3713    /**
3714     * The distance in pixels from the left edge of this view's parent
3715     * to the left edge of this view.
3716     * {@hide}
3717     */
3718    @ViewDebug.ExportedProperty(category = "layout")
3719    protected int mLeft;
3720    /**
3721     * The distance in pixels from the left edge of this view's parent
3722     * to the right edge of this view.
3723     * {@hide}
3724     */
3725    @ViewDebug.ExportedProperty(category = "layout")
3726    protected int mRight;
3727    /**
3728     * The distance in pixels from the top edge of this view's parent
3729     * to the top edge of this view.
3730     * {@hide}
3731     */
3732    @ViewDebug.ExportedProperty(category = "layout")
3733    protected int mTop;
3734    /**
3735     * The distance in pixels from the top edge of this view's parent
3736     * to the bottom edge of this view.
3737     * {@hide}
3738     */
3739    @ViewDebug.ExportedProperty(category = "layout")
3740    protected int mBottom;
3741
3742    /**
3743     * The offset, in pixels, by which the content of this view is scrolled
3744     * horizontally.
3745     * {@hide}
3746     */
3747    @ViewDebug.ExportedProperty(category = "scrolling")
3748    protected int mScrollX;
3749    /**
3750     * The offset, in pixels, by which the content of this view is scrolled
3751     * vertically.
3752     * {@hide}
3753     */
3754    @ViewDebug.ExportedProperty(category = "scrolling")
3755    protected int mScrollY;
3756
3757    /**
3758     * The left padding in pixels, that is the distance in pixels between the
3759     * left edge of this view and the left edge of its content.
3760     * {@hide}
3761     */
3762    @ViewDebug.ExportedProperty(category = "padding")
3763    protected int mPaddingLeft = 0;
3764    /**
3765     * The right padding in pixels, that is the distance in pixels between the
3766     * right edge of this view and the right edge of its content.
3767     * {@hide}
3768     */
3769    @ViewDebug.ExportedProperty(category = "padding")
3770    protected int mPaddingRight = 0;
3771    /**
3772     * The top padding in pixels, that is the distance in pixels between the
3773     * top edge of this view and the top edge of its content.
3774     * {@hide}
3775     */
3776    @ViewDebug.ExportedProperty(category = "padding")
3777    protected int mPaddingTop;
3778    /**
3779     * The bottom padding in pixels, that is the distance in pixels between the
3780     * bottom edge of this view and the bottom edge of its content.
3781     * {@hide}
3782     */
3783    @ViewDebug.ExportedProperty(category = "padding")
3784    protected int mPaddingBottom;
3785
3786    /**
3787     * The layout insets in pixels, that is the distance in pixels between the
3788     * visible edges of this view its bounds.
3789     */
3790    private Insets mLayoutInsets;
3791
3792    /**
3793     * Briefly describes the view and is primarily used for accessibility support.
3794     */
3795    private CharSequence mContentDescription;
3796
3797    /**
3798     * Specifies the id of a view for which this view serves as a label for
3799     * accessibility purposes.
3800     */
3801    private int mLabelForId = View.NO_ID;
3802
3803    /**
3804     * Predicate for matching labeled view id with its label for
3805     * accessibility purposes.
3806     */
3807    private MatchLabelForPredicate mMatchLabelForPredicate;
3808
3809    /**
3810     * Specifies a view before which this one is visited in accessibility traversal.
3811     */
3812    private int mAccessibilityTraversalBeforeId = NO_ID;
3813
3814    /**
3815     * Specifies a view after which this one is visited in accessibility traversal.
3816     */
3817    private int mAccessibilityTraversalAfterId = NO_ID;
3818
3819    /**
3820     * Predicate for matching a view by its id.
3821     */
3822    private MatchIdPredicate mMatchIdPredicate;
3823
3824    /**
3825     * Cache the paddingRight set by the user to append to the scrollbar's size.
3826     *
3827     * @hide
3828     */
3829    @ViewDebug.ExportedProperty(category = "padding")
3830    protected int mUserPaddingRight;
3831
3832    /**
3833     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3834     *
3835     * @hide
3836     */
3837    @ViewDebug.ExportedProperty(category = "padding")
3838    protected int mUserPaddingBottom;
3839
3840    /**
3841     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3842     *
3843     * @hide
3844     */
3845    @ViewDebug.ExportedProperty(category = "padding")
3846    protected int mUserPaddingLeft;
3847
3848    /**
3849     * Cache the paddingStart set by the user to append to the scrollbar's size.
3850     *
3851     */
3852    @ViewDebug.ExportedProperty(category = "padding")
3853    int mUserPaddingStart;
3854
3855    /**
3856     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3857     *
3858     */
3859    @ViewDebug.ExportedProperty(category = "padding")
3860    int mUserPaddingEnd;
3861
3862    /**
3863     * Cache initial left padding.
3864     *
3865     * @hide
3866     */
3867    int mUserPaddingLeftInitial;
3868
3869    /**
3870     * Cache initial right padding.
3871     *
3872     * @hide
3873     */
3874    int mUserPaddingRightInitial;
3875
3876    /**
3877     * Default undefined padding
3878     */
3879    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3880
3881    /**
3882     * Cache if a left padding has been defined
3883     */
3884    private boolean mLeftPaddingDefined = false;
3885
3886    /**
3887     * Cache if a right padding has been defined
3888     */
3889    private boolean mRightPaddingDefined = false;
3890
3891    /**
3892     * @hide
3893     */
3894    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3895    /**
3896     * @hide
3897     */
3898    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3899
3900    private LongSparseLongArray mMeasureCache;
3901
3902    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3903    private Drawable mBackground;
3904    private TintInfo mBackgroundTint;
3905
3906    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3907    private ForegroundInfo mForegroundInfo;
3908
3909    private Drawable mScrollIndicatorDrawable;
3910
3911    /**
3912     * RenderNode used for backgrounds.
3913     * <p>
3914     * When non-null and valid, this is expected to contain an up-to-date copy
3915     * of the background drawable. It is cleared on temporary detach, and reset
3916     * on cleanup.
3917     */
3918    private RenderNode mBackgroundRenderNode;
3919
3920    private int mBackgroundResource;
3921    private boolean mBackgroundSizeChanged;
3922
3923    private String mTransitionName;
3924
3925    static class TintInfo {
3926        ColorStateList mTintList;
3927        PorterDuff.Mode mTintMode;
3928        boolean mHasTintMode;
3929        boolean mHasTintList;
3930    }
3931
3932    private static class ForegroundInfo {
3933        private Drawable mDrawable;
3934        private TintInfo mTintInfo;
3935        private int mGravity = Gravity.FILL;
3936        private boolean mInsidePadding = true;
3937        private boolean mBoundsChanged = true;
3938        private final Rect mSelfBounds = new Rect();
3939        private final Rect mOverlayBounds = new Rect();
3940    }
3941
3942    static class ListenerInfo {
3943        /**
3944         * Listener used to dispatch focus change events.
3945         * This field should be made private, so it is hidden from the SDK.
3946         * {@hide}
3947         */
3948        protected OnFocusChangeListener mOnFocusChangeListener;
3949
3950        /**
3951         * Listeners for layout change events.
3952         */
3953        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3954
3955        protected OnScrollChangeListener mOnScrollChangeListener;
3956
3957        /**
3958         * Listeners for attach events.
3959         */
3960        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3961
3962        /**
3963         * Listener used to dispatch click events.
3964         * This field should be made private, so it is hidden from the SDK.
3965         * {@hide}
3966         */
3967        public OnClickListener mOnClickListener;
3968
3969        /**
3970         * Listener used to dispatch long click events.
3971         * This field should be made private, so it is hidden from the SDK.
3972         * {@hide}
3973         */
3974        protected OnLongClickListener mOnLongClickListener;
3975
3976        /**
3977         * Listener used to dispatch context click events. This field should be made private, so it
3978         * is hidden from the SDK.
3979         * {@hide}
3980         */
3981        protected OnContextClickListener mOnContextClickListener;
3982
3983        /**
3984         * Listener used to build the context menu.
3985         * This field should be made private, so it is hidden from the SDK.
3986         * {@hide}
3987         */
3988        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3989
3990        private OnKeyListener mOnKeyListener;
3991
3992        private OnTouchListener mOnTouchListener;
3993
3994        private OnHoverListener mOnHoverListener;
3995
3996        private OnGenericMotionListener mOnGenericMotionListener;
3997
3998        private OnDragListener mOnDragListener;
3999
4000        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4001
4002        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4003
4004        OnCapturedPointerListener mOnCapturedPointerListener;
4005    }
4006
4007    ListenerInfo mListenerInfo;
4008
4009    private static class TooltipInfo {
4010        /**
4011         * Text to be displayed in a tooltip popup.
4012         */
4013        @Nullable
4014        CharSequence mTooltipText;
4015
4016        /**
4017         * View-relative position of the tooltip anchor point.
4018         */
4019        int mAnchorX;
4020        int mAnchorY;
4021
4022        /**
4023         * The tooltip popup.
4024         */
4025        @Nullable
4026        TooltipPopup mTooltipPopup;
4027
4028        /**
4029         * Set to true if the tooltip was shown as a result of a long click.
4030         */
4031        boolean mTooltipFromLongClick;
4032
4033        /**
4034         * Keep these Runnables so that they can be used to reschedule.
4035         */
4036        Runnable mShowTooltipRunnable;
4037        Runnable mHideTooltipRunnable;
4038    }
4039
4040    TooltipInfo mTooltipInfo;
4041
4042    // Temporary values used to hold (x,y) coordinates when delegating from the
4043    // two-arg performLongClick() method to the legacy no-arg version.
4044    private float mLongClickX = Float.NaN;
4045    private float mLongClickY = Float.NaN;
4046
4047    /**
4048     * The application environment this view lives in.
4049     * This field should be made private, so it is hidden from the SDK.
4050     * {@hide}
4051     */
4052    @ViewDebug.ExportedProperty(deepExport = true)
4053    protected Context mContext;
4054
4055    private final Resources mResources;
4056
4057    private ScrollabilityCache mScrollCache;
4058
4059    private int[] mDrawableState = null;
4060
4061    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4062
4063    /**
4064     * Animator that automatically runs based on state changes.
4065     */
4066    private StateListAnimator mStateListAnimator;
4067
4068    /**
4069     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4070     * the user may specify which view to go to next.
4071     */
4072    private int mNextFocusLeftId = View.NO_ID;
4073
4074    /**
4075     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4076     * the user may specify which view to go to next.
4077     */
4078    private int mNextFocusRightId = View.NO_ID;
4079
4080    /**
4081     * When this view has focus and the next focus is {@link #FOCUS_UP},
4082     * the user may specify which view to go to next.
4083     */
4084    private int mNextFocusUpId = View.NO_ID;
4085
4086    /**
4087     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4088     * the user may specify which view to go to next.
4089     */
4090    private int mNextFocusDownId = View.NO_ID;
4091
4092    /**
4093     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4094     * the user may specify which view to go to next.
4095     */
4096    int mNextFocusForwardId = View.NO_ID;
4097
4098    /**
4099     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4100     *
4101     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4102     */
4103    int mNextClusterForwardId = View.NO_ID;
4104
4105    /**
4106     * Whether this View should use a default focus highlight when it gets focused but doesn't
4107     * have {@link android.R.attr#state_focused} defined in its background.
4108     */
4109    boolean mDefaultFocusHighlightEnabled = true;
4110
4111    private CheckForLongPress mPendingCheckForLongPress;
4112    private CheckForTap mPendingCheckForTap = null;
4113    private PerformClick mPerformClick;
4114    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4115
4116    private UnsetPressedState mUnsetPressedState;
4117
4118    /**
4119     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4120     * up event while a long press is invoked as soon as the long press duration is reached, so
4121     * a long press could be performed before the tap is checked, in which case the tap's action
4122     * should not be invoked.
4123     */
4124    private boolean mHasPerformedLongPress;
4125
4126    /**
4127     * Whether a context click button is currently pressed down. This is true when the stylus is
4128     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4129     * pressed. This is false once the button is released or if the stylus has been lifted.
4130     */
4131    private boolean mInContextButtonPress;
4132
4133    /**
4134     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4135     * true after a stylus button press has occured, when the next up event should not be recognized
4136     * as a tap.
4137     */
4138    private boolean mIgnoreNextUpEvent;
4139
4140    /**
4141     * The minimum height of the view. We'll try our best to have the height
4142     * of this view to at least this amount.
4143     */
4144    @ViewDebug.ExportedProperty(category = "measurement")
4145    private int mMinHeight;
4146
4147    /**
4148     * The minimum width of the view. We'll try our best to have the width
4149     * of this view to at least this amount.
4150     */
4151    @ViewDebug.ExportedProperty(category = "measurement")
4152    private int mMinWidth;
4153
4154    /**
4155     * The delegate to handle touch events that are physically in this view
4156     * but should be handled by another view.
4157     */
4158    private TouchDelegate mTouchDelegate = null;
4159
4160    /**
4161     * Solid color to use as a background when creating the drawing cache. Enables
4162     * the cache to use 16 bit bitmaps instead of 32 bit.
4163     */
4164    private int mDrawingCacheBackgroundColor = 0;
4165
4166    /**
4167     * Special tree observer used when mAttachInfo is null.
4168     */
4169    private ViewTreeObserver mFloatingTreeObserver;
4170
4171    /**
4172     * Cache the touch slop from the context that created the view.
4173     */
4174    private int mTouchSlop;
4175
4176    /**
4177     * Object that handles automatic animation of view properties.
4178     */
4179    private ViewPropertyAnimator mAnimator = null;
4180
4181    /**
4182     * List of registered FrameMetricsObservers.
4183     */
4184    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4185
4186    /**
4187     * Flag indicating that a drag can cross window boundaries.  When
4188     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4189     * with this flag set, all visible applications with targetSdkVersion >=
4190     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4191     * in the drag operation and receive the dragged content.
4192     *
4193     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4194     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4195     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4196     */
4197    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4198
4199    /**
4200     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4201     * request read access to the content URI(s) contained in the {@link ClipData} object.
4202     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4203     */
4204    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4205
4206    /**
4207     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4208     * request write access to the content URI(s) contained in the {@link ClipData} object.
4209     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4210     */
4211    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4212
4213    /**
4214     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4215     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4216     * reboots until explicitly revoked with
4217     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4218     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4219     */
4220    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4221            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4222
4223    /**
4224     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4225     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4226     * match against the original granted URI.
4227     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4228     */
4229    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4230            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4231
4232    /**
4233     * Flag indicating that the drag shadow will be opaque.  When
4234     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4235     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4236     */
4237    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4238
4239    /**
4240     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4241     */
4242    private float mVerticalScrollFactor;
4243
4244    /**
4245     * Position of the vertical scroll bar.
4246     */
4247    private int mVerticalScrollbarPosition;
4248
4249    /**
4250     * Position the scroll bar at the default position as determined by the system.
4251     */
4252    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4253
4254    /**
4255     * Position the scroll bar along the left edge.
4256     */
4257    public static final int SCROLLBAR_POSITION_LEFT = 1;
4258
4259    /**
4260     * Position the scroll bar along the right edge.
4261     */
4262    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4263
4264    /**
4265     * Indicates that the view does not have a layer.
4266     *
4267     * @see #getLayerType()
4268     * @see #setLayerType(int, android.graphics.Paint)
4269     * @see #LAYER_TYPE_SOFTWARE
4270     * @see #LAYER_TYPE_HARDWARE
4271     */
4272    public static final int LAYER_TYPE_NONE = 0;
4273
4274    /**
4275     * <p>Indicates that the view has a software layer. A software layer is backed
4276     * by a bitmap and causes the view to be rendered using Android's software
4277     * rendering pipeline, even if hardware acceleration is enabled.</p>
4278     *
4279     * <p>Software layers have various usages:</p>
4280     * <p>When the application is not using hardware acceleration, a software layer
4281     * is useful to apply a specific color filter and/or blending mode and/or
4282     * translucency to a view and all its children.</p>
4283     * <p>When the application is using hardware acceleration, a software layer
4284     * is useful to render drawing primitives not supported by the hardware
4285     * accelerated pipeline. It can also be used to cache a complex view tree
4286     * into a texture and reduce the complexity of drawing operations. For instance,
4287     * when animating a complex view tree with a translation, a software layer can
4288     * be used to render the view tree only once.</p>
4289     * <p>Software layers should be avoided when the affected view tree updates
4290     * often. Every update will require to re-render the software layer, which can
4291     * potentially be slow (particularly when hardware acceleration is turned on
4292     * since the layer will have to be uploaded into a hardware texture after every
4293     * update.)</p>
4294     *
4295     * @see #getLayerType()
4296     * @see #setLayerType(int, android.graphics.Paint)
4297     * @see #LAYER_TYPE_NONE
4298     * @see #LAYER_TYPE_HARDWARE
4299     */
4300    public static final int LAYER_TYPE_SOFTWARE = 1;
4301
4302    /**
4303     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4304     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4305     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4306     * rendering pipeline, but only if hardware acceleration is turned on for the
4307     * view hierarchy. When hardware acceleration is turned off, hardware layers
4308     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4309     *
4310     * <p>A hardware layer is useful to apply a specific color filter and/or
4311     * blending mode and/or translucency to a view and all its children.</p>
4312     * <p>A hardware layer can be used to cache a complex view tree into a
4313     * texture and reduce the complexity of drawing operations. For instance,
4314     * when animating a complex view tree with a translation, a hardware layer can
4315     * be used to render the view tree only once.</p>
4316     * <p>A hardware layer can also be used to increase the rendering quality when
4317     * rotation transformations are applied on a view. It can also be used to
4318     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4319     *
4320     * @see #getLayerType()
4321     * @see #setLayerType(int, android.graphics.Paint)
4322     * @see #LAYER_TYPE_NONE
4323     * @see #LAYER_TYPE_SOFTWARE
4324     */
4325    public static final int LAYER_TYPE_HARDWARE = 2;
4326
4327    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4328            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4329            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4330            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4331    })
4332    int mLayerType = LAYER_TYPE_NONE;
4333    Paint mLayerPaint;
4334
4335    /**
4336     * Set to true when drawing cache is enabled and cannot be created.
4337     *
4338     * @hide
4339     */
4340    public boolean mCachingFailed;
4341    private Bitmap mDrawingCache;
4342    private Bitmap mUnscaledDrawingCache;
4343
4344    /**
4345     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4346     * <p>
4347     * When non-null and valid, this is expected to contain an up-to-date copy
4348     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4349     * cleanup.
4350     */
4351    final RenderNode mRenderNode;
4352
4353    /**
4354     * Set to true when the view is sending hover accessibility events because it
4355     * is the innermost hovered view.
4356     */
4357    private boolean mSendingHoverAccessibilityEvents;
4358
4359    /**
4360     * Delegate for injecting accessibility functionality.
4361     */
4362    AccessibilityDelegate mAccessibilityDelegate;
4363
4364    /**
4365     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4366     * and add/remove objects to/from the overlay directly through the Overlay methods.
4367     */
4368    ViewOverlay mOverlay;
4369
4370    /**
4371     * The currently active parent view for receiving delegated nested scrolling events.
4372     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4373     * by {@link #stopNestedScroll()} at the same point where we clear
4374     * requestDisallowInterceptTouchEvent.
4375     */
4376    private ViewParent mNestedScrollingParent;
4377
4378    /**
4379     * Consistency verifier for debugging purposes.
4380     * @hide
4381     */
4382    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4383            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4384                    new InputEventConsistencyVerifier(this, 0) : null;
4385
4386    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4387
4388    private int[] mTempNestedScrollConsumed;
4389
4390    /**
4391     * An overlay is going to draw this View instead of being drawn as part of this
4392     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4393     * when this view is invalidated.
4394     */
4395    GhostView mGhostView;
4396
4397    /**
4398     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4399     * @hide
4400     */
4401    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4402    public String[] mAttributes;
4403
4404    /**
4405     * Maps a Resource id to its name.
4406     */
4407    private static SparseArray<String> mAttributeMap;
4408
4409    /**
4410     * Queue of pending runnables. Used to postpone calls to post() until this
4411     * view is attached and has a handler.
4412     */
4413    private HandlerActionQueue mRunQueue;
4414
4415    /**
4416     * The pointer icon when the mouse hovers on this view. The default is null.
4417     */
4418    private PointerIcon mPointerIcon;
4419
4420    /**
4421     * @hide
4422     */
4423    String mStartActivityRequestWho;
4424
4425    @Nullable
4426    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4427
4428    /**
4429     * Simple constructor to use when creating a view from code.
4430     *
4431     * @param context The Context the view is running in, through which it can
4432     *        access the current theme, resources, etc.
4433     */
4434    public View(Context context) {
4435        mContext = context;
4436        mResources = context != null ? context.getResources() : null;
4437        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4438        // Set some flags defaults
4439        mPrivateFlags2 =
4440                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4441                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4442                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4443                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4444                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4445                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4446        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4447        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4448        mUserPaddingStart = UNDEFINED_PADDING;
4449        mUserPaddingEnd = UNDEFINED_PADDING;
4450        mRenderNode = RenderNode.create(getClass().getName(), this);
4451
4452        if (!sCompatibilityDone && context != null) {
4453            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4454
4455            // Older apps may need this compatibility hack for measurement.
4456            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4457
4458            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4459            // of whether a layout was requested on that View.
4460            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4461
4462            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4463
4464            // In M and newer, our widgets can pass a "hint" value in the size
4465            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4466            // know what the expected parent size is going to be, so e.g. list items can size
4467            // themselves at 1/3 the size of their container. It breaks older apps though,
4468            // specifically apps that use some popular open source libraries.
4469            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4470
4471            // Old versions of the platform would give different results from
4472            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4473            // modes, so we always need to run an additional EXACTLY pass.
4474            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4475
4476            // Prior to N, layout params could change without requiring a
4477            // subsequent call to setLayoutParams() and they would usually
4478            // work. Partial layout breaks this assumption.
4479            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4480
4481            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4482            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4483            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4484
4485            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4486            // in apps so we target check it to avoid breaking existing apps.
4487            sPreserveMarginParamsInLayoutParamConversion =
4488                    targetSdkVersion >= Build.VERSION_CODES.N;
4489
4490            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4491
4492            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4493
4494            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4495
4496            sCompatibilityDone = true;
4497        }
4498    }
4499
4500    /**
4501     * Constructor that is called when inflating a view from XML. This is called
4502     * when a view is being constructed from an XML file, supplying attributes
4503     * that were specified in the XML file. This version uses a default style of
4504     * 0, so the only attribute values applied are those in the Context's Theme
4505     * and the given AttributeSet.
4506     *
4507     * <p>
4508     * The method onFinishInflate() will be called after all children have been
4509     * added.
4510     *
4511     * @param context The Context the view is running in, through which it can
4512     *        access the current theme, resources, etc.
4513     * @param attrs The attributes of the XML tag that is inflating the view.
4514     * @see #View(Context, AttributeSet, int)
4515     */
4516    public View(Context context, @Nullable AttributeSet attrs) {
4517        this(context, attrs, 0);
4518    }
4519
4520    /**
4521     * Perform inflation from XML and apply a class-specific base style from a
4522     * theme attribute. This constructor of View allows subclasses to use their
4523     * own base style when they are inflating. For example, a Button class's
4524     * constructor would call this version of the super class constructor and
4525     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4526     * allows the theme's button style to modify all of the base view attributes
4527     * (in particular its background) as well as the Button class's attributes.
4528     *
4529     * @param context The Context the view is running in, through which it can
4530     *        access the current theme, resources, etc.
4531     * @param attrs The attributes of the XML tag that is inflating the view.
4532     * @param defStyleAttr An attribute in the current theme that contains a
4533     *        reference to a style resource that supplies default values for
4534     *        the view. Can be 0 to not look for defaults.
4535     * @see #View(Context, AttributeSet)
4536     */
4537    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4538        this(context, attrs, defStyleAttr, 0);
4539    }
4540
4541    /**
4542     * Perform inflation from XML and apply a class-specific base style from a
4543     * theme attribute or style resource. This constructor of View allows
4544     * subclasses to use their own base style when they are inflating.
4545     * <p>
4546     * When determining the final value of a particular attribute, there are
4547     * four inputs that come into play:
4548     * <ol>
4549     * <li>Any attribute values in the given AttributeSet.
4550     * <li>The style resource specified in the AttributeSet (named "style").
4551     * <li>The default style specified by <var>defStyleAttr</var>.
4552     * <li>The default style specified by <var>defStyleRes</var>.
4553     * <li>The base values in this theme.
4554     * </ol>
4555     * <p>
4556     * Each of these inputs is considered in-order, with the first listed taking
4557     * precedence over the following ones. In other words, if in the
4558     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4559     * , then the button's text will <em>always</em> be black, regardless of
4560     * what is specified in any of the styles.
4561     *
4562     * @param context The Context the view is running in, through which it can
4563     *        access the current theme, resources, etc.
4564     * @param attrs The attributes of the XML tag that is inflating the view.
4565     * @param defStyleAttr An attribute in the current theme that contains a
4566     *        reference to a style resource that supplies default values for
4567     *        the view. Can be 0 to not look for defaults.
4568     * @param defStyleRes A resource identifier of a style resource that
4569     *        supplies default values for the view, used only if
4570     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4571     *        to not look for defaults.
4572     * @see #View(Context, AttributeSet, int)
4573     */
4574    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4575        this(context);
4576
4577        final TypedArray a = context.obtainStyledAttributes(
4578                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4579
4580        if (mDebugViewAttributes) {
4581            saveAttributeData(attrs, a);
4582        }
4583
4584        Drawable background = null;
4585
4586        int leftPadding = -1;
4587        int topPadding = -1;
4588        int rightPadding = -1;
4589        int bottomPadding = -1;
4590        int startPadding = UNDEFINED_PADDING;
4591        int endPadding = UNDEFINED_PADDING;
4592
4593        int padding = -1;
4594        int paddingHorizontal = -1;
4595        int paddingVertical = -1;
4596
4597        int viewFlagValues = 0;
4598        int viewFlagMasks = 0;
4599
4600        boolean setScrollContainer = false;
4601
4602        int x = 0;
4603        int y = 0;
4604
4605        float tx = 0;
4606        float ty = 0;
4607        float tz = 0;
4608        float elevation = 0;
4609        float rotation = 0;
4610        float rotationX = 0;
4611        float rotationY = 0;
4612        float sx = 1f;
4613        float sy = 1f;
4614        boolean transformSet = false;
4615
4616        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4617        int overScrollMode = mOverScrollMode;
4618        boolean initializeScrollbars = false;
4619        boolean initializeScrollIndicators = false;
4620
4621        boolean startPaddingDefined = false;
4622        boolean endPaddingDefined = false;
4623        boolean leftPaddingDefined = false;
4624        boolean rightPaddingDefined = false;
4625
4626        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4627
4628        // Set default values.
4629        viewFlagValues |= FOCUSABLE_AUTO;
4630        viewFlagMasks |= FOCUSABLE_AUTO;
4631
4632        final int N = a.getIndexCount();
4633        for (int i = 0; i < N; i++) {
4634            int attr = a.getIndex(i);
4635            switch (attr) {
4636                case com.android.internal.R.styleable.View_background:
4637                    background = a.getDrawable(attr);
4638                    break;
4639                case com.android.internal.R.styleable.View_padding:
4640                    padding = a.getDimensionPixelSize(attr, -1);
4641                    mUserPaddingLeftInitial = padding;
4642                    mUserPaddingRightInitial = padding;
4643                    leftPaddingDefined = true;
4644                    rightPaddingDefined = true;
4645                    break;
4646                case com.android.internal.R.styleable.View_paddingHorizontal:
4647                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4648                    mUserPaddingLeftInitial = paddingHorizontal;
4649                    mUserPaddingRightInitial = paddingHorizontal;
4650                    leftPaddingDefined = true;
4651                    rightPaddingDefined = true;
4652                    break;
4653                case com.android.internal.R.styleable.View_paddingVertical:
4654                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4655                    break;
4656                 case com.android.internal.R.styleable.View_paddingLeft:
4657                    leftPadding = a.getDimensionPixelSize(attr, -1);
4658                    mUserPaddingLeftInitial = leftPadding;
4659                    leftPaddingDefined = true;
4660                    break;
4661                case com.android.internal.R.styleable.View_paddingTop:
4662                    topPadding = a.getDimensionPixelSize(attr, -1);
4663                    break;
4664                case com.android.internal.R.styleable.View_paddingRight:
4665                    rightPadding = a.getDimensionPixelSize(attr, -1);
4666                    mUserPaddingRightInitial = rightPadding;
4667                    rightPaddingDefined = true;
4668                    break;
4669                case com.android.internal.R.styleable.View_paddingBottom:
4670                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4671                    break;
4672                case com.android.internal.R.styleable.View_paddingStart:
4673                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4674                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4675                    break;
4676                case com.android.internal.R.styleable.View_paddingEnd:
4677                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4678                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4679                    break;
4680                case com.android.internal.R.styleable.View_scrollX:
4681                    x = a.getDimensionPixelOffset(attr, 0);
4682                    break;
4683                case com.android.internal.R.styleable.View_scrollY:
4684                    y = a.getDimensionPixelOffset(attr, 0);
4685                    break;
4686                case com.android.internal.R.styleable.View_alpha:
4687                    setAlpha(a.getFloat(attr, 1f));
4688                    break;
4689                case com.android.internal.R.styleable.View_transformPivotX:
4690                    setPivotX(a.getDimension(attr, 0));
4691                    break;
4692                case com.android.internal.R.styleable.View_transformPivotY:
4693                    setPivotY(a.getDimension(attr, 0));
4694                    break;
4695                case com.android.internal.R.styleable.View_translationX:
4696                    tx = a.getDimension(attr, 0);
4697                    transformSet = true;
4698                    break;
4699                case com.android.internal.R.styleable.View_translationY:
4700                    ty = a.getDimension(attr, 0);
4701                    transformSet = true;
4702                    break;
4703                case com.android.internal.R.styleable.View_translationZ:
4704                    tz = a.getDimension(attr, 0);
4705                    transformSet = true;
4706                    break;
4707                case com.android.internal.R.styleable.View_elevation:
4708                    elevation = a.getDimension(attr, 0);
4709                    transformSet = true;
4710                    break;
4711                case com.android.internal.R.styleable.View_rotation:
4712                    rotation = a.getFloat(attr, 0);
4713                    transformSet = true;
4714                    break;
4715                case com.android.internal.R.styleable.View_rotationX:
4716                    rotationX = a.getFloat(attr, 0);
4717                    transformSet = true;
4718                    break;
4719                case com.android.internal.R.styleable.View_rotationY:
4720                    rotationY = a.getFloat(attr, 0);
4721                    transformSet = true;
4722                    break;
4723                case com.android.internal.R.styleable.View_scaleX:
4724                    sx = a.getFloat(attr, 1f);
4725                    transformSet = true;
4726                    break;
4727                case com.android.internal.R.styleable.View_scaleY:
4728                    sy = a.getFloat(attr, 1f);
4729                    transformSet = true;
4730                    break;
4731                case com.android.internal.R.styleable.View_id:
4732                    mID = a.getResourceId(attr, NO_ID);
4733                    break;
4734                case com.android.internal.R.styleable.View_tag:
4735                    mTag = a.getText(attr);
4736                    break;
4737                case com.android.internal.R.styleable.View_fitsSystemWindows:
4738                    if (a.getBoolean(attr, false)) {
4739                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4740                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4741                    }
4742                    break;
4743                case com.android.internal.R.styleable.View_focusable:
4744                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4745                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4746                        viewFlagMasks |= FOCUSABLE_MASK;
4747                    }
4748                    break;
4749                case com.android.internal.R.styleable.View_focusableInTouchMode:
4750                    if (a.getBoolean(attr, false)) {
4751                        // unset auto focus since focusableInTouchMode implies explicit focusable
4752                        viewFlagValues &= ~FOCUSABLE_AUTO;
4753                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4754                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4755                    }
4756                    break;
4757                case com.android.internal.R.styleable.View_clickable:
4758                    if (a.getBoolean(attr, false)) {
4759                        viewFlagValues |= CLICKABLE;
4760                        viewFlagMasks |= CLICKABLE;
4761                    }
4762                    break;
4763                case com.android.internal.R.styleable.View_longClickable:
4764                    if (a.getBoolean(attr, false)) {
4765                        viewFlagValues |= LONG_CLICKABLE;
4766                        viewFlagMasks |= LONG_CLICKABLE;
4767                    }
4768                    break;
4769                case com.android.internal.R.styleable.View_contextClickable:
4770                    if (a.getBoolean(attr, false)) {
4771                        viewFlagValues |= CONTEXT_CLICKABLE;
4772                        viewFlagMasks |= CONTEXT_CLICKABLE;
4773                    }
4774                    break;
4775                case com.android.internal.R.styleable.View_saveEnabled:
4776                    if (!a.getBoolean(attr, true)) {
4777                        viewFlagValues |= SAVE_DISABLED;
4778                        viewFlagMasks |= SAVE_DISABLED_MASK;
4779                    }
4780                    break;
4781                case com.android.internal.R.styleable.View_duplicateParentState:
4782                    if (a.getBoolean(attr, false)) {
4783                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4784                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4785                    }
4786                    break;
4787                case com.android.internal.R.styleable.View_visibility:
4788                    final int visibility = a.getInt(attr, 0);
4789                    if (visibility != 0) {
4790                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4791                        viewFlagMasks |= VISIBILITY_MASK;
4792                    }
4793                    break;
4794                case com.android.internal.R.styleable.View_layoutDirection:
4795                    // Clear any layout direction flags (included resolved bits) already set
4796                    mPrivateFlags2 &=
4797                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4798                    // Set the layout direction flags depending on the value of the attribute
4799                    final int layoutDirection = a.getInt(attr, -1);
4800                    final int value = (layoutDirection != -1) ?
4801                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4802                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4803                    break;
4804                case com.android.internal.R.styleable.View_drawingCacheQuality:
4805                    final int cacheQuality = a.getInt(attr, 0);
4806                    if (cacheQuality != 0) {
4807                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4808                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4809                    }
4810                    break;
4811                case com.android.internal.R.styleable.View_contentDescription:
4812                    setContentDescription(a.getString(attr));
4813                    break;
4814                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4815                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4816                    break;
4817                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4818                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4819                    break;
4820                case com.android.internal.R.styleable.View_labelFor:
4821                    setLabelFor(a.getResourceId(attr, NO_ID));
4822                    break;
4823                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4824                    if (!a.getBoolean(attr, true)) {
4825                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4826                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4827                    }
4828                    break;
4829                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4830                    if (!a.getBoolean(attr, true)) {
4831                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4832                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4833                    }
4834                    break;
4835                case R.styleable.View_scrollbars:
4836                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4837                    if (scrollbars != SCROLLBARS_NONE) {
4838                        viewFlagValues |= scrollbars;
4839                        viewFlagMasks |= SCROLLBARS_MASK;
4840                        initializeScrollbars = true;
4841                    }
4842                    break;
4843                //noinspection deprecation
4844                case R.styleable.View_fadingEdge:
4845                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4846                        // Ignore the attribute starting with ICS
4847                        break;
4848                    }
4849                    // With builds < ICS, fall through and apply fading edges
4850                case R.styleable.View_requiresFadingEdge:
4851                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4852                    if (fadingEdge != FADING_EDGE_NONE) {
4853                        viewFlagValues |= fadingEdge;
4854                        viewFlagMasks |= FADING_EDGE_MASK;
4855                        initializeFadingEdgeInternal(a);
4856                    }
4857                    break;
4858                case R.styleable.View_scrollbarStyle:
4859                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4860                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4861                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4862                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4863                    }
4864                    break;
4865                case R.styleable.View_isScrollContainer:
4866                    setScrollContainer = true;
4867                    if (a.getBoolean(attr, false)) {
4868                        setScrollContainer(true);
4869                    }
4870                    break;
4871                case com.android.internal.R.styleable.View_keepScreenOn:
4872                    if (a.getBoolean(attr, false)) {
4873                        viewFlagValues |= KEEP_SCREEN_ON;
4874                        viewFlagMasks |= KEEP_SCREEN_ON;
4875                    }
4876                    break;
4877                case R.styleable.View_filterTouchesWhenObscured:
4878                    if (a.getBoolean(attr, false)) {
4879                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4880                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4881                    }
4882                    break;
4883                case R.styleable.View_nextFocusLeft:
4884                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4885                    break;
4886                case R.styleable.View_nextFocusRight:
4887                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4888                    break;
4889                case R.styleable.View_nextFocusUp:
4890                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4891                    break;
4892                case R.styleable.View_nextFocusDown:
4893                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4894                    break;
4895                case R.styleable.View_nextFocusForward:
4896                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4897                    break;
4898                case R.styleable.View_nextClusterForward:
4899                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4900                    break;
4901                case R.styleable.View_minWidth:
4902                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4903                    break;
4904                case R.styleable.View_minHeight:
4905                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4906                    break;
4907                case R.styleable.View_onClick:
4908                    if (context.isRestricted()) {
4909                        throw new IllegalStateException("The android:onClick attribute cannot "
4910                                + "be used within a restricted context");
4911                    }
4912
4913                    final String handlerName = a.getString(attr);
4914                    if (handlerName != null) {
4915                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4916                    }
4917                    break;
4918                case R.styleable.View_overScrollMode:
4919                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4920                    break;
4921                case R.styleable.View_verticalScrollbarPosition:
4922                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4923                    break;
4924                case R.styleable.View_layerType:
4925                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4926                    break;
4927                case R.styleable.View_textDirection:
4928                    // Clear any text direction flag already set
4929                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4930                    // Set the text direction flags depending on the value of the attribute
4931                    final int textDirection = a.getInt(attr, -1);
4932                    if (textDirection != -1) {
4933                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4934                    }
4935                    break;
4936                case R.styleable.View_textAlignment:
4937                    // Clear any text alignment flag already set
4938                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4939                    // Set the text alignment flag depending on the value of the attribute
4940                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4941                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4942                    break;
4943                case R.styleable.View_importantForAccessibility:
4944                    setImportantForAccessibility(a.getInt(attr,
4945                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4946                    break;
4947                case R.styleable.View_accessibilityLiveRegion:
4948                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4949                    break;
4950                case R.styleable.View_transitionName:
4951                    setTransitionName(a.getString(attr));
4952                    break;
4953                case R.styleable.View_nestedScrollingEnabled:
4954                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4955                    break;
4956                case R.styleable.View_stateListAnimator:
4957                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4958                            a.getResourceId(attr, 0)));
4959                    break;
4960                case R.styleable.View_backgroundTint:
4961                    // This will get applied later during setBackground().
4962                    if (mBackgroundTint == null) {
4963                        mBackgroundTint = new TintInfo();
4964                    }
4965                    mBackgroundTint.mTintList = a.getColorStateList(
4966                            R.styleable.View_backgroundTint);
4967                    mBackgroundTint.mHasTintList = true;
4968                    break;
4969                case R.styleable.View_backgroundTintMode:
4970                    // This will get applied later during setBackground().
4971                    if (mBackgroundTint == null) {
4972                        mBackgroundTint = new TintInfo();
4973                    }
4974                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4975                            R.styleable.View_backgroundTintMode, -1), null);
4976                    mBackgroundTint.mHasTintMode = true;
4977                    break;
4978                case R.styleable.View_outlineProvider:
4979                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4980                            PROVIDER_BACKGROUND));
4981                    break;
4982                case R.styleable.View_foreground:
4983                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4984                        setForeground(a.getDrawable(attr));
4985                    }
4986                    break;
4987                case R.styleable.View_foregroundGravity:
4988                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4989                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4990                    }
4991                    break;
4992                case R.styleable.View_foregroundTintMode:
4993                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4994                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4995                    }
4996                    break;
4997                case R.styleable.View_foregroundTint:
4998                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4999                        setForegroundTintList(a.getColorStateList(attr));
5000                    }
5001                    break;
5002                case R.styleable.View_foregroundInsidePadding:
5003                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5004                        if (mForegroundInfo == null) {
5005                            mForegroundInfo = new ForegroundInfo();
5006                        }
5007                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5008                                mForegroundInfo.mInsidePadding);
5009                    }
5010                    break;
5011                case R.styleable.View_scrollIndicators:
5012                    final int scrollIndicators =
5013                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5014                                    & SCROLL_INDICATORS_PFLAG3_MASK;
5015                    if (scrollIndicators != 0) {
5016                        mPrivateFlags3 |= scrollIndicators;
5017                        initializeScrollIndicators = true;
5018                    }
5019                    break;
5020                case R.styleable.View_pointerIcon:
5021                    final int resourceId = a.getResourceId(attr, 0);
5022                    if (resourceId != 0) {
5023                        setPointerIcon(PointerIcon.load(
5024                                context.getResources(), resourceId));
5025                    } else {
5026                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5027                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5028                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5029                        }
5030                    }
5031                    break;
5032                case R.styleable.View_forceHasOverlappingRendering:
5033                    if (a.peekValue(attr) != null) {
5034                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5035                    }
5036                    break;
5037                case R.styleable.View_tooltipText:
5038                    setTooltipText(a.getText(attr));
5039                    break;
5040                case R.styleable.View_keyboardNavigationCluster:
5041                    if (a.peekValue(attr) != null) {
5042                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5043                    }
5044                    break;
5045                case R.styleable.View_focusedByDefault:
5046                    if (a.peekValue(attr) != null) {
5047                        setFocusedByDefault(a.getBoolean(attr, true));
5048                    }
5049                    break;
5050                case R.styleable.View_autofillMode:
5051                    if (a.peekValue(attr) != null) {
5052                        setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
5053                    }
5054                    break;
5055                case R.styleable.View_autofillHints:
5056                    if (a.peekValue(attr) != null) {
5057                        CharSequence[] rawHints = null;
5058                        String rawString = null;
5059
5060                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5061                            int resId = a.getResourceId(attr, 0);
5062
5063                            try {
5064                                rawHints = a.getTextArray(attr);
5065                            } catch (Resources.NotFoundException e) {
5066                                rawString = getResources().getString(resId);
5067                            }
5068                        } else {
5069                            rawString = a.getString(attr);
5070                        }
5071
5072                        if (rawHints == null) {
5073                            if (rawString == null) {
5074                                throw new IllegalArgumentException(
5075                                        "Could not resolve autofillHints");
5076                            } else {
5077                                rawHints = rawString.split(",");
5078                            }
5079                        }
5080
5081                        String[] hints = new String[rawHints.length];
5082
5083                        int numHints = rawHints.length;
5084                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5085                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5086                        }
5087                        setAutofillHints(hints);
5088                    }
5089                    break;
5090                case R.styleable.View_importantForAutofill:
5091                    if (a.peekValue(attr) != null) {
5092                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5093                    }
5094                    break;
5095                case R.styleable.View_defaultFocusHighlightEnabled:
5096                    if (a.peekValue(attr) != null) {
5097                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5098                    }
5099                    break;
5100            }
5101        }
5102
5103        setOverScrollMode(overScrollMode);
5104
5105        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5106        // the resolved layout direction). Those cached values will be used later during padding
5107        // resolution.
5108        mUserPaddingStart = startPadding;
5109        mUserPaddingEnd = endPadding;
5110
5111        if (background != null) {
5112            setBackground(background);
5113        }
5114
5115        // setBackground above will record that padding is currently provided by the background.
5116        // If we have padding specified via xml, record that here instead and use it.
5117        mLeftPaddingDefined = leftPaddingDefined;
5118        mRightPaddingDefined = rightPaddingDefined;
5119
5120        if (padding >= 0) {
5121            leftPadding = padding;
5122            topPadding = padding;
5123            rightPadding = padding;
5124            bottomPadding = padding;
5125            mUserPaddingLeftInitial = padding;
5126            mUserPaddingRightInitial = padding;
5127        } else {
5128            if (paddingHorizontal >= 0) {
5129                leftPadding = paddingHorizontal;
5130                rightPadding = paddingHorizontal;
5131                mUserPaddingLeftInitial = paddingHorizontal;
5132                mUserPaddingRightInitial = paddingHorizontal;
5133            }
5134            if (paddingVertical >= 0) {
5135                topPadding = paddingVertical;
5136                bottomPadding = paddingVertical;
5137            }
5138        }
5139
5140        if (isRtlCompatibilityMode()) {
5141            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5142            // left / right padding are used if defined (meaning here nothing to do). If they are not
5143            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5144            // start / end and resolve them as left / right (layout direction is not taken into account).
5145            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5146            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5147            // defined.
5148            if (!mLeftPaddingDefined && startPaddingDefined) {
5149                leftPadding = startPadding;
5150            }
5151            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5152            if (!mRightPaddingDefined && endPaddingDefined) {
5153                rightPadding = endPadding;
5154            }
5155            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5156        } else {
5157            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5158            // values defined. Otherwise, left /right values are used.
5159            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5160            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5161            // defined.
5162            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5163
5164            if (mLeftPaddingDefined && !hasRelativePadding) {
5165                mUserPaddingLeftInitial = leftPadding;
5166            }
5167            if (mRightPaddingDefined && !hasRelativePadding) {
5168                mUserPaddingRightInitial = rightPadding;
5169            }
5170        }
5171
5172        internalSetPadding(
5173                mUserPaddingLeftInitial,
5174                topPadding >= 0 ? topPadding : mPaddingTop,
5175                mUserPaddingRightInitial,
5176                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5177
5178        if (viewFlagMasks != 0) {
5179            setFlags(viewFlagValues, viewFlagMasks);
5180        }
5181
5182        if (initializeScrollbars) {
5183            initializeScrollbarsInternal(a);
5184        }
5185
5186        if (initializeScrollIndicators) {
5187            initializeScrollIndicatorsInternal();
5188        }
5189
5190        a.recycle();
5191
5192        // Needs to be called after mViewFlags is set
5193        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5194            recomputePadding();
5195        }
5196
5197        if (x != 0 || y != 0) {
5198            scrollTo(x, y);
5199        }
5200
5201        if (transformSet) {
5202            setTranslationX(tx);
5203            setTranslationY(ty);
5204            setTranslationZ(tz);
5205            setElevation(elevation);
5206            setRotation(rotation);
5207            setRotationX(rotationX);
5208            setRotationY(rotationY);
5209            setScaleX(sx);
5210            setScaleY(sy);
5211        }
5212
5213        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5214            setScrollContainer(true);
5215        }
5216
5217        computeOpaqueFlags();
5218    }
5219
5220    /**
5221     * An implementation of OnClickListener that attempts to lazily load a
5222     * named click handling method from a parent or ancestor context.
5223     */
5224    private static class DeclaredOnClickListener implements OnClickListener {
5225        private final View mHostView;
5226        private final String mMethodName;
5227
5228        private Method mResolvedMethod;
5229        private Context mResolvedContext;
5230
5231        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5232            mHostView = hostView;
5233            mMethodName = methodName;
5234        }
5235
5236        @Override
5237        public void onClick(@NonNull View v) {
5238            if (mResolvedMethod == null) {
5239                resolveMethod(mHostView.getContext(), mMethodName);
5240            }
5241
5242            try {
5243                mResolvedMethod.invoke(mResolvedContext, v);
5244            } catch (IllegalAccessException e) {
5245                throw new IllegalStateException(
5246                        "Could not execute non-public method for android:onClick", e);
5247            } catch (InvocationTargetException e) {
5248                throw new IllegalStateException(
5249                        "Could not execute method for android:onClick", e);
5250            }
5251        }
5252
5253        @NonNull
5254        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5255            while (context != null) {
5256                try {
5257                    if (!context.isRestricted()) {
5258                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5259                        if (method != null) {
5260                            mResolvedMethod = method;
5261                            mResolvedContext = context;
5262                            return;
5263                        }
5264                    }
5265                } catch (NoSuchMethodException e) {
5266                    // Failed to find method, keep searching up the hierarchy.
5267                }
5268
5269                if (context instanceof ContextWrapper) {
5270                    context = ((ContextWrapper) context).getBaseContext();
5271                } else {
5272                    // Can't search up the hierarchy, null out and fail.
5273                    context = null;
5274                }
5275            }
5276
5277            final int id = mHostView.getId();
5278            final String idText = id == NO_ID ? "" : " with id '"
5279                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5280            throw new IllegalStateException("Could not find method " + mMethodName
5281                    + "(View) in a parent or ancestor Context for android:onClick "
5282                    + "attribute defined on view " + mHostView.getClass() + idText);
5283        }
5284    }
5285
5286    /**
5287     * Non-public constructor for use in testing
5288     */
5289    View() {
5290        mResources = null;
5291        mRenderNode = RenderNode.create(getClass().getName(), this);
5292    }
5293
5294    final boolean debugDraw() {
5295        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5296    }
5297
5298    private static SparseArray<String> getAttributeMap() {
5299        if (mAttributeMap == null) {
5300            mAttributeMap = new SparseArray<>();
5301        }
5302        return mAttributeMap;
5303    }
5304
5305    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5306        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5307        final int indexCount = t.getIndexCount();
5308        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5309
5310        int i = 0;
5311
5312        // Store raw XML attributes.
5313        for (int j = 0; j < attrsCount; ++j) {
5314            attributes[i] = attrs.getAttributeName(j);
5315            attributes[i + 1] = attrs.getAttributeValue(j);
5316            i += 2;
5317        }
5318
5319        // Store resolved styleable attributes.
5320        final Resources res = t.getResources();
5321        final SparseArray<String> attributeMap = getAttributeMap();
5322        for (int j = 0; j < indexCount; ++j) {
5323            final int index = t.getIndex(j);
5324            if (!t.hasValueOrEmpty(index)) {
5325                // Value is undefined. Skip it.
5326                continue;
5327            }
5328
5329            final int resourceId = t.getResourceId(index, 0);
5330            if (resourceId == 0) {
5331                // Value is not a reference. Skip it.
5332                continue;
5333            }
5334
5335            String resourceName = attributeMap.get(resourceId);
5336            if (resourceName == null) {
5337                try {
5338                    resourceName = res.getResourceName(resourceId);
5339                } catch (Resources.NotFoundException e) {
5340                    resourceName = "0x" + Integer.toHexString(resourceId);
5341                }
5342                attributeMap.put(resourceId, resourceName);
5343            }
5344
5345            attributes[i] = resourceName;
5346            attributes[i + 1] = t.getString(index);
5347            i += 2;
5348        }
5349
5350        // Trim to fit contents.
5351        final String[] trimmed = new String[i];
5352        System.arraycopy(attributes, 0, trimmed, 0, i);
5353        mAttributes = trimmed;
5354    }
5355
5356    public String toString() {
5357        StringBuilder out = new StringBuilder(128);
5358        out.append(getClass().getName());
5359        out.append('{');
5360        out.append(Integer.toHexString(System.identityHashCode(this)));
5361        out.append(' ');
5362        switch (mViewFlags&VISIBILITY_MASK) {
5363            case VISIBLE: out.append('V'); break;
5364            case INVISIBLE: out.append('I'); break;
5365            case GONE: out.append('G'); break;
5366            default: out.append('.'); break;
5367        }
5368        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5369        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5370        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5371        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5372        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5373        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5374        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5375        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5376        out.append(' ');
5377        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5378        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5379        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5380        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5381            out.append('p');
5382        } else {
5383            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5384        }
5385        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5386        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5387        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5388        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5389        out.append(' ');
5390        out.append(mLeft);
5391        out.append(',');
5392        out.append(mTop);
5393        out.append('-');
5394        out.append(mRight);
5395        out.append(',');
5396        out.append(mBottom);
5397        final int id = getId();
5398        if (id != NO_ID) {
5399            out.append(" #");
5400            out.append(Integer.toHexString(id));
5401            final Resources r = mResources;
5402            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5403                try {
5404                    String pkgname;
5405                    switch (id&0xff000000) {
5406                        case 0x7f000000:
5407                            pkgname="app";
5408                            break;
5409                        case 0x01000000:
5410                            pkgname="android";
5411                            break;
5412                        default:
5413                            pkgname = r.getResourcePackageName(id);
5414                            break;
5415                    }
5416                    String typename = r.getResourceTypeName(id);
5417                    String entryname = r.getResourceEntryName(id);
5418                    out.append(" ");
5419                    out.append(pkgname);
5420                    out.append(":");
5421                    out.append(typename);
5422                    out.append("/");
5423                    out.append(entryname);
5424                } catch (Resources.NotFoundException e) {
5425                }
5426            }
5427        }
5428        out.append("}");
5429        return out.toString();
5430    }
5431
5432    /**
5433     * <p>
5434     * Initializes the fading edges from a given set of styled attributes. This
5435     * method should be called by subclasses that need fading edges and when an
5436     * instance of these subclasses is created programmatically rather than
5437     * being inflated from XML. This method is automatically called when the XML
5438     * is inflated.
5439     * </p>
5440     *
5441     * @param a the styled attributes set to initialize the fading edges from
5442     *
5443     * @removed
5444     */
5445    protected void initializeFadingEdge(TypedArray a) {
5446        // This method probably shouldn't have been included in the SDK to begin with.
5447        // It relies on 'a' having been initialized using an attribute filter array that is
5448        // not publicly available to the SDK. The old method has been renamed
5449        // to initializeFadingEdgeInternal and hidden for framework use only;
5450        // this one initializes using defaults to make it safe to call for apps.
5451
5452        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5453
5454        initializeFadingEdgeInternal(arr);
5455
5456        arr.recycle();
5457    }
5458
5459    /**
5460     * <p>
5461     * Initializes the fading edges from a given set of styled attributes. This
5462     * method should be called by subclasses that need fading edges and when an
5463     * instance of these subclasses is created programmatically rather than
5464     * being inflated from XML. This method is automatically called when the XML
5465     * is inflated.
5466     * </p>
5467     *
5468     * @param a the styled attributes set to initialize the fading edges from
5469     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5470     */
5471    protected void initializeFadingEdgeInternal(TypedArray a) {
5472        initScrollCache();
5473
5474        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5475                R.styleable.View_fadingEdgeLength,
5476                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5477    }
5478
5479    /**
5480     * Returns the size of the vertical faded edges used to indicate that more
5481     * content in this view is visible.
5482     *
5483     * @return The size in pixels of the vertical faded edge or 0 if vertical
5484     *         faded edges are not enabled for this view.
5485     * @attr ref android.R.styleable#View_fadingEdgeLength
5486     */
5487    public int getVerticalFadingEdgeLength() {
5488        if (isVerticalFadingEdgeEnabled()) {
5489            ScrollabilityCache cache = mScrollCache;
5490            if (cache != null) {
5491                return cache.fadingEdgeLength;
5492            }
5493        }
5494        return 0;
5495    }
5496
5497    /**
5498     * Set the size of the faded edge used to indicate that more content in this
5499     * view is available.  Will not change whether the fading edge is enabled; use
5500     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5501     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5502     * for the vertical or horizontal fading edges.
5503     *
5504     * @param length The size in pixels of the faded edge used to indicate that more
5505     *        content in this view is visible.
5506     */
5507    public void setFadingEdgeLength(int length) {
5508        initScrollCache();
5509        mScrollCache.fadingEdgeLength = length;
5510    }
5511
5512    /**
5513     * Returns the size of the horizontal faded edges used to indicate that more
5514     * content in this view is visible.
5515     *
5516     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5517     *         faded edges are not enabled for this view.
5518     * @attr ref android.R.styleable#View_fadingEdgeLength
5519     */
5520    public int getHorizontalFadingEdgeLength() {
5521        if (isHorizontalFadingEdgeEnabled()) {
5522            ScrollabilityCache cache = mScrollCache;
5523            if (cache != null) {
5524                return cache.fadingEdgeLength;
5525            }
5526        }
5527        return 0;
5528    }
5529
5530    /**
5531     * Returns the width of the vertical scrollbar.
5532     *
5533     * @return The width in pixels of the vertical scrollbar or 0 if there
5534     *         is no vertical scrollbar.
5535     */
5536    public int getVerticalScrollbarWidth() {
5537        ScrollabilityCache cache = mScrollCache;
5538        if (cache != null) {
5539            ScrollBarDrawable scrollBar = cache.scrollBar;
5540            if (scrollBar != null) {
5541                int size = scrollBar.getSize(true);
5542                if (size <= 0) {
5543                    size = cache.scrollBarSize;
5544                }
5545                return size;
5546            }
5547            return 0;
5548        }
5549        return 0;
5550    }
5551
5552    /**
5553     * Returns the height of the horizontal scrollbar.
5554     *
5555     * @return The height in pixels of the horizontal scrollbar or 0 if
5556     *         there is no horizontal scrollbar.
5557     */
5558    protected int getHorizontalScrollbarHeight() {
5559        ScrollabilityCache cache = mScrollCache;
5560        if (cache != null) {
5561            ScrollBarDrawable scrollBar = cache.scrollBar;
5562            if (scrollBar != null) {
5563                int size = scrollBar.getSize(false);
5564                if (size <= 0) {
5565                    size = cache.scrollBarSize;
5566                }
5567                return size;
5568            }
5569            return 0;
5570        }
5571        return 0;
5572    }
5573
5574    /**
5575     * <p>
5576     * Initializes the scrollbars from a given set of styled attributes. This
5577     * method should be called by subclasses that need scrollbars and when an
5578     * instance of these subclasses is created programmatically rather than
5579     * being inflated from XML. This method is automatically called when the XML
5580     * is inflated.
5581     * </p>
5582     *
5583     * @param a the styled attributes set to initialize the scrollbars from
5584     *
5585     * @removed
5586     */
5587    protected void initializeScrollbars(TypedArray a) {
5588        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5589        // using the View filter array which is not available to the SDK. As such, internal
5590        // framework usage now uses initializeScrollbarsInternal and we grab a default
5591        // TypedArray with the right filter instead here.
5592        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5593
5594        initializeScrollbarsInternal(arr);
5595
5596        // We ignored the method parameter. Recycle the one we actually did use.
5597        arr.recycle();
5598    }
5599
5600    /**
5601     * <p>
5602     * Initializes the scrollbars from a given set of styled attributes. This
5603     * method should be called by subclasses that need scrollbars and when an
5604     * instance of these subclasses is created programmatically rather than
5605     * being inflated from XML. This method is automatically called when the XML
5606     * is inflated.
5607     * </p>
5608     *
5609     * @param a the styled attributes set to initialize the scrollbars from
5610     * @hide
5611     */
5612    protected void initializeScrollbarsInternal(TypedArray a) {
5613        initScrollCache();
5614
5615        final ScrollabilityCache scrollabilityCache = mScrollCache;
5616
5617        if (scrollabilityCache.scrollBar == null) {
5618            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5619            scrollabilityCache.scrollBar.setState(getDrawableState());
5620            scrollabilityCache.scrollBar.setCallback(this);
5621        }
5622
5623        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5624
5625        if (!fadeScrollbars) {
5626            scrollabilityCache.state = ScrollabilityCache.ON;
5627        }
5628        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5629
5630
5631        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5632                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5633                        .getScrollBarFadeDuration());
5634        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5635                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5636                ViewConfiguration.getScrollDefaultDelay());
5637
5638
5639        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5640                com.android.internal.R.styleable.View_scrollbarSize,
5641                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5642
5643        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5644        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5645
5646        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5647        if (thumb != null) {
5648            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5649        }
5650
5651        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5652                false);
5653        if (alwaysDraw) {
5654            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5655        }
5656
5657        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5658        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5659
5660        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5661        if (thumb != null) {
5662            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5663        }
5664
5665        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5666                false);
5667        if (alwaysDraw) {
5668            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5669        }
5670
5671        // Apply layout direction to the new Drawables if needed
5672        final int layoutDirection = getLayoutDirection();
5673        if (track != null) {
5674            track.setLayoutDirection(layoutDirection);
5675        }
5676        if (thumb != null) {
5677            thumb.setLayoutDirection(layoutDirection);
5678        }
5679
5680        // Re-apply user/background padding so that scrollbar(s) get added
5681        resolvePadding();
5682    }
5683
5684    private void initializeScrollIndicatorsInternal() {
5685        // Some day maybe we'll break this into top/left/start/etc. and let the
5686        // client control it. Until then, you can have any scroll indicator you
5687        // want as long as it's a 1dp foreground-colored rectangle.
5688        if (mScrollIndicatorDrawable == null) {
5689            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5690        }
5691    }
5692
5693    /**
5694     * <p>
5695     * Initalizes the scrollability cache if necessary.
5696     * </p>
5697     */
5698    private void initScrollCache() {
5699        if (mScrollCache == null) {
5700            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5701        }
5702    }
5703
5704    private ScrollabilityCache getScrollCache() {
5705        initScrollCache();
5706        return mScrollCache;
5707    }
5708
5709    /**
5710     * Set the position of the vertical scroll bar. Should be one of
5711     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5712     * {@link #SCROLLBAR_POSITION_RIGHT}.
5713     *
5714     * @param position Where the vertical scroll bar should be positioned.
5715     */
5716    public void setVerticalScrollbarPosition(int position) {
5717        if (mVerticalScrollbarPosition != position) {
5718            mVerticalScrollbarPosition = position;
5719            computeOpaqueFlags();
5720            resolvePadding();
5721        }
5722    }
5723
5724    /**
5725     * @return The position where the vertical scroll bar will show, if applicable.
5726     * @see #setVerticalScrollbarPosition(int)
5727     */
5728    public int getVerticalScrollbarPosition() {
5729        return mVerticalScrollbarPosition;
5730    }
5731
5732    boolean isOnScrollbar(float x, float y) {
5733        if (mScrollCache == null) {
5734            return false;
5735        }
5736        x += getScrollX();
5737        y += getScrollY();
5738        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5739            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5740            getVerticalScrollBarBounds(null, touchBounds);
5741            if (touchBounds.contains((int) x, (int) y)) {
5742                return true;
5743            }
5744        }
5745        if (isHorizontalScrollBarEnabled()) {
5746            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5747            getHorizontalScrollBarBounds(null, touchBounds);
5748            if (touchBounds.contains((int) x, (int) y)) {
5749                return true;
5750            }
5751        }
5752        return false;
5753    }
5754
5755    boolean isOnScrollbarThumb(float x, float y) {
5756        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5757    }
5758
5759    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5760        if (mScrollCache == null) {
5761            return false;
5762        }
5763        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5764            x += getScrollX();
5765            y += getScrollY();
5766            final Rect bounds = mScrollCache.mScrollBarBounds;
5767            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5768            getVerticalScrollBarBounds(bounds, touchBounds);
5769            final int range = computeVerticalScrollRange();
5770            final int offset = computeVerticalScrollOffset();
5771            final int extent = computeVerticalScrollExtent();
5772            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5773                    extent, range);
5774            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5775                    extent, range, offset);
5776            final int thumbTop = bounds.top + thumbOffset;
5777            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5778            if (x >= touchBounds.left && x <= touchBounds.right
5779                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5780                return true;
5781            }
5782        }
5783        return false;
5784    }
5785
5786    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5787        if (mScrollCache == null) {
5788            return false;
5789        }
5790        if (isHorizontalScrollBarEnabled()) {
5791            x += getScrollX();
5792            y += getScrollY();
5793            final Rect bounds = mScrollCache.mScrollBarBounds;
5794            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5795            getHorizontalScrollBarBounds(bounds, touchBounds);
5796            final int range = computeHorizontalScrollRange();
5797            final int offset = computeHorizontalScrollOffset();
5798            final int extent = computeHorizontalScrollExtent();
5799            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5800                    extent, range);
5801            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5802                    extent, range, offset);
5803            final int thumbLeft = bounds.left + thumbOffset;
5804            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5805            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5806                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5807                return true;
5808            }
5809        }
5810        return false;
5811    }
5812
5813    boolean isDraggingScrollBar() {
5814        return mScrollCache != null
5815                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5816    }
5817
5818    /**
5819     * Sets the state of all scroll indicators.
5820     * <p>
5821     * See {@link #setScrollIndicators(int, int)} for usage information.
5822     *
5823     * @param indicators a bitmask of indicators that should be enabled, or
5824     *                   {@code 0} to disable all indicators
5825     * @see #setScrollIndicators(int, int)
5826     * @see #getScrollIndicators()
5827     * @attr ref android.R.styleable#View_scrollIndicators
5828     */
5829    public void setScrollIndicators(@ScrollIndicators int indicators) {
5830        setScrollIndicators(indicators,
5831                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5832    }
5833
5834    /**
5835     * Sets the state of the scroll indicators specified by the mask. To change
5836     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5837     * <p>
5838     * When a scroll indicator is enabled, it will be displayed if the view
5839     * can scroll in the direction of the indicator.
5840     * <p>
5841     * Multiple indicator types may be enabled or disabled by passing the
5842     * logical OR of the desired types. If multiple types are specified, they
5843     * will all be set to the same enabled state.
5844     * <p>
5845     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5846     *
5847     * @param indicators the indicator direction, or the logical OR of multiple
5848     *             indicator directions. One or more of:
5849     *             <ul>
5850     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5851     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5852     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5853     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5854     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5855     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5856     *             </ul>
5857     * @see #setScrollIndicators(int)
5858     * @see #getScrollIndicators()
5859     * @attr ref android.R.styleable#View_scrollIndicators
5860     */
5861    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5862        // Shift and sanitize mask.
5863        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5864        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5865
5866        // Shift and mask indicators.
5867        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5868        indicators &= mask;
5869
5870        // Merge with non-masked flags.
5871        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5872
5873        if (mPrivateFlags3 != updatedFlags) {
5874            mPrivateFlags3 = updatedFlags;
5875
5876            if (indicators != 0) {
5877                initializeScrollIndicatorsInternal();
5878            }
5879            invalidate();
5880        }
5881    }
5882
5883    /**
5884     * Returns a bitmask representing the enabled scroll indicators.
5885     * <p>
5886     * For example, if the top and left scroll indicators are enabled and all
5887     * other indicators are disabled, the return value will be
5888     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5889     * <p>
5890     * To check whether the bottom scroll indicator is enabled, use the value
5891     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5892     *
5893     * @return a bitmask representing the enabled scroll indicators
5894     */
5895    @ScrollIndicators
5896    public int getScrollIndicators() {
5897        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5898                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5899    }
5900
5901    ListenerInfo getListenerInfo() {
5902        if (mListenerInfo != null) {
5903            return mListenerInfo;
5904        }
5905        mListenerInfo = new ListenerInfo();
5906        return mListenerInfo;
5907    }
5908
5909    /**
5910     * Register a callback to be invoked when the scroll X or Y positions of
5911     * this view change.
5912     * <p>
5913     * <b>Note:</b> Some views handle scrolling independently from View and may
5914     * have their own separate listeners for scroll-type events. For example,
5915     * {@link android.widget.ListView ListView} allows clients to register an
5916     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5917     * to listen for changes in list scroll position.
5918     *
5919     * @param l The listener to notify when the scroll X or Y position changes.
5920     * @see android.view.View#getScrollX()
5921     * @see android.view.View#getScrollY()
5922     */
5923    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5924        getListenerInfo().mOnScrollChangeListener = l;
5925    }
5926
5927    /**
5928     * Register a callback to be invoked when focus of this view changed.
5929     *
5930     * @param l The callback that will run.
5931     */
5932    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5933        getListenerInfo().mOnFocusChangeListener = l;
5934    }
5935
5936    /**
5937     * Add a listener that will be called when the bounds of the view change due to
5938     * layout processing.
5939     *
5940     * @param listener The listener that will be called when layout bounds change.
5941     */
5942    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5943        ListenerInfo li = getListenerInfo();
5944        if (li.mOnLayoutChangeListeners == null) {
5945            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5946        }
5947        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5948            li.mOnLayoutChangeListeners.add(listener);
5949        }
5950    }
5951
5952    /**
5953     * Remove a listener for layout changes.
5954     *
5955     * @param listener The listener for layout bounds change.
5956     */
5957    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5958        ListenerInfo li = mListenerInfo;
5959        if (li == null || li.mOnLayoutChangeListeners == null) {
5960            return;
5961        }
5962        li.mOnLayoutChangeListeners.remove(listener);
5963    }
5964
5965    /**
5966     * Add a listener for attach state changes.
5967     *
5968     * This listener will be called whenever this view is attached or detached
5969     * from a window. Remove the listener using
5970     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5971     *
5972     * @param listener Listener to attach
5973     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5974     */
5975    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5976        ListenerInfo li = getListenerInfo();
5977        if (li.mOnAttachStateChangeListeners == null) {
5978            li.mOnAttachStateChangeListeners
5979                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5980        }
5981        li.mOnAttachStateChangeListeners.add(listener);
5982    }
5983
5984    /**
5985     * Remove a listener for attach state changes. The listener will receive no further
5986     * notification of window attach/detach events.
5987     *
5988     * @param listener Listener to remove
5989     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5990     */
5991    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5992        ListenerInfo li = mListenerInfo;
5993        if (li == null || li.mOnAttachStateChangeListeners == null) {
5994            return;
5995        }
5996        li.mOnAttachStateChangeListeners.remove(listener);
5997    }
5998
5999    /**
6000     * Returns the focus-change callback registered for this view.
6001     *
6002     * @return The callback, or null if one is not registered.
6003     */
6004    public OnFocusChangeListener getOnFocusChangeListener() {
6005        ListenerInfo li = mListenerInfo;
6006        return li != null ? li.mOnFocusChangeListener : null;
6007    }
6008
6009    /**
6010     * Register a callback to be invoked when this view is clicked. If this view is not
6011     * clickable, it becomes clickable.
6012     *
6013     * @param l The callback that will run
6014     *
6015     * @see #setClickable(boolean)
6016     */
6017    public void setOnClickListener(@Nullable OnClickListener l) {
6018        if (!isClickable()) {
6019            setClickable(true);
6020        }
6021        getListenerInfo().mOnClickListener = l;
6022    }
6023
6024    /**
6025     * Return whether this view has an attached OnClickListener.  Returns
6026     * true if there is a listener, false if there is none.
6027     */
6028    public boolean hasOnClickListeners() {
6029        ListenerInfo li = mListenerInfo;
6030        return (li != null && li.mOnClickListener != null);
6031    }
6032
6033    /**
6034     * Register a callback to be invoked when this view is clicked and held. If this view is not
6035     * long clickable, it becomes long clickable.
6036     *
6037     * @param l The callback that will run
6038     *
6039     * @see #setLongClickable(boolean)
6040     */
6041    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6042        if (!isLongClickable()) {
6043            setLongClickable(true);
6044        }
6045        getListenerInfo().mOnLongClickListener = l;
6046    }
6047
6048    /**
6049     * Register a callback to be invoked when this view is context clicked. If the view is not
6050     * context clickable, it becomes context clickable.
6051     *
6052     * @param l The callback that will run
6053     * @see #setContextClickable(boolean)
6054     */
6055    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6056        if (!isContextClickable()) {
6057            setContextClickable(true);
6058        }
6059        getListenerInfo().mOnContextClickListener = l;
6060    }
6061
6062    /**
6063     * Register a callback to be invoked when the context menu for this view is
6064     * being built. If this view is not long clickable, it becomes long clickable.
6065     *
6066     * @param l The callback that will run
6067     *
6068     */
6069    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6070        if (!isLongClickable()) {
6071            setLongClickable(true);
6072        }
6073        getListenerInfo().mOnCreateContextMenuListener = l;
6074    }
6075
6076    /**
6077     * Set an observer to collect stats for each frame rendered for this view.
6078     *
6079     * @hide
6080     */
6081    public void addFrameMetricsListener(Window window,
6082            Window.OnFrameMetricsAvailableListener listener,
6083            Handler handler) {
6084        if (mAttachInfo != null) {
6085            if (mAttachInfo.mThreadedRenderer != null) {
6086                if (mFrameMetricsObservers == null) {
6087                    mFrameMetricsObservers = new ArrayList<>();
6088                }
6089
6090                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6091                        handler.getLooper(), listener);
6092                mFrameMetricsObservers.add(fmo);
6093                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6094            } else {
6095                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6096            }
6097        } else {
6098            if (mFrameMetricsObservers == null) {
6099                mFrameMetricsObservers = new ArrayList<>();
6100            }
6101
6102            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6103                    handler.getLooper(), listener);
6104            mFrameMetricsObservers.add(fmo);
6105        }
6106    }
6107
6108    /**
6109     * Remove observer configured to collect frame stats for this view.
6110     *
6111     * @hide
6112     */
6113    public void removeFrameMetricsListener(
6114            Window.OnFrameMetricsAvailableListener listener) {
6115        ThreadedRenderer renderer = getThreadedRenderer();
6116        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6117        if (fmo == null) {
6118            throw new IllegalArgumentException(
6119                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6120        }
6121
6122        if (mFrameMetricsObservers != null) {
6123            mFrameMetricsObservers.remove(fmo);
6124            if (renderer != null) {
6125                renderer.removeFrameMetricsObserver(fmo);
6126            }
6127        }
6128    }
6129
6130    private void registerPendingFrameMetricsObservers() {
6131        if (mFrameMetricsObservers != null) {
6132            ThreadedRenderer renderer = getThreadedRenderer();
6133            if (renderer != null) {
6134                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6135                    renderer.addFrameMetricsObserver(fmo);
6136                }
6137            } else {
6138                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6139            }
6140        }
6141    }
6142
6143    private FrameMetricsObserver findFrameMetricsObserver(
6144            Window.OnFrameMetricsAvailableListener listener) {
6145        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6146            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6147            if (observer.mListener == listener) {
6148                return observer;
6149            }
6150        }
6151
6152        return null;
6153    }
6154
6155    /**
6156     * Call this view's OnClickListener, if it is defined.  Performs all normal
6157     * actions associated with clicking: reporting accessibility event, playing
6158     * a sound, etc.
6159     *
6160     * @return True there was an assigned OnClickListener that was called, false
6161     *         otherwise is returned.
6162     */
6163    public boolean performClick() {
6164        final boolean result;
6165        final ListenerInfo li = mListenerInfo;
6166        if (li != null && li.mOnClickListener != null) {
6167            playSoundEffect(SoundEffectConstants.CLICK);
6168            li.mOnClickListener.onClick(this);
6169            result = true;
6170        } else {
6171            result = false;
6172        }
6173
6174        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6175
6176        notifyEnterOrExitForAutoFillIfNeeded(true);
6177
6178        return result;
6179    }
6180
6181    /**
6182     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6183     * this only calls the listener, and does not do any associated clicking
6184     * actions like reporting an accessibility event.
6185     *
6186     * @return True there was an assigned OnClickListener that was called, false
6187     *         otherwise is returned.
6188     */
6189    public boolean callOnClick() {
6190        ListenerInfo li = mListenerInfo;
6191        if (li != null && li.mOnClickListener != null) {
6192            li.mOnClickListener.onClick(this);
6193            return true;
6194        }
6195        return false;
6196    }
6197
6198    /**
6199     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6200     * context menu if the OnLongClickListener did not consume the event.
6201     *
6202     * @return {@code true} if one of the above receivers consumed the event,
6203     *         {@code false} otherwise
6204     */
6205    public boolean performLongClick() {
6206        return performLongClickInternal(mLongClickX, mLongClickY);
6207    }
6208
6209    /**
6210     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6211     * context menu if the OnLongClickListener did not consume the event,
6212     * anchoring it to an (x,y) coordinate.
6213     *
6214     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6215     *          to disable anchoring
6216     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6217     *          to disable anchoring
6218     * @return {@code true} if one of the above receivers consumed the event,
6219     *         {@code false} otherwise
6220     */
6221    public boolean performLongClick(float x, float y) {
6222        mLongClickX = x;
6223        mLongClickY = y;
6224        final boolean handled = performLongClick();
6225        mLongClickX = Float.NaN;
6226        mLongClickY = Float.NaN;
6227        return handled;
6228    }
6229
6230    /**
6231     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6232     * context menu if the OnLongClickListener did not consume the event,
6233     * optionally anchoring it to an (x,y) coordinate.
6234     *
6235     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6236     *          to disable anchoring
6237     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6238     *          to disable anchoring
6239     * @return {@code true} if one of the above receivers consumed the event,
6240     *         {@code false} otherwise
6241     */
6242    private boolean performLongClickInternal(float x, float y) {
6243        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6244
6245        boolean handled = false;
6246        final ListenerInfo li = mListenerInfo;
6247        if (li != null && li.mOnLongClickListener != null) {
6248            handled = li.mOnLongClickListener.onLongClick(View.this);
6249        }
6250        if (!handled) {
6251            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6252            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6253        }
6254        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6255            if (!handled) {
6256                handled = showLongClickTooltip((int) x, (int) y);
6257            }
6258        }
6259        if (handled) {
6260            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6261        }
6262        return handled;
6263    }
6264
6265    /**
6266     * Call this view's OnContextClickListener, if it is defined.
6267     *
6268     * @param x the x coordinate of the context click
6269     * @param y the y coordinate of the context click
6270     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6271     *         otherwise.
6272     */
6273    public boolean performContextClick(float x, float y) {
6274        return performContextClick();
6275    }
6276
6277    /**
6278     * Call this view's OnContextClickListener, if it is defined.
6279     *
6280     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6281     *         otherwise.
6282     */
6283    public boolean performContextClick() {
6284        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6285
6286        boolean handled = false;
6287        ListenerInfo li = mListenerInfo;
6288        if (li != null && li.mOnContextClickListener != null) {
6289            handled = li.mOnContextClickListener.onContextClick(View.this);
6290        }
6291        if (handled) {
6292            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6293        }
6294        return handled;
6295    }
6296
6297    /**
6298     * Performs button-related actions during a touch down event.
6299     *
6300     * @param event The event.
6301     * @return True if the down was consumed.
6302     *
6303     * @hide
6304     */
6305    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6306        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6307            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6308            showContextMenu(event.getX(), event.getY());
6309            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6310            return true;
6311        }
6312        return false;
6313    }
6314
6315    /**
6316     * Shows the context menu for this view.
6317     *
6318     * @return {@code true} if the context menu was shown, {@code false}
6319     *         otherwise
6320     * @see #showContextMenu(float, float)
6321     */
6322    public boolean showContextMenu() {
6323        return getParent().showContextMenuForChild(this);
6324    }
6325
6326    /**
6327     * Shows the context menu for this view anchored to the specified
6328     * view-relative coordinate.
6329     *
6330     * @param x the X coordinate in pixels relative to the view to which the
6331     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6332     * @param y the Y coordinate in pixels relative to the view to which the
6333     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6334     * @return {@code true} if the context menu was shown, {@code false}
6335     *         otherwise
6336     */
6337    public boolean showContextMenu(float x, float y) {
6338        return getParent().showContextMenuForChild(this, x, y);
6339    }
6340
6341    /**
6342     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6343     *
6344     * @param callback Callback that will control the lifecycle of the action mode
6345     * @return The new action mode if it is started, null otherwise
6346     *
6347     * @see ActionMode
6348     * @see #startActionMode(android.view.ActionMode.Callback, int)
6349     */
6350    public ActionMode startActionMode(ActionMode.Callback callback) {
6351        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6352    }
6353
6354    /**
6355     * Start an action mode with the given type.
6356     *
6357     * @param callback Callback that will control the lifecycle of the action mode
6358     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6359     * @return The new action mode if it is started, null otherwise
6360     *
6361     * @see ActionMode
6362     */
6363    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6364        ViewParent parent = getParent();
6365        if (parent == null) return null;
6366        try {
6367            return parent.startActionModeForChild(this, callback, type);
6368        } catch (AbstractMethodError ame) {
6369            // Older implementations of custom views might not implement this.
6370            return parent.startActionModeForChild(this, callback);
6371        }
6372    }
6373
6374    /**
6375     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6376     * Context, creating a unique View identifier to retrieve the result.
6377     *
6378     * @param intent The Intent to be started.
6379     * @param requestCode The request code to use.
6380     * @hide
6381     */
6382    public void startActivityForResult(Intent intent, int requestCode) {
6383        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6384        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6385    }
6386
6387    /**
6388     * If this View corresponds to the calling who, dispatches the activity result.
6389     * @param who The identifier for the targeted View to receive the result.
6390     * @param requestCode The integer request code originally supplied to
6391     *                    startActivityForResult(), allowing you to identify who this
6392     *                    result came from.
6393     * @param resultCode The integer result code returned by the child activity
6394     *                   through its setResult().
6395     * @param data An Intent, which can return result data to the caller
6396     *               (various data can be attached to Intent "extras").
6397     * @return {@code true} if the activity result was dispatched.
6398     * @hide
6399     */
6400    public boolean dispatchActivityResult(
6401            String who, int requestCode, int resultCode, Intent data) {
6402        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6403            onActivityResult(requestCode, resultCode, data);
6404            mStartActivityRequestWho = null;
6405            return true;
6406        }
6407        return false;
6408    }
6409
6410    /**
6411     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6412     *
6413     * @param requestCode The integer request code originally supplied to
6414     *                    startActivityForResult(), allowing you to identify who this
6415     *                    result came from.
6416     * @param resultCode The integer result code returned by the child activity
6417     *                   through its setResult().
6418     * @param data An Intent, which can return result data to the caller
6419     *               (various data can be attached to Intent "extras").
6420     * @hide
6421     */
6422    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6423        // Do nothing.
6424    }
6425
6426    /**
6427     * Register a callback to be invoked when a hardware key is pressed in this view.
6428     * Key presses in software input methods will generally not trigger the methods of
6429     * this listener.
6430     * @param l the key listener to attach to this view
6431     */
6432    public void setOnKeyListener(OnKeyListener l) {
6433        getListenerInfo().mOnKeyListener = l;
6434    }
6435
6436    /**
6437     * Register a callback to be invoked when a touch event is sent to this view.
6438     * @param l the touch listener to attach to this view
6439     */
6440    public void setOnTouchListener(OnTouchListener l) {
6441        getListenerInfo().mOnTouchListener = l;
6442    }
6443
6444    /**
6445     * Register a callback to be invoked when a generic motion event is sent to this view.
6446     * @param l the generic motion listener to attach to this view
6447     */
6448    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6449        getListenerInfo().mOnGenericMotionListener = l;
6450    }
6451
6452    /**
6453     * Register a callback to be invoked when a hover event is sent to this view.
6454     * @param l the hover listener to attach to this view
6455     */
6456    public void setOnHoverListener(OnHoverListener l) {
6457        getListenerInfo().mOnHoverListener = l;
6458    }
6459
6460    /**
6461     * Register a drag event listener callback object for this View. The parameter is
6462     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6463     * View, the system calls the
6464     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6465     * @param l An implementation of {@link android.view.View.OnDragListener}.
6466     */
6467    public void setOnDragListener(OnDragListener l) {
6468        getListenerInfo().mOnDragListener = l;
6469    }
6470
6471    /**
6472     * Give this view focus. This will cause
6473     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6474     *
6475     * Note: this does not check whether this {@link View} should get focus, it just
6476     * gives it focus no matter what.  It should only be called internally by framework
6477     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6478     *
6479     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6480     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6481     *        focus moved when requestFocus() is called. It may not always
6482     *        apply, in which case use the default View.FOCUS_DOWN.
6483     * @param previouslyFocusedRect The rectangle of the view that had focus
6484     *        prior in this View's coordinate system.
6485     */
6486    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6487        if (DBG) {
6488            System.out.println(this + " requestFocus()");
6489        }
6490
6491        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6492            mPrivateFlags |= PFLAG_FOCUSED;
6493
6494            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6495
6496            if (mParent != null) {
6497                mParent.requestChildFocus(this, this);
6498                setFocusedInCluster();
6499            }
6500
6501            if (mAttachInfo != null) {
6502                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6503            }
6504
6505            onFocusChanged(true, direction, previouslyFocusedRect);
6506            refreshDrawableState();
6507        }
6508    }
6509
6510    /**
6511     * Sets this view's preference for reveal behavior when it gains focus.
6512     *
6513     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6514     * this view would prefer to be brought fully into view when it gains focus.
6515     * For example, a text field that a user is meant to type into. Other views such
6516     * as scrolling containers may prefer to opt-out of this behavior.</p>
6517     *
6518     * <p>The default value for views is true, though subclasses may change this
6519     * based on their preferred behavior.</p>
6520     *
6521     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6522     *
6523     * @see #getRevealOnFocusHint()
6524     */
6525    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6526        if (revealOnFocus) {
6527            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6528        } else {
6529            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6530        }
6531    }
6532
6533    /**
6534     * Returns this view's preference for reveal behavior when it gains focus.
6535     *
6536     * <p>When this method returns true for a child view requesting focus, ancestor
6537     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6538     * should make a best effort to make the newly focused child fully visible to the user.
6539     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6540     * other properties affecting visibility to the user as part of the focus change.</p>
6541     *
6542     * @return true if this view would prefer to become fully visible when it gains focus,
6543     *         false if it would prefer not to disrupt scroll positioning
6544     *
6545     * @see #setRevealOnFocusHint(boolean)
6546     */
6547    public final boolean getRevealOnFocusHint() {
6548        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6549    }
6550
6551    /**
6552     * Populates <code>outRect</code> with the hotspot bounds. By default,
6553     * the hotspot bounds are identical to the screen bounds.
6554     *
6555     * @param outRect rect to populate with hotspot bounds
6556     * @hide Only for internal use by views and widgets.
6557     */
6558    public void getHotspotBounds(Rect outRect) {
6559        final Drawable background = getBackground();
6560        if (background != null) {
6561            background.getHotspotBounds(outRect);
6562        } else {
6563            getBoundsOnScreen(outRect);
6564        }
6565    }
6566
6567    /**
6568     * Request that a rectangle of this view be visible on the screen,
6569     * scrolling if necessary just enough.
6570     *
6571     * <p>A View should call this if it maintains some notion of which part
6572     * of its content is interesting.  For example, a text editing view
6573     * should call this when its cursor moves.
6574     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6575     * It should not be affected by which part of the View is currently visible or its scroll
6576     * position.
6577     *
6578     * @param rectangle The rectangle in the View's content coordinate space
6579     * @return Whether any parent scrolled.
6580     */
6581    public boolean requestRectangleOnScreen(Rect rectangle) {
6582        return requestRectangleOnScreen(rectangle, false);
6583    }
6584
6585    /**
6586     * Request that a rectangle of this view be visible on the screen,
6587     * scrolling if necessary just enough.
6588     *
6589     * <p>A View should call this if it maintains some notion of which part
6590     * of its content is interesting.  For example, a text editing view
6591     * should call this when its cursor moves.
6592     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6593     * It should not be affected by which part of the View is currently visible or its scroll
6594     * position.
6595     * <p>When <code>immediate</code> is set to true, scrolling will not be
6596     * animated.
6597     *
6598     * @param rectangle The rectangle in the View's content coordinate space
6599     * @param immediate True to forbid animated scrolling, false otherwise
6600     * @return Whether any parent scrolled.
6601     */
6602    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6603        if (mParent == null) {
6604            return false;
6605        }
6606
6607        View child = this;
6608
6609        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6610        position.set(rectangle);
6611
6612        ViewParent parent = mParent;
6613        boolean scrolled = false;
6614        while (parent != null) {
6615            rectangle.set((int) position.left, (int) position.top,
6616                    (int) position.right, (int) position.bottom);
6617
6618            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6619
6620            if (!(parent instanceof View)) {
6621                break;
6622            }
6623
6624            // move it from child's content coordinate space to parent's content coordinate space
6625            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6626
6627            child = (View) parent;
6628            parent = child.getParent();
6629        }
6630
6631        return scrolled;
6632    }
6633
6634    /**
6635     * Called when this view wants to give up focus. If focus is cleared
6636     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6637     * <p>
6638     * <strong>Note:</strong> When a View clears focus the framework is trying
6639     * to give focus to the first focusable View from the top. Hence, if this
6640     * View is the first from the top that can take focus, then all callbacks
6641     * related to clearing focus will be invoked after which the framework will
6642     * give focus to this view.
6643     * </p>
6644     */
6645    public void clearFocus() {
6646        if (DBG) {
6647            System.out.println(this + " clearFocus()");
6648        }
6649
6650        clearFocusInternal(null, true, true);
6651    }
6652
6653    /**
6654     * Clears focus from the view, optionally propagating the change up through
6655     * the parent hierarchy and requesting that the root view place new focus.
6656     *
6657     * @param propagate whether to propagate the change up through the parent
6658     *            hierarchy
6659     * @param refocus when propagate is true, specifies whether to request the
6660     *            root view place new focus
6661     */
6662    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6663        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6664            mPrivateFlags &= ~PFLAG_FOCUSED;
6665
6666            if (propagate && mParent != null) {
6667                mParent.clearChildFocus(this);
6668            }
6669
6670            onFocusChanged(false, 0, null);
6671            refreshDrawableState();
6672
6673            if (propagate && (!refocus || !rootViewRequestFocus())) {
6674                notifyGlobalFocusCleared(this);
6675            }
6676        }
6677    }
6678
6679    void notifyGlobalFocusCleared(View oldFocus) {
6680        if (oldFocus != null && mAttachInfo != null) {
6681            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6682        }
6683    }
6684
6685    boolean rootViewRequestFocus() {
6686        final View root = getRootView();
6687        return root != null && root.requestFocus();
6688    }
6689
6690    /**
6691     * Called internally by the view system when a new view is getting focus.
6692     * This is what clears the old focus.
6693     * <p>
6694     * <b>NOTE:</b> The parent view's focused child must be updated manually
6695     * after calling this method. Otherwise, the view hierarchy may be left in
6696     * an inconstent state.
6697     */
6698    void unFocus(View focused) {
6699        if (DBG) {
6700            System.out.println(this + " unFocus()");
6701        }
6702
6703        clearFocusInternal(focused, false, false);
6704    }
6705
6706    /**
6707     * Returns true if this view has focus itself, or is the ancestor of the
6708     * view that has focus.
6709     *
6710     * @return True if this view has or contains focus, false otherwise.
6711     */
6712    @ViewDebug.ExportedProperty(category = "focus")
6713    public boolean hasFocus() {
6714        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6715    }
6716
6717    /**
6718     * Returns true if this view is focusable or if it contains a reachable View
6719     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6720     * is a view whose parents do not block descendants focus.
6721     * Only {@link #VISIBLE} views are considered focusable.
6722     *
6723     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6724     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6725     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6726     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6727     * {@code false} for views not explicitly marked as focusable.
6728     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6729     * behavior.</p>
6730     *
6731     * @return {@code true} if the view is focusable or if the view contains a focusable
6732     *         view, {@code false} otherwise
6733     *
6734     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6735     * @see ViewGroup#getTouchscreenBlocksFocus()
6736     * @see #hasExplicitFocusable()
6737     */
6738    public boolean hasFocusable() {
6739        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6740    }
6741
6742    /**
6743     * Returns true if this view is focusable or if it contains a reachable View
6744     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6745     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6746     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6747     * {@link #FOCUSABLE} are considered focusable.
6748     *
6749     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6750     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6751     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6752     * to focusable will not.</p>
6753     *
6754     * @return {@code true} if the view is focusable or if the view contains a focusable
6755     *         view, {@code false} otherwise
6756     *
6757     * @see #hasFocusable()
6758     */
6759    public boolean hasExplicitFocusable() {
6760        return hasFocusable(false, true);
6761    }
6762
6763    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6764        if (!isFocusableInTouchMode()) {
6765            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6766                final ViewGroup g = (ViewGroup) p;
6767                if (g.shouldBlockFocusForTouchscreen()) {
6768                    return false;
6769                }
6770            }
6771        }
6772
6773        // Invisible and gone views are never focusable.
6774        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6775            return false;
6776        }
6777
6778        // Only use effective focusable value when allowed.
6779        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6780            return true;
6781        }
6782
6783        return false;
6784    }
6785
6786    /**
6787     * Called by the view system when the focus state of this view changes.
6788     * When the focus change event is caused by directional navigation, direction
6789     * and previouslyFocusedRect provide insight into where the focus is coming from.
6790     * When overriding, be sure to call up through to the super class so that
6791     * the standard focus handling will occur.
6792     *
6793     * @param gainFocus True if the View has focus; false otherwise.
6794     * @param direction The direction focus has moved when requestFocus()
6795     *                  is called to give this view focus. Values are
6796     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6797     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6798     *                  It may not always apply, in which case use the default.
6799     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6800     *        system, of the previously focused view.  If applicable, this will be
6801     *        passed in as finer grained information about where the focus is coming
6802     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6803     */
6804    @CallSuper
6805    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6806            @Nullable Rect previouslyFocusedRect) {
6807        if (gainFocus) {
6808            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6809        } else {
6810            notifyViewAccessibilityStateChangedIfNeeded(
6811                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6812        }
6813
6814        InputMethodManager imm = InputMethodManager.peekInstance();
6815        if (!gainFocus) {
6816            if (isPressed()) {
6817                setPressed(false);
6818            }
6819            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6820                imm.focusOut(this);
6821            }
6822            onFocusLost();
6823        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6824            imm.focusIn(this);
6825        }
6826
6827        invalidate(true);
6828        ListenerInfo li = mListenerInfo;
6829        if (li != null && li.mOnFocusChangeListener != null) {
6830            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6831        }
6832
6833        if (mAttachInfo != null) {
6834            mAttachInfo.mKeyDispatchState.reset(this);
6835        }
6836
6837        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6838    }
6839
6840    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6841        if (isAutofillable() && isAttachedToWindow()
6842                && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
6843            AutofillManager afm = getAutofillManager();
6844            if (afm != null) {
6845                if (enter && hasWindowFocus() && isFocused()) {
6846                    afm.notifyViewEntered(this);
6847                } else if (!hasWindowFocus() || !isFocused()) {
6848                    afm.notifyViewExited(this);
6849                }
6850            }
6851        }
6852    }
6853
6854    /**
6855     * Sends an accessibility event of the given type. If accessibility is
6856     * not enabled this method has no effect. The default implementation calls
6857     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6858     * to populate information about the event source (this View), then calls
6859     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6860     * populate the text content of the event source including its descendants,
6861     * and last calls
6862     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6863     * on its parent to request sending of the event to interested parties.
6864     * <p>
6865     * If an {@link AccessibilityDelegate} has been specified via calling
6866     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6867     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6868     * responsible for handling this call.
6869     * </p>
6870     *
6871     * @param eventType The type of the event to send, as defined by several types from
6872     * {@link android.view.accessibility.AccessibilityEvent}, such as
6873     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6874     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6875     *
6876     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6877     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6878     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6879     * @see AccessibilityDelegate
6880     */
6881    public void sendAccessibilityEvent(int eventType) {
6882        if (mAccessibilityDelegate != null) {
6883            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6884        } else {
6885            sendAccessibilityEventInternal(eventType);
6886        }
6887    }
6888
6889    /**
6890     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6891     * {@link AccessibilityEvent} to make an announcement which is related to some
6892     * sort of a context change for which none of the events representing UI transitions
6893     * is a good fit. For example, announcing a new page in a book. If accessibility
6894     * is not enabled this method does nothing.
6895     *
6896     * @param text The announcement text.
6897     */
6898    public void announceForAccessibility(CharSequence text) {
6899        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6900            AccessibilityEvent event = AccessibilityEvent.obtain(
6901                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6902            onInitializeAccessibilityEvent(event);
6903            event.getText().add(text);
6904            event.setContentDescription(null);
6905            mParent.requestSendAccessibilityEvent(this, event);
6906        }
6907    }
6908
6909    /**
6910     * @see #sendAccessibilityEvent(int)
6911     *
6912     * Note: Called from the default {@link AccessibilityDelegate}.
6913     *
6914     * @hide
6915     */
6916    public void sendAccessibilityEventInternal(int eventType) {
6917        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6918            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6919        }
6920    }
6921
6922    /**
6923     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6924     * takes as an argument an empty {@link AccessibilityEvent} and does not
6925     * perform a check whether accessibility is enabled.
6926     * <p>
6927     * If an {@link AccessibilityDelegate} has been specified via calling
6928     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6929     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6930     * is responsible for handling this call.
6931     * </p>
6932     *
6933     * @param event The event to send.
6934     *
6935     * @see #sendAccessibilityEvent(int)
6936     */
6937    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6938        if (mAccessibilityDelegate != null) {
6939            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6940        } else {
6941            sendAccessibilityEventUncheckedInternal(event);
6942        }
6943    }
6944
6945    /**
6946     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6947     *
6948     * Note: Called from the default {@link AccessibilityDelegate}.
6949     *
6950     * @hide
6951     */
6952    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6953        if (!isShown()) {
6954            return;
6955        }
6956        onInitializeAccessibilityEvent(event);
6957        // Only a subset of accessibility events populates text content.
6958        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6959            dispatchPopulateAccessibilityEvent(event);
6960        }
6961        // In the beginning we called #isShown(), so we know that getParent() is not null.
6962        getParent().requestSendAccessibilityEvent(this, event);
6963    }
6964
6965    /**
6966     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6967     * to its children for adding their text content to the event. Note that the
6968     * event text is populated in a separate dispatch path since we add to the
6969     * event not only the text of the source but also the text of all its descendants.
6970     * A typical implementation will call
6971     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6972     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6973     * on each child. Override this method if custom population of the event text
6974     * content is required.
6975     * <p>
6976     * If an {@link AccessibilityDelegate} has been specified via calling
6977     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6978     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6979     * is responsible for handling this call.
6980     * </p>
6981     * <p>
6982     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6983     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6984     * </p>
6985     *
6986     * @param event The event.
6987     *
6988     * @return True if the event population was completed.
6989     */
6990    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6991        if (mAccessibilityDelegate != null) {
6992            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6993        } else {
6994            return dispatchPopulateAccessibilityEventInternal(event);
6995        }
6996    }
6997
6998    /**
6999     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7000     *
7001     * Note: Called from the default {@link AccessibilityDelegate}.
7002     *
7003     * @hide
7004     */
7005    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7006        onPopulateAccessibilityEvent(event);
7007        return false;
7008    }
7009
7010    /**
7011     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7012     * giving a chance to this View to populate the accessibility event with its
7013     * text content. While this method is free to modify event
7014     * attributes other than text content, doing so should normally be performed in
7015     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7016     * <p>
7017     * Example: Adding formatted date string to an accessibility event in addition
7018     *          to the text added by the super implementation:
7019     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7020     *     super.onPopulateAccessibilityEvent(event);
7021     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7022     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7023     *         mCurrentDate.getTimeInMillis(), flags);
7024     *     event.getText().add(selectedDateUtterance);
7025     * }</pre>
7026     * <p>
7027     * If an {@link AccessibilityDelegate} has been specified via calling
7028     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7029     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7030     * is responsible for handling this call.
7031     * </p>
7032     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7033     * information to the event, in case the default implementation has basic information to add.
7034     * </p>
7035     *
7036     * @param event The accessibility event which to populate.
7037     *
7038     * @see #sendAccessibilityEvent(int)
7039     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7040     */
7041    @CallSuper
7042    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7043        if (mAccessibilityDelegate != null) {
7044            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7045        } else {
7046            onPopulateAccessibilityEventInternal(event);
7047        }
7048    }
7049
7050    /**
7051     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7052     *
7053     * Note: Called from the default {@link AccessibilityDelegate}.
7054     *
7055     * @hide
7056     */
7057    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7058    }
7059
7060    /**
7061     * Initializes an {@link AccessibilityEvent} with information about
7062     * this View which is the event source. In other words, the source of
7063     * an accessibility event is the view whose state change triggered firing
7064     * the event.
7065     * <p>
7066     * Example: Setting the password property of an event in addition
7067     *          to properties set by the super implementation:
7068     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7069     *     super.onInitializeAccessibilityEvent(event);
7070     *     event.setPassword(true);
7071     * }</pre>
7072     * <p>
7073     * If an {@link AccessibilityDelegate} has been specified via calling
7074     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7075     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7076     * is responsible for handling this call.
7077     * </p>
7078     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7079     * information to the event, in case the default implementation has basic information to add.
7080     * </p>
7081     * @param event The event to initialize.
7082     *
7083     * @see #sendAccessibilityEvent(int)
7084     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7085     */
7086    @CallSuper
7087    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7088        if (mAccessibilityDelegate != null) {
7089            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7090        } else {
7091            onInitializeAccessibilityEventInternal(event);
7092        }
7093    }
7094
7095    /**
7096     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7097     *
7098     * Note: Called from the default {@link AccessibilityDelegate}.
7099     *
7100     * @hide
7101     */
7102    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7103        event.setSource(this);
7104        event.setClassName(getAccessibilityClassName());
7105        event.setPackageName(getContext().getPackageName());
7106        event.setEnabled(isEnabled());
7107        event.setContentDescription(mContentDescription);
7108
7109        switch (event.getEventType()) {
7110            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7111                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7112                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7113                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7114                event.setItemCount(focusablesTempList.size());
7115                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7116                if (mAttachInfo != null) {
7117                    focusablesTempList.clear();
7118                }
7119            } break;
7120            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7121                CharSequence text = getIterableTextForAccessibility();
7122                if (text != null && text.length() > 0) {
7123                    event.setFromIndex(getAccessibilitySelectionStart());
7124                    event.setToIndex(getAccessibilitySelectionEnd());
7125                    event.setItemCount(text.length());
7126                }
7127            } break;
7128        }
7129    }
7130
7131    /**
7132     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7133     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7134     * This method is responsible for obtaining an accessibility node info from a
7135     * pool of reusable instances and calling
7136     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7137     * initialize the former.
7138     * <p>
7139     * Note: The client is responsible for recycling the obtained instance by calling
7140     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7141     * </p>
7142     *
7143     * @return A populated {@link AccessibilityNodeInfo}.
7144     *
7145     * @see AccessibilityNodeInfo
7146     */
7147    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7148        if (mAccessibilityDelegate != null) {
7149            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7150        } else {
7151            return createAccessibilityNodeInfoInternal();
7152        }
7153    }
7154
7155    /**
7156     * @see #createAccessibilityNodeInfo()
7157     *
7158     * @hide
7159     */
7160    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7161        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7162        if (provider != null) {
7163            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7164        } else {
7165            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7166            onInitializeAccessibilityNodeInfo(info);
7167            return info;
7168        }
7169    }
7170
7171    /**
7172     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7173     * The base implementation sets:
7174     * <ul>
7175     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7176     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7177     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7178     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7179     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7180     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7181     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7182     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7183     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7184     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7185     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7186     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7187     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7188     * </ul>
7189     * <p>
7190     * Subclasses should override this method, call the super implementation,
7191     * and set additional attributes.
7192     * </p>
7193     * <p>
7194     * If an {@link AccessibilityDelegate} has been specified via calling
7195     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7196     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7197     * is responsible for handling this call.
7198     * </p>
7199     *
7200     * @param info The instance to initialize.
7201     */
7202    @CallSuper
7203    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7204        if (mAccessibilityDelegate != null) {
7205            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7206        } else {
7207            onInitializeAccessibilityNodeInfoInternal(info);
7208        }
7209    }
7210
7211    /**
7212     * Gets the location of this view in screen coordinates.
7213     *
7214     * @param outRect The output location
7215     * @hide
7216     */
7217    public void getBoundsOnScreen(Rect outRect) {
7218        getBoundsOnScreen(outRect, false);
7219    }
7220
7221    /**
7222     * Gets the location of this view in screen coordinates.
7223     *
7224     * @param outRect The output location
7225     * @param clipToParent Whether to clip child bounds to the parent ones.
7226     * @hide
7227     */
7228    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7229        if (mAttachInfo == null) {
7230            return;
7231        }
7232
7233        RectF position = mAttachInfo.mTmpTransformRect;
7234        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7235
7236        if (!hasIdentityMatrix()) {
7237            getMatrix().mapRect(position);
7238        }
7239
7240        position.offset(mLeft, mTop);
7241
7242        ViewParent parent = mParent;
7243        while (parent instanceof View) {
7244            View parentView = (View) parent;
7245
7246            position.offset(-parentView.mScrollX, -parentView.mScrollY);
7247
7248            if (clipToParent) {
7249                position.left = Math.max(position.left, 0);
7250                position.top = Math.max(position.top, 0);
7251                position.right = Math.min(position.right, parentView.getWidth());
7252                position.bottom = Math.min(position.bottom, parentView.getHeight());
7253            }
7254
7255            if (!parentView.hasIdentityMatrix()) {
7256                parentView.getMatrix().mapRect(position);
7257            }
7258
7259            position.offset(parentView.mLeft, parentView.mTop);
7260
7261            parent = parentView.mParent;
7262        }
7263
7264        if (parent instanceof ViewRootImpl) {
7265            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7266            position.offset(0, -viewRootImpl.mCurScrollY);
7267        }
7268
7269        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7270
7271        outRect.set(Math.round(position.left), Math.round(position.top),
7272                Math.round(position.right), Math.round(position.bottom));
7273    }
7274
7275    /**
7276     * Return the class name of this object to be used for accessibility purposes.
7277     * Subclasses should only override this if they are implementing something that
7278     * should be seen as a completely new class of view when used by accessibility,
7279     * unrelated to the class it is deriving from.  This is used to fill in
7280     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7281     */
7282    public CharSequence getAccessibilityClassName() {
7283        return View.class.getName();
7284    }
7285
7286    /**
7287     * Called when assist structure is being retrieved from a view as part of
7288     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7289     * @param structure Fill in with structured view data.  The default implementation
7290     * fills in all data that can be inferred from the view itself.
7291     */
7292    public void onProvideStructure(ViewStructure structure) {
7293        onProvideStructureForAssistOrAutofill(structure, false);
7294    }
7295
7296    /**
7297     * Called when assist structure is being retrieved from a view as part of an autofill request.
7298     *
7299     * <p>This method already provides most of what's needed for autofill, but should be overridden
7300     * when:
7301     * <ol>
7302     * <li>The view contents does not include PII (Personally Identifiable Information), so it
7303     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7304     * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7305     * {@link ViewStructure#setAutofillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
7306     * </ol>
7307     *
7308     * @param structure Fill in with structured view data. The default implementation
7309     * fills in all data that can be inferred from the view itself.
7310     * @param flags optional flags (currently {@code 0}).
7311     */
7312    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
7313        onProvideStructureForAssistOrAutofill(structure, true);
7314    }
7315
7316    private void setAutofillId(ViewStructure structure) {
7317        // The autofill id needs to be unique, but its value doesn't matter,
7318        // so it's better to reuse the accessibility id to save space.
7319        structure.setAutofillId(getAccessibilityViewId());
7320    }
7321
7322    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7323            boolean forAutofill) {
7324        final int id = mID;
7325        if (id != NO_ID && !isViewIdGenerated(id)) {
7326            String pkg, type, entry;
7327            try {
7328                final Resources res = getResources();
7329                entry = res.getResourceEntryName(id);
7330                type = res.getResourceTypeName(id);
7331                pkg = res.getResourcePackageName(id);
7332            } catch (Resources.NotFoundException e) {
7333                entry = type = pkg = null;
7334            }
7335            structure.setId(id, pkg, type, entry);
7336        } else {
7337            structure.setId(id, null, null, null);
7338        }
7339
7340        if (forAutofill) {
7341            setAutofillId(structure);
7342            final @AutofillType int autofillType = getAutofillType();
7343            // Don't need to fill autofill info if view does not support it.
7344            // For example, only TextViews that are editable support autofill
7345            if (autofillType != AUTOFILL_TYPE_NONE) {
7346                structure.setAutofillType(autofillType);
7347                structure.setAutofillHints(getAutofillHints());
7348                structure.setAutofillValue(getAutofillValue());
7349            }
7350        }
7351
7352        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
7353        if (!hasIdentityMatrix()) {
7354            structure.setTransformation(getMatrix());
7355        }
7356        structure.setElevation(getZ());
7357        structure.setVisibility(getVisibility());
7358        structure.setEnabled(isEnabled());
7359        if (isClickable()) {
7360            structure.setClickable(true);
7361        }
7362        if (isFocusable()) {
7363            structure.setFocusable(true);
7364        }
7365        if (isFocused()) {
7366            structure.setFocused(true);
7367        }
7368        if (isAccessibilityFocused()) {
7369            structure.setAccessibilityFocused(true);
7370        }
7371        if (isSelected()) {
7372            structure.setSelected(true);
7373        }
7374        if (isActivated()) {
7375            structure.setActivated(true);
7376        }
7377        if (isLongClickable()) {
7378            structure.setLongClickable(true);
7379        }
7380        if (this instanceof Checkable) {
7381            structure.setCheckable(true);
7382            if (((Checkable)this).isChecked()) {
7383                structure.setChecked(true);
7384            }
7385        }
7386        if (isOpaque()) {
7387            structure.setOpaque(true);
7388        }
7389        if (isContextClickable()) {
7390            structure.setContextClickable(true);
7391        }
7392        structure.setClassName(getAccessibilityClassName().toString());
7393        structure.setContentDescription(getContentDescription());
7394    }
7395
7396    /**
7397     * Called when assist structure is being retrieved from a view as part of
7398     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7399     * generate additional virtual structure under this view.  The defaullt implementation
7400     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7401     * view's virtual accessibility nodes, if any.  You can override this for a more
7402     * optimal implementation providing this data.
7403     */
7404    public void onProvideVirtualStructure(ViewStructure structure) {
7405        onProvideVirtualStructureForAssistOrAutofill(structure, false);
7406    }
7407
7408    /**
7409     * Called when assist structure is being retrieved from a view as part of an autofill request
7410     * to generate additional virtual structure under this view.
7411     *
7412     * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
7413     * generate this from the view's virtual accessibility nodes, if any. You can override this
7414     * for a more optimal implementation providing this data.
7415     *
7416     * <p>When implementing this method, subclasses must follow the rules below:
7417     *
7418     * <ol>
7419     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7420     * children.
7421     * <li>Call
7422     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7423     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7424     * when the focus inside the view changed.
7425     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7426     * AutofillValue)} when the value of a child changed.
7427     * <li>Call {@link AutofillManager#commit()} when the autofill context
7428     * of the view structure changed and you want the current autofill interaction if such
7429     * to be commited.
7430     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7431     * of the view structure changed and you want the current autofill interaction if such
7432     * to be cancelled.
7433     * </ol>
7434     *
7435     * @param structure Fill in with structured view data.
7436     * @param flags optional flags (currently {@code 0}).
7437     */
7438    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7439        onProvideVirtualStructureForAssistOrAutofill(structure, true);
7440    }
7441
7442    private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure,
7443            boolean forAutofill) {
7444        if (forAutofill) {
7445            setAutofillId(structure);
7446        }
7447        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7448        // this method should take a boolean with the type of request.
7449        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7450        if (provider != null) {
7451            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7452            structure.setChildCount(1);
7453            ViewStructure root = structure.newChild(0);
7454            if (forAutofill) {
7455                setAutofillId(root);
7456            }
7457            populateVirtualStructure(root, provider, info, forAutofill);
7458            info.recycle();
7459        }
7460    }
7461
7462    /**
7463     * Automatically fills the content of this view with the {@code value}.
7464     *
7465     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7466     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7467     * to support the Autofill Framework.
7468     *
7469     * <p>Typically, it is implemented by:
7470     *
7471     * <ol>
7472     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7473     * <li>Passing the actual value to the equivalent setter in the view.
7474     * </ol>
7475     *
7476     * <p>For example, a text-field view would call:
7477     * <pre class="prettyprint">
7478     * CharSequence text = value.getTextValue();
7479     * if (text != null) {
7480     *     setText(text);
7481     * }
7482     * </pre>
7483     *
7484     * <p>If the value is updated asyncronously the next call to
7485     * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
7486     * changed to the autofilled value. If not, the view will not be considered autofilled.
7487     *
7488     * @param value value to be autofilled.
7489     */
7490    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7491    }
7492
7493    /**
7494     * Automatically fills the content of a virtual views.
7495     *
7496     * <p>See {@link #autofill(AutofillValue)} and
7497     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7498     * <p>To indicate that a virtual view was autofilled
7499     * <code>@android:drawable/autofilled_highlight</code> should be drawn over it until the data
7500     * changes.
7501     *
7502     * @param values map of values to be autofilled, keyed by virtual child id.
7503     */
7504    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7505    }
7506
7507    /**
7508     * Describes the autofill type that should be used on calls to
7509     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7510     *
7511     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7512     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7513     */
7514    public @AutofillType int getAutofillType() {
7515        return AUTOFILL_TYPE_NONE;
7516    }
7517
7518    /**
7519     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7520     *
7521     * @return The hints set via the attribute or {@code null} if no hint it set.
7522     *
7523     * @attr ref android.R.styleable#View_autofillHints
7524     */
7525    @ViewDebug.ExportedProperty()
7526    @Nullable public String[] getAutofillHints() {
7527        return mAutofillHints;
7528    }
7529
7530    /**
7531     * @hide
7532     */
7533    public boolean isAutofilled() {
7534        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7535    }
7536
7537    /**
7538     * Gets the {@link View}'s current autofill value.
7539     *
7540     * <p>By default returns {@code null}, but views should override it (and
7541     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7542     * Framework.
7543     */
7544    @Nullable
7545    public AutofillValue getAutofillValue() {
7546        return null;
7547    }
7548
7549    /**
7550     * Gets the mode for determining whether this View is important for autofill.
7551     *
7552     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7553     *
7554     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7555     * {@link #setImportantForAutofill(int)}.
7556     *
7557     * @attr ref android.R.styleable#View_importantForAutofill
7558     */
7559    @ViewDebug.ExportedProperty(mapping = {
7560            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7561            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7562            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
7563    public @AutofillImportance int getImportantForAutofill() {
7564        return (mPrivateFlags3
7565                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7566    }
7567
7568    /**
7569     * Sets the mode for determining whether this View is important for autofill.
7570     *
7571     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7572     *
7573     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7574     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7575     *
7576     * @attr ref android.R.styleable#View_importantForAutofill
7577     */
7578    public void setImportantForAutofill(@AutofillImportance int mode) {
7579        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7580        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7581                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7582    }
7583
7584    /**
7585     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7586     * associated with this View should be included in a {@link ViewStructure} used for
7587     * autofill purposes.
7588     *
7589     * <p>Generally speaking, a view is important for autofill if:
7590     * <ol>
7591     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7592     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7593     * autofill other views.
7594     * <ol>
7595     *
7596     * <p>For example, view containers should typically return {@code false} for performance reasons
7597     * (since the important info is provided by their children), but if the container is actually
7598     * whose children are part of a compound view, it should return {@code true} (and then override
7599     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7600     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7601     * the structure). On the other hand, views representing labels or editable fields should
7602     * typically return {@code true}, but in some cases they could return {@code false} (for
7603     * example, if they're part of a "Captcha" mechanism).
7604     *
7605     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7606     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7607     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7608     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7609     * should use {@link #setImportantForAutofill(int)} instead.
7610     *
7611     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7612     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
7613     * View might be always included.
7614     *
7615     * <p>This decision applies just for the view, not its children - if the view children are not
7616     * important for autofill, the view should override
7617     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7618     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7619     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7620     *
7621     * @return whether the view is considered important for autofill.
7622     *
7623     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7624     * @see #IMPORTANT_FOR_AUTOFILL_YES
7625     * @see #IMPORTANT_FOR_AUTOFILL_NO
7626     */
7627    public final boolean isImportantForAutofill() {
7628        final int flag = getImportantForAutofill();
7629
7630        // First, check if view explicity set it to YES or NO
7631        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
7632            return true;
7633        }
7634        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
7635            return false;
7636        }
7637
7638        // Then use some heuristics to handle AUTO.
7639
7640        // Always include views that have a explicity resource id.
7641        final int id = mID;
7642        if (id != NO_ID && !isViewIdGenerated(id)) {
7643            final Resources res = getResources();
7644            String entry = null;
7645            String pkg = null;
7646            try {
7647                entry = res.getResourceEntryName(id);
7648                pkg = res.getResourcePackageName(id);
7649            } catch (Resources.NotFoundException e) {
7650                // ignore
7651            }
7652            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7653                return true;
7654            }
7655        }
7656
7657        // Otherwise, assume it's not important...
7658        return false;
7659    }
7660
7661    @Nullable
7662    private AutofillManager getAutofillManager() {
7663        return mContext.getSystemService(AutofillManager.class);
7664    }
7665
7666    private boolean isAutofillable() {
7667        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
7668    }
7669
7670    private void populateVirtualStructure(ViewStructure structure,
7671            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) {
7672        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7673                null, null, null);
7674        Rect rect = structure.getTempRect();
7675        info.getBoundsInParent(rect);
7676        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7677        structure.setVisibility(VISIBLE);
7678        structure.setEnabled(info.isEnabled());
7679        if (info.isClickable()) {
7680            structure.setClickable(true);
7681        }
7682        if (info.isFocusable()) {
7683            structure.setFocusable(true);
7684        }
7685        if (info.isFocused()) {
7686            structure.setFocused(true);
7687        }
7688        if (info.isAccessibilityFocused()) {
7689            structure.setAccessibilityFocused(true);
7690        }
7691        if (info.isSelected()) {
7692            structure.setSelected(true);
7693        }
7694        if (info.isLongClickable()) {
7695            structure.setLongClickable(true);
7696        }
7697        if (info.isCheckable()) {
7698            structure.setCheckable(true);
7699            if (info.isChecked()) {
7700                structure.setChecked(true);
7701            }
7702        }
7703        if (info.isContextClickable()) {
7704            structure.setContextClickable(true);
7705        }
7706        CharSequence cname = info.getClassName();
7707        structure.setClassName(cname != null ? cname.toString() : null);
7708        structure.setContentDescription(info.getContentDescription());
7709        if (!forAutofill && (info.getText() != null || info.getError() != null)) {
7710            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7711            // just set sanitized values (like text coming from resource files), rather than not
7712            // setting it at all.
7713            structure.setText(info.getText(), info.getTextSelectionStart(),
7714                    info.getTextSelectionEnd());
7715        }
7716        final int NCHILDREN = info.getChildCount();
7717        if (NCHILDREN > 0) {
7718            structure.setChildCount(NCHILDREN);
7719            for (int i=0; i<NCHILDREN; i++) {
7720                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7721                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7722                ViewStructure child = structure.newChild(i);
7723                if (forAutofill) {
7724                    // TODO(b/33197203): add CTS test to autofill virtual children based on
7725                    // Accessibility API.
7726                    child.setAutofillId(structure, i);
7727                }
7728                populateVirtualStructure(child, provider, cinfo, forAutofill);
7729                cinfo.recycle();
7730            }
7731        }
7732    }
7733
7734    /**
7735     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7736     * implementation calls {@link #onProvideStructure} and
7737     * {@link #onProvideVirtualStructure}.
7738     */
7739    public void dispatchProvideStructure(ViewStructure structure) {
7740        dispatchProvideStructureForAssistOrAutofill(structure, false);
7741    }
7742
7743    /**
7744     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7745     *
7746     * <p>The structure must be filled according to the request type, which is set in the
7747     * {@code flags} parameter - see the documentation on each flag for more details.
7748     *
7749     * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
7750     * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7751     *
7752     * @param structure Fill in with structured view data.
7753     * @param flags optional flags (currently {@code 0}).
7754     */
7755    public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
7756        dispatchProvideStructureForAssistOrAutofill(structure, true);
7757    }
7758
7759    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7760            boolean forAutofill) {
7761        boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
7762        if (!blocked) {
7763            if (forAutofill) {
7764                setAutofillId(structure);
7765                // NOTE: flags are not currently supported, hence 0
7766                onProvideAutofillStructure(structure, 0);
7767                onProvideAutofillVirtualStructure(structure, 0);
7768            } else {
7769                onProvideStructure(structure);
7770                onProvideVirtualStructure(structure);
7771            }
7772        } else {
7773            structure.setClassName(getAccessibilityClassName().toString());
7774            structure.setAssistBlocked(true);
7775        }
7776    }
7777
7778    /**
7779     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7780     *
7781     * Note: Called from the default {@link AccessibilityDelegate}.
7782     *
7783     * @hide
7784     */
7785    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7786        if (mAttachInfo == null) {
7787            return;
7788        }
7789
7790        Rect bounds = mAttachInfo.mTmpInvalRect;
7791
7792        getDrawingRect(bounds);
7793        info.setBoundsInParent(bounds);
7794
7795        getBoundsOnScreen(bounds, true);
7796        info.setBoundsInScreen(bounds);
7797
7798        ViewParent parent = getParentForAccessibility();
7799        if (parent instanceof View) {
7800            info.setParent((View) parent);
7801        }
7802
7803        if (mID != View.NO_ID) {
7804            View rootView = getRootView();
7805            if (rootView == null) {
7806                rootView = this;
7807            }
7808
7809            View label = rootView.findLabelForView(this, mID);
7810            if (label != null) {
7811                info.setLabeledBy(label);
7812            }
7813
7814            if ((mAttachInfo.mAccessibilityFetchFlags
7815                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7816                    && Resources.resourceHasPackage(mID)) {
7817                try {
7818                    String viewId = getResources().getResourceName(mID);
7819                    info.setViewIdResourceName(viewId);
7820                } catch (Resources.NotFoundException nfe) {
7821                    /* ignore */
7822                }
7823            }
7824        }
7825
7826        if (mLabelForId != View.NO_ID) {
7827            View rootView = getRootView();
7828            if (rootView == null) {
7829                rootView = this;
7830            }
7831            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7832            if (labeled != null) {
7833                info.setLabelFor(labeled);
7834            }
7835        }
7836
7837        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7838            View rootView = getRootView();
7839            if (rootView == null) {
7840                rootView = this;
7841            }
7842            View next = rootView.findViewInsideOutShouldExist(this,
7843                    mAccessibilityTraversalBeforeId);
7844            if (next != null && next.includeForAccessibility()) {
7845                info.setTraversalBefore(next);
7846            }
7847        }
7848
7849        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7850            View rootView = getRootView();
7851            if (rootView == null) {
7852                rootView = this;
7853            }
7854            View next = rootView.findViewInsideOutShouldExist(this,
7855                    mAccessibilityTraversalAfterId);
7856            if (next != null && next.includeForAccessibility()) {
7857                info.setTraversalAfter(next);
7858            }
7859        }
7860
7861        info.setVisibleToUser(isVisibleToUser());
7862
7863        info.setImportantForAccessibility(isImportantForAccessibility());
7864        info.setPackageName(mContext.getPackageName());
7865        info.setClassName(getAccessibilityClassName());
7866        info.setContentDescription(getContentDescription());
7867
7868        info.setEnabled(isEnabled());
7869        info.setClickable(isClickable());
7870        info.setFocusable(isFocusable());
7871        info.setFocused(isFocused());
7872        info.setAccessibilityFocused(isAccessibilityFocused());
7873        info.setSelected(isSelected());
7874        info.setLongClickable(isLongClickable());
7875        info.setContextClickable(isContextClickable());
7876        info.setLiveRegion(getAccessibilityLiveRegion());
7877
7878        // TODO: These make sense only if we are in an AdapterView but all
7879        // views can be selected. Maybe from accessibility perspective
7880        // we should report as selectable view in an AdapterView.
7881        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7882        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7883
7884        if (isFocusable()) {
7885            if (isFocused()) {
7886                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7887            } else {
7888                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7889            }
7890        }
7891
7892        if (!isAccessibilityFocused()) {
7893            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7894        } else {
7895            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7896        }
7897
7898        if (isClickable() && isEnabled()) {
7899            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7900        }
7901
7902        if (isLongClickable() && isEnabled()) {
7903            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7904        }
7905
7906        if (isContextClickable() && isEnabled()) {
7907            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7908        }
7909
7910        CharSequence text = getIterableTextForAccessibility();
7911        if (text != null && text.length() > 0) {
7912            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7913
7914            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7915            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7916            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7917            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7918                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7919                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7920        }
7921
7922        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7923        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7924    }
7925
7926    /**
7927     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7928     * additional data.
7929     * <p>
7930     * This method only needs overloading if the node is marked as having extra data available.
7931     * </p>
7932     *
7933     * @param info The info to which to add the extra data. Never {@code null}.
7934     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7935     *                     extra data should be added to the {@link Bundle} returned by
7936     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7937     *                     {@code null}.
7938     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7939     *                  {@code null} if the service provided no arguments.
7940     *
7941     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
7942     */
7943    public void addExtraDataToAccessibilityNodeInfo(
7944            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7945            @Nullable Bundle arguments) {
7946    }
7947
7948    /**
7949     * Determine the order in which this view will be drawn relative to its siblings for a11y
7950     *
7951     * @param info The info whose drawing order should be populated
7952     */
7953    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7954        /*
7955         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7956         * drawing order may not be well-defined, and some Views with custom drawing order may
7957         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7958         */
7959        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7960            info.setDrawingOrder(0);
7961            return;
7962        }
7963        int drawingOrderInParent = 1;
7964        // Iterate up the hierarchy if parents are not important for a11y
7965        View viewAtDrawingLevel = this;
7966        final ViewParent parent = getParentForAccessibility();
7967        while (viewAtDrawingLevel != parent) {
7968            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7969            if (!(currentParent instanceof ViewGroup)) {
7970                // Should only happen for the Decor
7971                drawingOrderInParent = 0;
7972                break;
7973            } else {
7974                final ViewGroup parentGroup = (ViewGroup) currentParent;
7975                final int childCount = parentGroup.getChildCount();
7976                if (childCount > 1) {
7977                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7978                    if (preorderedList != null) {
7979                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7980                        for (int i = 0; i < childDrawIndex; i++) {
7981                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7982                        }
7983                    } else {
7984                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7985                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7986                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7987                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7988                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7989                        if (childDrawIndex != 0) {
7990                            for (int i = 0; i < numChildrenToIterate; i++) {
7991                                final int otherDrawIndex = (customOrder ?
7992                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7993                                if (otherDrawIndex < childDrawIndex) {
7994                                    drawingOrderInParent +=
7995                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7996                                }
7997                            }
7998                        }
7999                    }
8000                }
8001            }
8002            viewAtDrawingLevel = (View) currentParent;
8003        }
8004        info.setDrawingOrder(drawingOrderInParent);
8005    }
8006
8007    private static int numViewsForAccessibility(View view) {
8008        if (view != null) {
8009            if (view.includeForAccessibility()) {
8010                return 1;
8011            } else if (view instanceof ViewGroup) {
8012                return ((ViewGroup) view).getNumChildrenForAccessibility();
8013            }
8014        }
8015        return 0;
8016    }
8017
8018    private View findLabelForView(View view, int labeledId) {
8019        if (mMatchLabelForPredicate == null) {
8020            mMatchLabelForPredicate = new MatchLabelForPredicate();
8021        }
8022        mMatchLabelForPredicate.mLabeledId = labeledId;
8023        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8024    }
8025
8026    /**
8027     * Computes whether this view is visible to the user. Such a view is
8028     * attached, visible, all its predecessors are visible, it is not clipped
8029     * entirely by its predecessors, and has an alpha greater than zero.
8030     *
8031     * @return Whether the view is visible on the screen.
8032     *
8033     * @hide
8034     */
8035    protected boolean isVisibleToUser() {
8036        return isVisibleToUser(null);
8037    }
8038
8039    /**
8040     * Computes whether the given portion of this view is visible to the user.
8041     * Such a view is attached, visible, all its predecessors are visible,
8042     * has an alpha greater than zero, and the specified portion is not
8043     * clipped entirely by its predecessors.
8044     *
8045     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8046     *                    <code>null</code>, and the entire view will be tested in this case.
8047     *                    When <code>true</code> is returned by the function, the actual visible
8048     *                    region will be stored in this parameter; that is, if boundInView is fully
8049     *                    contained within the view, no modification will be made, otherwise regions
8050     *                    outside of the visible area of the view will be clipped.
8051     *
8052     * @return Whether the specified portion of the view is visible on the screen.
8053     *
8054     * @hide
8055     */
8056    protected boolean isVisibleToUser(Rect boundInView) {
8057        if (mAttachInfo != null) {
8058            // Attached to invisible window means this view is not visible.
8059            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8060                return false;
8061            }
8062            // An invisible predecessor or one with alpha zero means
8063            // that this view is not visible to the user.
8064            Object current = this;
8065            while (current instanceof View) {
8066                View view = (View) current;
8067                // We have attach info so this view is attached and there is no
8068                // need to check whether we reach to ViewRootImpl on the way up.
8069                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8070                        view.getVisibility() != VISIBLE) {
8071                    return false;
8072                }
8073                current = view.mParent;
8074            }
8075            // Check if the view is entirely covered by its predecessors.
8076            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8077            Point offset = mAttachInfo.mPoint;
8078            if (!getGlobalVisibleRect(visibleRect, offset)) {
8079                return false;
8080            }
8081            // Check if the visible portion intersects the rectangle of interest.
8082            if (boundInView != null) {
8083                visibleRect.offset(-offset.x, -offset.y);
8084                return boundInView.intersect(visibleRect);
8085            }
8086            return true;
8087        }
8088        return false;
8089    }
8090
8091    /**
8092     * Returns the delegate for implementing accessibility support via
8093     * composition. For more details see {@link AccessibilityDelegate}.
8094     *
8095     * @return The delegate, or null if none set.
8096     *
8097     * @hide
8098     */
8099    public AccessibilityDelegate getAccessibilityDelegate() {
8100        return mAccessibilityDelegate;
8101    }
8102
8103    /**
8104     * Sets a delegate for implementing accessibility support via composition
8105     * (as opposed to inheritance). For more details, see
8106     * {@link AccessibilityDelegate}.
8107     * <p>
8108     * <strong>Note:</strong> On platform versions prior to
8109     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8110     * views in the {@code android.widget.*} package are called <i>before</i>
8111     * host methods. This prevents certain properties such as class name from
8112     * being modified by overriding
8113     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8114     * as any changes will be overwritten by the host class.
8115     * <p>
8116     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8117     * methods are called <i>after</i> host methods, which all properties to be
8118     * modified without being overwritten by the host class.
8119     *
8120     * @param delegate the object to which accessibility method calls should be
8121     *                 delegated
8122     * @see AccessibilityDelegate
8123     */
8124    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8125        mAccessibilityDelegate = delegate;
8126    }
8127
8128    /**
8129     * Gets the provider for managing a virtual view hierarchy rooted at this View
8130     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8131     * that explore the window content.
8132     * <p>
8133     * If this method returns an instance, this instance is responsible for managing
8134     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8135     * View including the one representing the View itself. Similarly the returned
8136     * instance is responsible for performing accessibility actions on any virtual
8137     * view or the root view itself.
8138     * </p>
8139     * <p>
8140     * If an {@link AccessibilityDelegate} has been specified via calling
8141     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8142     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8143     * is responsible for handling this call.
8144     * </p>
8145     *
8146     * @return The provider.
8147     *
8148     * @see AccessibilityNodeProvider
8149     */
8150    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8151        if (mAccessibilityDelegate != null) {
8152            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8153        } else {
8154            return null;
8155        }
8156    }
8157
8158    /**
8159     * Gets the unique identifier of this view on the screen for accessibility purposes.
8160     *
8161     * @return The view accessibility id.
8162     *
8163     * @hide
8164     */
8165    public int getAccessibilityViewId() {
8166        if (mAccessibilityViewId == NO_ID) {
8167            mAccessibilityViewId = mContext.getNextAccessibilityId();
8168        }
8169        return mAccessibilityViewId;
8170    }
8171
8172    /**
8173     * Gets the unique identifier of the window in which this View reseides.
8174     *
8175     * @return The window accessibility id.
8176     *
8177     * @hide
8178     */
8179    public int getAccessibilityWindowId() {
8180        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8181                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8182    }
8183
8184    /**
8185     * Returns the {@link View}'s content description.
8186     * <p>
8187     * <strong>Note:</strong> Do not override this method, as it will have no
8188     * effect on the content description presented to accessibility services.
8189     * You must call {@link #setContentDescription(CharSequence)} to modify the
8190     * content description.
8191     *
8192     * @return the content description
8193     * @see #setContentDescription(CharSequence)
8194     * @attr ref android.R.styleable#View_contentDescription
8195     */
8196    @ViewDebug.ExportedProperty(category = "accessibility")
8197    public CharSequence getContentDescription() {
8198        return mContentDescription;
8199    }
8200
8201    /**
8202     * Sets the {@link View}'s content description.
8203     * <p>
8204     * A content description briefly describes the view and is primarily used
8205     * for accessibility support to determine how a view should be presented to
8206     * the user. In the case of a view with no textual representation, such as
8207     * {@link android.widget.ImageButton}, a useful content description
8208     * explains what the view does. For example, an image button with a phone
8209     * icon that is used to place a call may use "Call" as its content
8210     * description. An image of a floppy disk that is used to save a file may
8211     * use "Save".
8212     *
8213     * @param contentDescription The content description.
8214     * @see #getContentDescription()
8215     * @attr ref android.R.styleable#View_contentDescription
8216     */
8217    @RemotableViewMethod
8218    public void setContentDescription(CharSequence contentDescription) {
8219        if (mContentDescription == null) {
8220            if (contentDescription == null) {
8221                return;
8222            }
8223        } else if (mContentDescription.equals(contentDescription)) {
8224            return;
8225        }
8226        mContentDescription = contentDescription;
8227        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8228        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8229            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8230            notifySubtreeAccessibilityStateChangedIfNeeded();
8231        } else {
8232            notifyViewAccessibilityStateChangedIfNeeded(
8233                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8234        }
8235    }
8236
8237    /**
8238     * Sets the id of a view before which this one is visited in accessibility traversal.
8239     * A screen-reader must visit the content of this view before the content of the one
8240     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8241     * will traverse the entire content of B before traversing the entire content of A,
8242     * regardles of what traversal strategy it is using.
8243     * <p>
8244     * Views that do not have specified before/after relationships are traversed in order
8245     * determined by the screen-reader.
8246     * </p>
8247     * <p>
8248     * Setting that this view is before a view that is not important for accessibility
8249     * or if this view is not important for accessibility will have no effect as the
8250     * screen-reader is not aware of unimportant views.
8251     * </p>
8252     *
8253     * @param beforeId The id of a view this one precedes in accessibility traversal.
8254     *
8255     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8256     *
8257     * @see #setImportantForAccessibility(int)
8258     */
8259    @RemotableViewMethod
8260    public void setAccessibilityTraversalBefore(int beforeId) {
8261        if (mAccessibilityTraversalBeforeId == beforeId) {
8262            return;
8263        }
8264        mAccessibilityTraversalBeforeId = beforeId;
8265        notifyViewAccessibilityStateChangedIfNeeded(
8266                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8267    }
8268
8269    /**
8270     * Gets the id of a view before which this one is visited in accessibility traversal.
8271     *
8272     * @return The id of a view this one precedes in accessibility traversal if
8273     *         specified, otherwise {@link #NO_ID}.
8274     *
8275     * @see #setAccessibilityTraversalBefore(int)
8276     */
8277    public int getAccessibilityTraversalBefore() {
8278        return mAccessibilityTraversalBeforeId;
8279    }
8280
8281    /**
8282     * Sets the id of a view after which this one is visited in accessibility traversal.
8283     * A screen-reader must visit the content of the other view before the content of this
8284     * one. For example, if view B is set to be after view A, then a screen-reader
8285     * will traverse the entire content of A before traversing the entire content of B,
8286     * regardles of what traversal strategy it is using.
8287     * <p>
8288     * Views that do not have specified before/after relationships are traversed in order
8289     * determined by the screen-reader.
8290     * </p>
8291     * <p>
8292     * Setting that this view is after a view that is not important for accessibility
8293     * or if this view is not important for accessibility will have no effect as the
8294     * screen-reader is not aware of unimportant views.
8295     * </p>
8296     *
8297     * @param afterId The id of a view this one succedees in accessibility traversal.
8298     *
8299     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8300     *
8301     * @see #setImportantForAccessibility(int)
8302     */
8303    @RemotableViewMethod
8304    public void setAccessibilityTraversalAfter(int afterId) {
8305        if (mAccessibilityTraversalAfterId == afterId) {
8306            return;
8307        }
8308        mAccessibilityTraversalAfterId = afterId;
8309        notifyViewAccessibilityStateChangedIfNeeded(
8310                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8311    }
8312
8313    /**
8314     * Gets the id of a view after which this one is visited in accessibility traversal.
8315     *
8316     * @return The id of a view this one succeedes in accessibility traversal if
8317     *         specified, otherwise {@link #NO_ID}.
8318     *
8319     * @see #setAccessibilityTraversalAfter(int)
8320     */
8321    public int getAccessibilityTraversalAfter() {
8322        return mAccessibilityTraversalAfterId;
8323    }
8324
8325    /**
8326     * Gets the id of a view for which this view serves as a label for
8327     * accessibility purposes.
8328     *
8329     * @return The labeled view id.
8330     */
8331    @ViewDebug.ExportedProperty(category = "accessibility")
8332    public int getLabelFor() {
8333        return mLabelForId;
8334    }
8335
8336    /**
8337     * Sets the id of a view for which this view serves as a label for
8338     * accessibility purposes.
8339     *
8340     * @param id The labeled view id.
8341     */
8342    @RemotableViewMethod
8343    public void setLabelFor(@IdRes int id) {
8344        if (mLabelForId == id) {
8345            return;
8346        }
8347        mLabelForId = id;
8348        if (mLabelForId != View.NO_ID
8349                && mID == View.NO_ID) {
8350            mID = generateViewId();
8351        }
8352        notifyViewAccessibilityStateChangedIfNeeded(
8353                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8354    }
8355
8356    /**
8357     * Invoked whenever this view loses focus, either by losing window focus or by losing
8358     * focus within its window. This method can be used to clear any state tied to the
8359     * focus. For instance, if a button is held pressed with the trackball and the window
8360     * loses focus, this method can be used to cancel the press.
8361     *
8362     * Subclasses of View overriding this method should always call super.onFocusLost().
8363     *
8364     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8365     * @see #onWindowFocusChanged(boolean)
8366     *
8367     * @hide pending API council approval
8368     */
8369    @CallSuper
8370    protected void onFocusLost() {
8371        resetPressedState();
8372    }
8373
8374    private void resetPressedState() {
8375        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8376            return;
8377        }
8378
8379        if (isPressed()) {
8380            setPressed(false);
8381
8382            if (!mHasPerformedLongPress) {
8383                removeLongPressCallback();
8384            }
8385        }
8386    }
8387
8388    /**
8389     * Returns true if this view has focus
8390     *
8391     * @return True if this view has focus, false otherwise.
8392     */
8393    @ViewDebug.ExportedProperty(category = "focus")
8394    public boolean isFocused() {
8395        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8396    }
8397
8398    /**
8399     * Find the view in the hierarchy rooted at this view that currently has
8400     * focus.
8401     *
8402     * @return The view that currently has focus, or null if no focused view can
8403     *         be found.
8404     */
8405    public View findFocus() {
8406        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8407    }
8408
8409    /**
8410     * Indicates whether this view is one of the set of scrollable containers in
8411     * its window.
8412     *
8413     * @return whether this view is one of the set of scrollable containers in
8414     * its window
8415     *
8416     * @attr ref android.R.styleable#View_isScrollContainer
8417     */
8418    public boolean isScrollContainer() {
8419        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8420    }
8421
8422    /**
8423     * Change whether this view is one of the set of scrollable containers in
8424     * its window.  This will be used to determine whether the window can
8425     * resize or must pan when a soft input area is open -- scrollable
8426     * containers allow the window to use resize mode since the container
8427     * will appropriately shrink.
8428     *
8429     * @attr ref android.R.styleable#View_isScrollContainer
8430     */
8431    public void setScrollContainer(boolean isScrollContainer) {
8432        if (isScrollContainer) {
8433            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8434                mAttachInfo.mScrollContainers.add(this);
8435                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8436            }
8437            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8438        } else {
8439            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8440                mAttachInfo.mScrollContainers.remove(this);
8441            }
8442            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8443        }
8444    }
8445
8446    /**
8447     * Returns the quality of the drawing cache.
8448     *
8449     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8450     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8451     *
8452     * @see #setDrawingCacheQuality(int)
8453     * @see #setDrawingCacheEnabled(boolean)
8454     * @see #isDrawingCacheEnabled()
8455     *
8456     * @attr ref android.R.styleable#View_drawingCacheQuality
8457     */
8458    @DrawingCacheQuality
8459    public int getDrawingCacheQuality() {
8460        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8461    }
8462
8463    /**
8464     * Set the drawing cache quality of this view. This value is used only when the
8465     * drawing cache is enabled
8466     *
8467     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8468     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8469     *
8470     * @see #getDrawingCacheQuality()
8471     * @see #setDrawingCacheEnabled(boolean)
8472     * @see #isDrawingCacheEnabled()
8473     *
8474     * @attr ref android.R.styleable#View_drawingCacheQuality
8475     */
8476    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8477        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8478    }
8479
8480    /**
8481     * Returns whether the screen should remain on, corresponding to the current
8482     * value of {@link #KEEP_SCREEN_ON}.
8483     *
8484     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8485     *
8486     * @see #setKeepScreenOn(boolean)
8487     *
8488     * @attr ref android.R.styleable#View_keepScreenOn
8489     */
8490    public boolean getKeepScreenOn() {
8491        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8492    }
8493
8494    /**
8495     * Controls whether the screen should remain on, modifying the
8496     * value of {@link #KEEP_SCREEN_ON}.
8497     *
8498     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8499     *
8500     * @see #getKeepScreenOn()
8501     *
8502     * @attr ref android.R.styleable#View_keepScreenOn
8503     */
8504    public void setKeepScreenOn(boolean keepScreenOn) {
8505        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8506    }
8507
8508    /**
8509     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8510     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8511     *
8512     * @attr ref android.R.styleable#View_nextFocusLeft
8513     */
8514    public int getNextFocusLeftId() {
8515        return mNextFocusLeftId;
8516    }
8517
8518    /**
8519     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8520     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8521     * decide automatically.
8522     *
8523     * @attr ref android.R.styleable#View_nextFocusLeft
8524     */
8525    public void setNextFocusLeftId(int nextFocusLeftId) {
8526        mNextFocusLeftId = nextFocusLeftId;
8527    }
8528
8529    /**
8530     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8531     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8532     *
8533     * @attr ref android.R.styleable#View_nextFocusRight
8534     */
8535    public int getNextFocusRightId() {
8536        return mNextFocusRightId;
8537    }
8538
8539    /**
8540     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8541     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8542     * decide automatically.
8543     *
8544     * @attr ref android.R.styleable#View_nextFocusRight
8545     */
8546    public void setNextFocusRightId(int nextFocusRightId) {
8547        mNextFocusRightId = nextFocusRightId;
8548    }
8549
8550    /**
8551     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8552     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8553     *
8554     * @attr ref android.R.styleable#View_nextFocusUp
8555     */
8556    public int getNextFocusUpId() {
8557        return mNextFocusUpId;
8558    }
8559
8560    /**
8561     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8562     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8563     * decide automatically.
8564     *
8565     * @attr ref android.R.styleable#View_nextFocusUp
8566     */
8567    public void setNextFocusUpId(int nextFocusUpId) {
8568        mNextFocusUpId = nextFocusUpId;
8569    }
8570
8571    /**
8572     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8573     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8574     *
8575     * @attr ref android.R.styleable#View_nextFocusDown
8576     */
8577    public int getNextFocusDownId() {
8578        return mNextFocusDownId;
8579    }
8580
8581    /**
8582     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8583     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8584     * decide automatically.
8585     *
8586     * @attr ref android.R.styleable#View_nextFocusDown
8587     */
8588    public void setNextFocusDownId(int nextFocusDownId) {
8589        mNextFocusDownId = nextFocusDownId;
8590    }
8591
8592    /**
8593     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8594     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8595     *
8596     * @attr ref android.R.styleable#View_nextFocusForward
8597     */
8598    public int getNextFocusForwardId() {
8599        return mNextFocusForwardId;
8600    }
8601
8602    /**
8603     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8604     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8605     * decide automatically.
8606     *
8607     * @attr ref android.R.styleable#View_nextFocusForward
8608     */
8609    public void setNextFocusForwardId(int nextFocusForwardId) {
8610        mNextFocusForwardId = nextFocusForwardId;
8611    }
8612
8613    /**
8614     * Gets the id of the root of the next keyboard navigation cluster.
8615     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8616     * decide automatically.
8617     *
8618     * @attr ref android.R.styleable#View_nextClusterForward
8619     */
8620    public int getNextClusterForwardId() {
8621        return mNextClusterForwardId;
8622    }
8623
8624    /**
8625     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8626     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8627     * decide automatically.
8628     *
8629     * @attr ref android.R.styleable#View_nextClusterForward
8630     */
8631    public void setNextClusterForwardId(int nextClusterForwardId) {
8632        mNextClusterForwardId = nextClusterForwardId;
8633    }
8634
8635    /**
8636     * Returns the visibility of this view and all of its ancestors
8637     *
8638     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8639     */
8640    public boolean isShown() {
8641        View current = this;
8642        //noinspection ConstantConditions
8643        do {
8644            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8645                return false;
8646            }
8647            ViewParent parent = current.mParent;
8648            if (parent == null) {
8649                return false; // We are not attached to the view root
8650            }
8651            if (!(parent instanceof View)) {
8652                return true;
8653            }
8654            current = (View) parent;
8655        } while (current != null);
8656
8657        return false;
8658    }
8659
8660    /**
8661     * Called by the view hierarchy when the content insets for a window have
8662     * changed, to allow it to adjust its content to fit within those windows.
8663     * The content insets tell you the space that the status bar, input method,
8664     * and other system windows infringe on the application's window.
8665     *
8666     * <p>You do not normally need to deal with this function, since the default
8667     * window decoration given to applications takes care of applying it to the
8668     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8669     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8670     * and your content can be placed under those system elements.  You can then
8671     * use this method within your view hierarchy if you have parts of your UI
8672     * which you would like to ensure are not being covered.
8673     *
8674     * <p>The default implementation of this method simply applies the content
8675     * insets to the view's padding, consuming that content (modifying the
8676     * insets to be 0), and returning true.  This behavior is off by default, but can
8677     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8678     *
8679     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8680     * insets object is propagated down the hierarchy, so any changes made to it will
8681     * be seen by all following views (including potentially ones above in
8682     * the hierarchy since this is a depth-first traversal).  The first view
8683     * that returns true will abort the entire traversal.
8684     *
8685     * <p>The default implementation works well for a situation where it is
8686     * used with a container that covers the entire window, allowing it to
8687     * apply the appropriate insets to its content on all edges.  If you need
8688     * a more complicated layout (such as two different views fitting system
8689     * windows, one on the top of the window, and one on the bottom),
8690     * you can override the method and handle the insets however you would like.
8691     * Note that the insets provided by the framework are always relative to the
8692     * far edges of the window, not accounting for the location of the called view
8693     * within that window.  (In fact when this method is called you do not yet know
8694     * where the layout will place the view, as it is done before layout happens.)
8695     *
8696     * <p>Note: unlike many View methods, there is no dispatch phase to this
8697     * call.  If you are overriding it in a ViewGroup and want to allow the
8698     * call to continue to your children, you must be sure to call the super
8699     * implementation.
8700     *
8701     * <p>Here is a sample layout that makes use of fitting system windows
8702     * to have controls for a video view placed inside of the window decorations
8703     * that it hides and shows.  This can be used with code like the second
8704     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8705     *
8706     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8707     *
8708     * @param insets Current content insets of the window.  Prior to
8709     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8710     * the insets or else you and Android will be unhappy.
8711     *
8712     * @return {@code true} if this view applied the insets and it should not
8713     * continue propagating further down the hierarchy, {@code false} otherwise.
8714     * @see #getFitsSystemWindows()
8715     * @see #setFitsSystemWindows(boolean)
8716     * @see #setSystemUiVisibility(int)
8717     *
8718     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8719     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8720     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8721     * to implement handling their own insets.
8722     */
8723    @Deprecated
8724    protected boolean fitSystemWindows(Rect insets) {
8725        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8726            if (insets == null) {
8727                // Null insets by definition have already been consumed.
8728                // This call cannot apply insets since there are none to apply,
8729                // so return false.
8730                return false;
8731            }
8732            // If we're not in the process of dispatching the newer apply insets call,
8733            // that means we're not in the compatibility path. Dispatch into the newer
8734            // apply insets path and take things from there.
8735            try {
8736                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8737                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8738            } finally {
8739                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8740            }
8741        } else {
8742            // We're being called from the newer apply insets path.
8743            // Perform the standard fallback behavior.
8744            return fitSystemWindowsInt(insets);
8745        }
8746    }
8747
8748    private boolean fitSystemWindowsInt(Rect insets) {
8749        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8750            mUserPaddingStart = UNDEFINED_PADDING;
8751            mUserPaddingEnd = UNDEFINED_PADDING;
8752            Rect localInsets = sThreadLocal.get();
8753            if (localInsets == null) {
8754                localInsets = new Rect();
8755                sThreadLocal.set(localInsets);
8756            }
8757            boolean res = computeFitSystemWindows(insets, localInsets);
8758            mUserPaddingLeftInitial = localInsets.left;
8759            mUserPaddingRightInitial = localInsets.right;
8760            internalSetPadding(localInsets.left, localInsets.top,
8761                    localInsets.right, localInsets.bottom);
8762            return res;
8763        }
8764        return false;
8765    }
8766
8767    /**
8768     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8769     *
8770     * <p>This method should be overridden by views that wish to apply a policy different from or
8771     * in addition to the default behavior. Clients that wish to force a view subtree
8772     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8773     *
8774     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8775     * it will be called during dispatch instead of this method. The listener may optionally
8776     * call this method from its own implementation if it wishes to apply the view's default
8777     * insets policy in addition to its own.</p>
8778     *
8779     * <p>Implementations of this method should either return the insets parameter unchanged
8780     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8781     * that this view applied itself. This allows new inset types added in future platform
8782     * versions to pass through existing implementations unchanged without being erroneously
8783     * consumed.</p>
8784     *
8785     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8786     * property is set then the view will consume the system window insets and apply them
8787     * as padding for the view.</p>
8788     *
8789     * @param insets Insets to apply
8790     * @return The supplied insets with any applied insets consumed
8791     */
8792    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8793        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8794            // We weren't called from within a direct call to fitSystemWindows,
8795            // call into it as a fallback in case we're in a class that overrides it
8796            // and has logic to perform.
8797            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8798                return insets.consumeSystemWindowInsets();
8799            }
8800        } else {
8801            // We were called from within a direct call to fitSystemWindows.
8802            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8803                return insets.consumeSystemWindowInsets();
8804            }
8805        }
8806        return insets;
8807    }
8808
8809    /**
8810     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8811     * window insets to this view. The listener's
8812     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8813     * method will be called instead of the view's
8814     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8815     *
8816     * @param listener Listener to set
8817     *
8818     * @see #onApplyWindowInsets(WindowInsets)
8819     */
8820    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8821        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8822    }
8823
8824    /**
8825     * Request to apply the given window insets to this view or another view in its subtree.
8826     *
8827     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8828     * obscured by window decorations or overlays. This can include the status and navigation bars,
8829     * action bars, input methods and more. New inset categories may be added in the future.
8830     * The method returns the insets provided minus any that were applied by this view or its
8831     * children.</p>
8832     *
8833     * <p>Clients wishing to provide custom behavior should override the
8834     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8835     * {@link OnApplyWindowInsetsListener} via the
8836     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8837     * method.</p>
8838     *
8839     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8840     * </p>
8841     *
8842     * @param insets Insets to apply
8843     * @return The provided insets minus the insets that were consumed
8844     */
8845    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8846        try {
8847            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8848            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8849                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8850            } else {
8851                return onApplyWindowInsets(insets);
8852            }
8853        } finally {
8854            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8855        }
8856    }
8857
8858    /**
8859     * Compute the view's coordinate within the surface.
8860     *
8861     * <p>Computes the coordinates of this view in its surface. The argument
8862     * must be an array of two integers. After the method returns, the array
8863     * contains the x and y location in that order.</p>
8864     * @hide
8865     * @param location an array of two integers in which to hold the coordinates
8866     */
8867    public void getLocationInSurface(@Size(2) int[] location) {
8868        getLocationInWindow(location);
8869        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8870            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8871            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8872        }
8873    }
8874
8875    /**
8876     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8877     * only available if the view is attached.
8878     *
8879     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8880     */
8881    public WindowInsets getRootWindowInsets() {
8882        if (mAttachInfo != null) {
8883            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8884        }
8885        return null;
8886    }
8887
8888    /**
8889     * @hide Compute the insets that should be consumed by this view and the ones
8890     * that should propagate to those under it.
8891     */
8892    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8893        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8894                || mAttachInfo == null
8895                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8896                        && !mAttachInfo.mOverscanRequested)) {
8897            outLocalInsets.set(inoutInsets);
8898            inoutInsets.set(0, 0, 0, 0);
8899            return true;
8900        } else {
8901            // The application wants to take care of fitting system window for
8902            // the content...  however we still need to take care of any overscan here.
8903            final Rect overscan = mAttachInfo.mOverscanInsets;
8904            outLocalInsets.set(overscan);
8905            inoutInsets.left -= overscan.left;
8906            inoutInsets.top -= overscan.top;
8907            inoutInsets.right -= overscan.right;
8908            inoutInsets.bottom -= overscan.bottom;
8909            return false;
8910        }
8911    }
8912
8913    /**
8914     * Compute insets that should be consumed by this view and the ones that should propagate
8915     * to those under it.
8916     *
8917     * @param in Insets currently being processed by this View, likely received as a parameter
8918     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8919     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8920     *                       by this view
8921     * @return Insets that should be passed along to views under this one
8922     */
8923    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8924        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8925                || mAttachInfo == null
8926                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8927            outLocalInsets.set(in.getSystemWindowInsets());
8928            return in.consumeSystemWindowInsets();
8929        } else {
8930            outLocalInsets.set(0, 0, 0, 0);
8931            return in;
8932        }
8933    }
8934
8935    /**
8936     * Sets whether or not this view should account for system screen decorations
8937     * such as the status bar and inset its content; that is, controlling whether
8938     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8939     * executed.  See that method for more details.
8940     *
8941     * <p>Note that if you are providing your own implementation of
8942     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8943     * flag to true -- your implementation will be overriding the default
8944     * implementation that checks this flag.
8945     *
8946     * @param fitSystemWindows If true, then the default implementation of
8947     * {@link #fitSystemWindows(Rect)} will be executed.
8948     *
8949     * @attr ref android.R.styleable#View_fitsSystemWindows
8950     * @see #getFitsSystemWindows()
8951     * @see #fitSystemWindows(Rect)
8952     * @see #setSystemUiVisibility(int)
8953     */
8954    public void setFitsSystemWindows(boolean fitSystemWindows) {
8955        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8956    }
8957
8958    /**
8959     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8960     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8961     * will be executed.
8962     *
8963     * @return {@code true} if the default implementation of
8964     * {@link #fitSystemWindows(Rect)} will be executed.
8965     *
8966     * @attr ref android.R.styleable#View_fitsSystemWindows
8967     * @see #setFitsSystemWindows(boolean)
8968     * @see #fitSystemWindows(Rect)
8969     * @see #setSystemUiVisibility(int)
8970     */
8971    @ViewDebug.ExportedProperty
8972    public boolean getFitsSystemWindows() {
8973        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8974    }
8975
8976    /** @hide */
8977    public boolean fitsSystemWindows() {
8978        return getFitsSystemWindows();
8979    }
8980
8981    /**
8982     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8983     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8984     */
8985    @Deprecated
8986    public void requestFitSystemWindows() {
8987        if (mParent != null) {
8988            mParent.requestFitSystemWindows();
8989        }
8990    }
8991
8992    /**
8993     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8994     */
8995    public void requestApplyInsets() {
8996        requestFitSystemWindows();
8997    }
8998
8999    /**
9000     * For use by PhoneWindow to make its own system window fitting optional.
9001     * @hide
9002     */
9003    public void makeOptionalFitsSystemWindows() {
9004        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9005    }
9006
9007    /**
9008     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9009     * treat them as such.
9010     * @hide
9011     */
9012    public void getOutsets(Rect outOutsetRect) {
9013        if (mAttachInfo != null) {
9014            outOutsetRect.set(mAttachInfo.mOutsets);
9015        } else {
9016            outOutsetRect.setEmpty();
9017        }
9018    }
9019
9020    /**
9021     * Returns the visibility status for this view.
9022     *
9023     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9024     * @attr ref android.R.styleable#View_visibility
9025     */
9026    @ViewDebug.ExportedProperty(mapping = {
9027        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9028        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9029        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9030    })
9031    @Visibility
9032    public int getVisibility() {
9033        return mViewFlags & VISIBILITY_MASK;
9034    }
9035
9036    /**
9037     * Set the visibility state of this view.
9038     *
9039     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9040     * @attr ref android.R.styleable#View_visibility
9041     */
9042    @RemotableViewMethod
9043    public void setVisibility(@Visibility int visibility) {
9044        setFlags(visibility, VISIBILITY_MASK);
9045    }
9046
9047    /**
9048     * Returns the enabled status for this view. The interpretation of the
9049     * enabled state varies by subclass.
9050     *
9051     * @return True if this view is enabled, false otherwise.
9052     */
9053    @ViewDebug.ExportedProperty
9054    public boolean isEnabled() {
9055        return (mViewFlags & ENABLED_MASK) == ENABLED;
9056    }
9057
9058    /**
9059     * Set the enabled state of this view. The interpretation of the enabled
9060     * state varies by subclass.
9061     *
9062     * @param enabled True if this view is enabled, false otherwise.
9063     */
9064    @RemotableViewMethod
9065    public void setEnabled(boolean enabled) {
9066        if (enabled == isEnabled()) return;
9067
9068        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9069
9070        /*
9071         * The View most likely has to change its appearance, so refresh
9072         * the drawable state.
9073         */
9074        refreshDrawableState();
9075
9076        // Invalidate too, since the default behavior for views is to be
9077        // be drawn at 50% alpha rather than to change the drawable.
9078        invalidate(true);
9079
9080        if (!enabled) {
9081            cancelPendingInputEvents();
9082        }
9083    }
9084
9085    /**
9086     * Set whether this view can receive the focus.
9087     * <p>
9088     * Setting this to false will also ensure that this view is not focusable
9089     * in touch mode.
9090     *
9091     * @param focusable If true, this view can receive the focus.
9092     *
9093     * @see #setFocusableInTouchMode(boolean)
9094     * @see #setFocusable(int)
9095     * @attr ref android.R.styleable#View_focusable
9096     */
9097    public void setFocusable(boolean focusable) {
9098        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9099    }
9100
9101    /**
9102     * Sets whether this view can receive focus.
9103     * <p>
9104     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9105     * automatically based on the view's interactivity. This is the default.
9106     * <p>
9107     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9108     * in touch mode.
9109     *
9110     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9111     *                  or {@link #FOCUSABLE_AUTO}.
9112     * @see #setFocusableInTouchMode(boolean)
9113     * @attr ref android.R.styleable#View_focusable
9114     */
9115    public void setFocusable(@Focusable int focusable) {
9116        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9117            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9118        }
9119        setFlags(focusable, FOCUSABLE_MASK);
9120    }
9121
9122    /**
9123     * Set whether this view can receive focus while in touch mode.
9124     *
9125     * Setting this to true will also ensure that this view is focusable.
9126     *
9127     * @param focusableInTouchMode If true, this view can receive the focus while
9128     *   in touch mode.
9129     *
9130     * @see #setFocusable(boolean)
9131     * @attr ref android.R.styleable#View_focusableInTouchMode
9132     */
9133    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9134        // Focusable in touch mode should always be set before the focusable flag
9135        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9136        // which, in touch mode, will not successfully request focus on this view
9137        // because the focusable in touch mode flag is not set
9138        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9139
9140        // Clear FOCUSABLE_AUTO if set.
9141        if (focusableInTouchMode) {
9142            // Clears FOCUSABLE_AUTO if set.
9143            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9144        }
9145    }
9146
9147    /**
9148     * Set autofill mode for the view.
9149     *
9150     * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
9151     *                     or {@link #AUTOFILL_MODE_MANUAL}.
9152     * @attr ref android.R.styleable#View_autofillMode
9153     */
9154    public void setAutofillMode(@AutofillMode int autofillMode) {
9155        Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
9156                AUTOFILL_MODE_MANUAL, "autofillMode");
9157
9158        mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
9159        mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
9160    }
9161
9162    /**
9163     * Sets the hints that helps the autofill service to select the appropriate data to fill the
9164     * view.
9165     *
9166     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9167     * @attr ref android.R.styleable#View_autofillHints
9168     */
9169    public void setAutofillHints(@Nullable String... autofillHints) {
9170        if (autofillHints == null || autofillHints.length == 0) {
9171            mAutofillHints = null;
9172        } else {
9173            mAutofillHints = autofillHints;
9174        }
9175    }
9176
9177    /**
9178     * @hide
9179     */
9180    @TestApi
9181    public void setAutofilled(boolean isAutofilled) {
9182        boolean wasChanged = isAutofilled != isAutofilled();
9183
9184        if (wasChanged) {
9185            if (isAutofilled) {
9186                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9187            } else {
9188                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9189            }
9190
9191            invalidate();
9192        }
9193    }
9194
9195    /**
9196     * Set whether this view should have sound effects enabled for events such as
9197     * clicking and touching.
9198     *
9199     * <p>You may wish to disable sound effects for a view if you already play sounds,
9200     * for instance, a dial key that plays dtmf tones.
9201     *
9202     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9203     * @see #isSoundEffectsEnabled()
9204     * @see #playSoundEffect(int)
9205     * @attr ref android.R.styleable#View_soundEffectsEnabled
9206     */
9207    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9208        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9209    }
9210
9211    /**
9212     * @return whether this view should have sound effects enabled for events such as
9213     *     clicking and touching.
9214     *
9215     * @see #setSoundEffectsEnabled(boolean)
9216     * @see #playSoundEffect(int)
9217     * @attr ref android.R.styleable#View_soundEffectsEnabled
9218     */
9219    @ViewDebug.ExportedProperty
9220    public boolean isSoundEffectsEnabled() {
9221        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9222    }
9223
9224    /**
9225     * Set whether this view should have haptic feedback for events such as
9226     * long presses.
9227     *
9228     * <p>You may wish to disable haptic feedback if your view already controls
9229     * its own haptic feedback.
9230     *
9231     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9232     * @see #isHapticFeedbackEnabled()
9233     * @see #performHapticFeedback(int)
9234     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9235     */
9236    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9237        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9238    }
9239
9240    /**
9241     * @return whether this view should have haptic feedback enabled for events
9242     * long presses.
9243     *
9244     * @see #setHapticFeedbackEnabled(boolean)
9245     * @see #performHapticFeedback(int)
9246     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9247     */
9248    @ViewDebug.ExportedProperty
9249    public boolean isHapticFeedbackEnabled() {
9250        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9251    }
9252
9253    /**
9254     * Returns the layout direction for this view.
9255     *
9256     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9257     *   {@link #LAYOUT_DIRECTION_RTL},
9258     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9259     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9260     *
9261     * @attr ref android.R.styleable#View_layoutDirection
9262     *
9263     * @hide
9264     */
9265    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9266        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9267        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9268        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9269        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9270    })
9271    @LayoutDir
9272    public int getRawLayoutDirection() {
9273        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9274    }
9275
9276    /**
9277     * Set the layout direction for this view. This will propagate a reset of layout direction
9278     * resolution to the view's children and resolve layout direction for this view.
9279     *
9280     * @param layoutDirection the layout direction to set. Should be one of:
9281     *
9282     * {@link #LAYOUT_DIRECTION_LTR},
9283     * {@link #LAYOUT_DIRECTION_RTL},
9284     * {@link #LAYOUT_DIRECTION_INHERIT},
9285     * {@link #LAYOUT_DIRECTION_LOCALE}.
9286     *
9287     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9288     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9289     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9290     *
9291     * @attr ref android.R.styleable#View_layoutDirection
9292     */
9293    @RemotableViewMethod
9294    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9295        if (getRawLayoutDirection() != layoutDirection) {
9296            // Reset the current layout direction and the resolved one
9297            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9298            resetRtlProperties();
9299            // Set the new layout direction (filtered)
9300            mPrivateFlags2 |=
9301                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9302            // We need to resolve all RTL properties as they all depend on layout direction
9303            resolveRtlPropertiesIfNeeded();
9304            requestLayout();
9305            invalidate(true);
9306        }
9307    }
9308
9309    /**
9310     * Returns the resolved layout direction for this view.
9311     *
9312     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9313     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9314     *
9315     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9316     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9317     *
9318     * @attr ref android.R.styleable#View_layoutDirection
9319     */
9320    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9321        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9322        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9323    })
9324    @ResolvedLayoutDir
9325    public int getLayoutDirection() {
9326        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9327        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9328            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9329            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9330        }
9331        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9332                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9333    }
9334
9335    /**
9336     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9337     * layout attribute and/or the inherited value from the parent
9338     *
9339     * @return true if the layout is right-to-left.
9340     *
9341     * @hide
9342     */
9343    @ViewDebug.ExportedProperty(category = "layout")
9344    public boolean isLayoutRtl() {
9345        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9346    }
9347
9348    /**
9349     * Indicates whether the view is currently tracking transient state that the
9350     * app should not need to concern itself with saving and restoring, but that
9351     * the framework should take special note to preserve when possible.
9352     *
9353     * <p>A view with transient state cannot be trivially rebound from an external
9354     * data source, such as an adapter binding item views in a list. This may be
9355     * because the view is performing an animation, tracking user selection
9356     * of content, or similar.</p>
9357     *
9358     * @return true if the view has transient state
9359     */
9360    @ViewDebug.ExportedProperty(category = "layout")
9361    public boolean hasTransientState() {
9362        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9363    }
9364
9365    /**
9366     * Set whether this view is currently tracking transient state that the
9367     * framework should attempt to preserve when possible. This flag is reference counted,
9368     * so every call to setHasTransientState(true) should be paired with a later call
9369     * to setHasTransientState(false).
9370     *
9371     * <p>A view with transient state cannot be trivially rebound from an external
9372     * data source, such as an adapter binding item views in a list. This may be
9373     * because the view is performing an animation, tracking user selection
9374     * of content, or similar.</p>
9375     *
9376     * @param hasTransientState true if this view has transient state
9377     */
9378    public void setHasTransientState(boolean hasTransientState) {
9379        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9380                mTransientStateCount - 1;
9381        if (mTransientStateCount < 0) {
9382            mTransientStateCount = 0;
9383            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9384                    "unmatched pair of setHasTransientState calls");
9385        } else if ((hasTransientState && mTransientStateCount == 1) ||
9386                (!hasTransientState && mTransientStateCount == 0)) {
9387            // update flag if we've just incremented up from 0 or decremented down to 0
9388            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9389                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9390            if (mParent != null) {
9391                try {
9392                    mParent.childHasTransientStateChanged(this, hasTransientState);
9393                } catch (AbstractMethodError e) {
9394                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9395                            " does not fully implement ViewParent", e);
9396                }
9397            }
9398        }
9399    }
9400
9401    /**
9402     * Returns true if this view is currently attached to a window.
9403     */
9404    public boolean isAttachedToWindow() {
9405        return mAttachInfo != null;
9406    }
9407
9408    /**
9409     * Returns true if this view has been through at least one layout since it
9410     * was last attached to or detached from a window.
9411     */
9412    public boolean isLaidOut() {
9413        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9414    }
9415
9416    /**
9417     * If this view doesn't do any drawing on its own, set this flag to
9418     * allow further optimizations. By default, this flag is not set on
9419     * View, but could be set on some View subclasses such as ViewGroup.
9420     *
9421     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9422     * you should clear this flag.
9423     *
9424     * @param willNotDraw whether or not this View draw on its own
9425     */
9426    public void setWillNotDraw(boolean willNotDraw) {
9427        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9428    }
9429
9430    /**
9431     * Returns whether or not this View draws on its own.
9432     *
9433     * @return true if this view has nothing to draw, false otherwise
9434     */
9435    @ViewDebug.ExportedProperty(category = "drawing")
9436    public boolean willNotDraw() {
9437        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9438    }
9439
9440    /**
9441     * When a View's drawing cache is enabled, drawing is redirected to an
9442     * offscreen bitmap. Some views, like an ImageView, must be able to
9443     * bypass this mechanism if they already draw a single bitmap, to avoid
9444     * unnecessary usage of the memory.
9445     *
9446     * @param willNotCacheDrawing true if this view does not cache its
9447     *        drawing, false otherwise
9448     */
9449    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9450        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9451    }
9452
9453    /**
9454     * Returns whether or not this View can cache its drawing or not.
9455     *
9456     * @return true if this view does not cache its drawing, false otherwise
9457     */
9458    @ViewDebug.ExportedProperty(category = "drawing")
9459    public boolean willNotCacheDrawing() {
9460        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9461    }
9462
9463    /**
9464     * Indicates whether this view reacts to click events or not.
9465     *
9466     * @return true if the view is clickable, false otherwise
9467     *
9468     * @see #setClickable(boolean)
9469     * @attr ref android.R.styleable#View_clickable
9470     */
9471    @ViewDebug.ExportedProperty
9472    public boolean isClickable() {
9473        return (mViewFlags & CLICKABLE) == CLICKABLE;
9474    }
9475
9476    /**
9477     * Enables or disables click events for this view. When a view
9478     * is clickable it will change its state to "pressed" on every click.
9479     * Subclasses should set the view clickable to visually react to
9480     * user's clicks.
9481     *
9482     * @param clickable true to make the view clickable, false otherwise
9483     *
9484     * @see #isClickable()
9485     * @attr ref android.R.styleable#View_clickable
9486     */
9487    public void setClickable(boolean clickable) {
9488        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9489    }
9490
9491    /**
9492     * Indicates whether this view reacts to long click events or not.
9493     *
9494     * @return true if the view is long clickable, false otherwise
9495     *
9496     * @see #setLongClickable(boolean)
9497     * @attr ref android.R.styleable#View_longClickable
9498     */
9499    public boolean isLongClickable() {
9500        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9501    }
9502
9503    /**
9504     * Enables or disables long click events for this view. When a view is long
9505     * clickable it reacts to the user holding down the button for a longer
9506     * duration than a tap. This event can either launch the listener or a
9507     * context menu.
9508     *
9509     * @param longClickable true to make the view long clickable, false otherwise
9510     * @see #isLongClickable()
9511     * @attr ref android.R.styleable#View_longClickable
9512     */
9513    public void setLongClickable(boolean longClickable) {
9514        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9515    }
9516
9517    /**
9518     * Indicates whether this view reacts to context clicks or not.
9519     *
9520     * @return true if the view is context clickable, false otherwise
9521     * @see #setContextClickable(boolean)
9522     * @attr ref android.R.styleable#View_contextClickable
9523     */
9524    public boolean isContextClickable() {
9525        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9526    }
9527
9528    /**
9529     * Enables or disables context clicking for this view. This event can launch the listener.
9530     *
9531     * @param contextClickable true to make the view react to a context click, false otherwise
9532     * @see #isContextClickable()
9533     * @attr ref android.R.styleable#View_contextClickable
9534     */
9535    public void setContextClickable(boolean contextClickable) {
9536        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9537    }
9538
9539    /**
9540     * Sets the pressed state for this view and provides a touch coordinate for
9541     * animation hinting.
9542     *
9543     * @param pressed Pass true to set the View's internal state to "pressed",
9544     *            or false to reverts the View's internal state from a
9545     *            previously set "pressed" state.
9546     * @param x The x coordinate of the touch that caused the press
9547     * @param y The y coordinate of the touch that caused the press
9548     */
9549    private void setPressed(boolean pressed, float x, float y) {
9550        if (pressed) {
9551            drawableHotspotChanged(x, y);
9552        }
9553
9554        setPressed(pressed);
9555    }
9556
9557    /**
9558     * Sets the pressed state for this view.
9559     *
9560     * @see #isClickable()
9561     * @see #setClickable(boolean)
9562     *
9563     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9564     *        the View's internal state from a previously set "pressed" state.
9565     */
9566    public void setPressed(boolean pressed) {
9567        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9568
9569        if (pressed) {
9570            mPrivateFlags |= PFLAG_PRESSED;
9571        } else {
9572            mPrivateFlags &= ~PFLAG_PRESSED;
9573        }
9574
9575        if (needsRefresh) {
9576            refreshDrawableState();
9577        }
9578        dispatchSetPressed(pressed);
9579    }
9580
9581    /**
9582     * Dispatch setPressed to all of this View's children.
9583     *
9584     * @see #setPressed(boolean)
9585     *
9586     * @param pressed The new pressed state
9587     */
9588    protected void dispatchSetPressed(boolean pressed) {
9589    }
9590
9591    /**
9592     * Indicates whether the view is currently in pressed state. Unless
9593     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9594     * the pressed state.
9595     *
9596     * @see #setPressed(boolean)
9597     * @see #isClickable()
9598     * @see #setClickable(boolean)
9599     *
9600     * @return true if the view is currently pressed, false otherwise
9601     */
9602    @ViewDebug.ExportedProperty
9603    public boolean isPressed() {
9604        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9605    }
9606
9607    /**
9608     * @hide
9609     * Indicates whether this view will participate in data collection through
9610     * {@link ViewStructure}.  If true, it will not provide any data
9611     * for itself or its children.  If false, the normal data collection will be allowed.
9612     *
9613     * @return Returns false if assist data collection is not blocked, else true.
9614     *
9615     * @see #setAssistBlocked(boolean)
9616     * @attr ref android.R.styleable#View_assistBlocked
9617     */
9618    public boolean isAssistBlocked() {
9619        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9620    }
9621
9622    /**
9623     * @hide
9624     * Indicates whether this view will participate in data collection through
9625     * {@link ViewStructure} for autofill purposes.
9626     *
9627     * <p>If {@code true}, it will not provide any data for itself or its children.
9628     * <p>If {@code false}, the normal data collection will be allowed.
9629     *
9630     * @return Returns {@code false} if assist data collection for autofill is not blocked,
9631     * else {@code true}.
9632     *
9633     * TODO(b/33197203): update / remove javadoc tags below
9634     * @see #setAssistBlocked(boolean)
9635     * @attr ref android.R.styleable#View_assistBlocked
9636     */
9637    public boolean isAutofillBlocked() {
9638        return false; // TODO(b/33197203): properly implement it
9639    }
9640
9641    /**
9642     * @hide
9643     * Controls whether assist data collection from this view and its children is enabled
9644     * (that is, whether {@link #onProvideStructure} and
9645     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9646     * allowing normal assist collection.  Setting this to false will disable assist collection.
9647     *
9648     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9649     * (the default) to allow it.
9650     *
9651     * @see #isAssistBlocked()
9652     * @see #onProvideStructure
9653     * @see #onProvideVirtualStructure
9654     * @attr ref android.R.styleable#View_assistBlocked
9655     */
9656    public void setAssistBlocked(boolean enabled) {
9657        if (enabled) {
9658            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9659        } else {
9660            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9661        }
9662    }
9663
9664    /**
9665     * Indicates whether this view will save its state (that is,
9666     * whether its {@link #onSaveInstanceState} method will be called).
9667     *
9668     * @return Returns true if the view state saving is enabled, else false.
9669     *
9670     * @see #setSaveEnabled(boolean)
9671     * @attr ref android.R.styleable#View_saveEnabled
9672     */
9673    public boolean isSaveEnabled() {
9674        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9675    }
9676
9677    /**
9678     * Controls whether the saving of this view's state is
9679     * enabled (that is, whether its {@link #onSaveInstanceState} method
9680     * will be called).  Note that even if freezing is enabled, the
9681     * view still must have an id assigned to it (via {@link #setId(int)})
9682     * for its state to be saved.  This flag can only disable the
9683     * saving of this view; any child views may still have their state saved.
9684     *
9685     * @param enabled Set to false to <em>disable</em> state saving, or true
9686     * (the default) to allow it.
9687     *
9688     * @see #isSaveEnabled()
9689     * @see #setId(int)
9690     * @see #onSaveInstanceState()
9691     * @attr ref android.R.styleable#View_saveEnabled
9692     */
9693    public void setSaveEnabled(boolean enabled) {
9694        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9695    }
9696
9697    /**
9698     * Gets whether the framework should discard touches when the view's
9699     * window is obscured by another visible window.
9700     * Refer to the {@link View} security documentation for more details.
9701     *
9702     * @return True if touch filtering is enabled.
9703     *
9704     * @see #setFilterTouchesWhenObscured(boolean)
9705     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9706     */
9707    @ViewDebug.ExportedProperty
9708    public boolean getFilterTouchesWhenObscured() {
9709        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9710    }
9711
9712    /**
9713     * Sets whether the framework should discard touches when the view's
9714     * window is obscured by another visible window.
9715     * Refer to the {@link View} security documentation for more details.
9716     *
9717     * @param enabled True if touch filtering should be enabled.
9718     *
9719     * @see #getFilterTouchesWhenObscured
9720     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9721     */
9722    public void setFilterTouchesWhenObscured(boolean enabled) {
9723        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9724                FILTER_TOUCHES_WHEN_OBSCURED);
9725    }
9726
9727    /**
9728     * Indicates whether the entire hierarchy under this view will save its
9729     * state when a state saving traversal occurs from its parent.  The default
9730     * is true; if false, these views will not be saved unless
9731     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9732     *
9733     * @return Returns true if the view state saving from parent is enabled, else false.
9734     *
9735     * @see #setSaveFromParentEnabled(boolean)
9736     */
9737    public boolean isSaveFromParentEnabled() {
9738        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9739    }
9740
9741    /**
9742     * Controls whether the entire hierarchy under this view will save its
9743     * state when a state saving traversal occurs from its parent.  The default
9744     * is true; if false, these views will not be saved unless
9745     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9746     *
9747     * @param enabled Set to false to <em>disable</em> state saving, or true
9748     * (the default) to allow it.
9749     *
9750     * @see #isSaveFromParentEnabled()
9751     * @see #setId(int)
9752     * @see #onSaveInstanceState()
9753     */
9754    public void setSaveFromParentEnabled(boolean enabled) {
9755        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9756    }
9757
9758
9759    /**
9760     * Returns whether this View is currently able to take focus.
9761     *
9762     * @return True if this view can take focus, or false otherwise.
9763     */
9764    @ViewDebug.ExportedProperty(category = "focus")
9765    public final boolean isFocusable() {
9766        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9767    }
9768
9769    /**
9770     * Returns the focusable setting for this view.
9771     *
9772     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9773     * @attr ref android.R.styleable#View_focusable
9774     */
9775    @ViewDebug.ExportedProperty(mapping = {
9776            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9777            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9778            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9779            })
9780    @Focusable
9781    public int getFocusable() {
9782        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9783    }
9784
9785    /**
9786     * When a view is focusable, it may not want to take focus when in touch mode.
9787     * For example, a button would like focus when the user is navigating via a D-pad
9788     * so that the user can click on it, but once the user starts touching the screen,
9789     * the button shouldn't take focus
9790     * @return Whether the view is focusable in touch mode.
9791     * @attr ref android.R.styleable#View_focusableInTouchMode
9792     */
9793    @ViewDebug.ExportedProperty
9794    public final boolean isFocusableInTouchMode() {
9795        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9796    }
9797
9798    /**
9799     * Returns the autofill mode for this view.
9800     *
9801     * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
9802     * {@link #AUTOFILL_MODE_MANUAL}.
9803     * @attr ref android.R.styleable#View_autofillMode
9804     */
9805    @ViewDebug.ExportedProperty(mapping = {
9806            @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
9807            @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
9808            @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
9809            })
9810    @AutofillMode
9811    public int getAutofillMode() {
9812        return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
9813    }
9814
9815    /**
9816     * Returns the resolved autofill mode for this view.
9817     *
9818     * This is the same as {@link #getAutofillMode()} but if the mode is
9819     * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
9820     *
9821     * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
9822     *         fill mode can not be resolved e.g. {@link #getAutofillMode()} is
9823     *         {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
9824     *         {@link #AUTOFILL_MODE_AUTO} is returned.
9825     */
9826    public @AutofillMode int getResolvedAutofillMode() {
9827        @AutofillMode int autofillMode = getAutofillMode();
9828
9829        if (autofillMode == AUTOFILL_MODE_INHERIT) {
9830            if (mParent == null) {
9831                return AUTOFILL_MODE_AUTO;
9832            } else {
9833                return mParent.getResolvedAutofillMode();
9834            }
9835        } else {
9836            return autofillMode;
9837        }
9838    }
9839
9840    /**
9841     * Find the nearest view in the specified direction that can take focus.
9842     * This does not actually give focus to that view.
9843     *
9844     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9845     *
9846     * @return The nearest focusable in the specified direction, or null if none
9847     *         can be found.
9848     */
9849    public View focusSearch(@FocusRealDirection int direction) {
9850        if (mParent != null) {
9851            return mParent.focusSearch(this, direction);
9852        } else {
9853            return null;
9854        }
9855    }
9856
9857    /**
9858     * Returns whether this View is a root of a keyboard navigation cluster.
9859     *
9860     * @return True if this view is a root of a cluster, or false otherwise.
9861     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9862     */
9863    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9864    public final boolean isKeyboardNavigationCluster() {
9865        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9866    }
9867
9868    /**
9869     * Set whether this view is a root of a keyboard navigation cluster.
9870     *
9871     * @param isCluster If true, this view is a root of a cluster.
9872     *
9873     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9874     */
9875    public void setKeyboardNavigationCluster(boolean isCluster) {
9876        if (isCluster) {
9877            mPrivateFlags3 |= PFLAG3_CLUSTER;
9878        } else {
9879            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9880        }
9881    }
9882
9883    /**
9884     * Sets this View as the one which receives focus the next time cluster navigation jumps
9885     * to the cluster containing this View. This does NOT change focus even if the cluster
9886     * containing this view is current.
9887     *
9888     * @hide
9889     */
9890    public void setFocusedInCluster() {
9891        if (mParent instanceof ViewGroup) {
9892            ((ViewGroup) mParent).setFocusInCluster(this);
9893        }
9894    }
9895
9896    /**
9897     * Returns whether this View should receive focus when the focus is restored for the view
9898     * hierarchy containing this view.
9899     * <p>
9900     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9901     * window or serves as a target of cluster navigation.
9902     *
9903     * @see #restoreDefaultFocus()
9904     *
9905     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9906     * @attr ref android.R.styleable#View_focusedByDefault
9907     */
9908    @ViewDebug.ExportedProperty(category = "focusedByDefault")
9909    public final boolean isFocusedByDefault() {
9910        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9911    }
9912
9913    /**
9914     * Sets whether this View should receive focus when the focus is restored for the view
9915     * hierarchy containing this view.
9916     * <p>
9917     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9918     * window or serves as a target of cluster navigation.
9919     *
9920     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9921     *                           {@code false} otherwise.
9922     *
9923     * @see #restoreDefaultFocus()
9924     *
9925     * @attr ref android.R.styleable#View_focusedByDefault
9926     */
9927    public void setFocusedByDefault(boolean isFocusedByDefault) {
9928        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9929            return;
9930        }
9931
9932        if (isFocusedByDefault) {
9933            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9934        } else {
9935            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9936        }
9937
9938        if (mParent instanceof ViewGroup) {
9939            if (isFocusedByDefault) {
9940                ((ViewGroup) mParent).setDefaultFocus(this);
9941            } else {
9942                ((ViewGroup) mParent).clearDefaultFocus(this);
9943            }
9944        }
9945    }
9946
9947    /**
9948     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9949     *
9950     * @return {@code true} if this view has default focus, {@code false} otherwise
9951     */
9952    boolean hasDefaultFocus() {
9953        return isFocusedByDefault();
9954    }
9955
9956    /**
9957     * Find the nearest keyboard navigation cluster in the specified direction.
9958     * This does not actually give focus to that cluster.
9959     *
9960     * @param currentCluster The starting point of the search. Null means the current cluster is not
9961     *                       found yet
9962     * @param direction Direction to look
9963     *
9964     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9965     *         can be found
9966     */
9967    public View keyboardNavigationClusterSearch(View currentCluster,
9968            @FocusDirection int direction) {
9969        if (isKeyboardNavigationCluster()) {
9970            currentCluster = this;
9971        }
9972        if (isRootNamespace()) {
9973            // Root namespace means we should consider ourselves the top of the
9974            // tree for group searching; otherwise we could be group searching
9975            // into other tabs.  see LocalActivityManager and TabHost for more info.
9976            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9977                    this, currentCluster, direction);
9978        } else if (mParent != null) {
9979            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9980        }
9981        return null;
9982    }
9983
9984    /**
9985     * This method is the last chance for the focused view and its ancestors to
9986     * respond to an arrow key. This is called when the focused view did not
9987     * consume the key internally, nor could the view system find a new view in
9988     * the requested direction to give focus to.
9989     *
9990     * @param focused The currently focused view.
9991     * @param direction The direction focus wants to move. One of FOCUS_UP,
9992     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9993     * @return True if the this view consumed this unhandled move.
9994     */
9995    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9996        return false;
9997    }
9998
9999    /**
10000     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10001     * have {@link android.R.attr#state_focused} defined in its background.
10002     *
10003     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10004     *                                      highlight, {@code false} otherwise.
10005     *
10006     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10007     */
10008    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10009        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10010    }
10011
10012    /**
10013
10014    /**
10015     * Returns whether this View should use a default focus highlight when it gets focused but
10016     * doesn't have {@link android.R.attr#state_focused} defined in its background.
10017     *
10018     * @return True if this View should use a default focus highlight.
10019     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10020     */
10021    @ViewDebug.ExportedProperty(category = "defaultFocusHighlightEnabled")
10022    public final boolean getDefaultFocusHighlightEnabled() {
10023        return mDefaultFocusHighlightEnabled;
10024    }
10025
10026    /**
10027     * If a user manually specified the next view id for a particular direction,
10028     * use the root to look up the view.
10029     * @param root The root view of the hierarchy containing this view.
10030     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10031     * or FOCUS_BACKWARD.
10032     * @return The user specified next view, or null if there is none.
10033     */
10034    View findUserSetNextFocus(View root, @FocusDirection int direction) {
10035        switch (direction) {
10036            case FOCUS_LEFT:
10037                if (mNextFocusLeftId == View.NO_ID) return null;
10038                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10039            case FOCUS_RIGHT:
10040                if (mNextFocusRightId == View.NO_ID) return null;
10041                return findViewInsideOutShouldExist(root, mNextFocusRightId);
10042            case FOCUS_UP:
10043                if (mNextFocusUpId == View.NO_ID) return null;
10044                return findViewInsideOutShouldExist(root, mNextFocusUpId);
10045            case FOCUS_DOWN:
10046                if (mNextFocusDownId == View.NO_ID) return null;
10047                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10048            case FOCUS_FORWARD:
10049                if (mNextFocusForwardId == View.NO_ID) return null;
10050                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10051            case FOCUS_BACKWARD: {
10052                if (mID == View.NO_ID) return null;
10053                final int id = mID;
10054                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10055                    @Override
10056                    public boolean test(View t) {
10057                        return t.mNextFocusForwardId == id;
10058                    }
10059                });
10060            }
10061        }
10062        return null;
10063    }
10064
10065    /**
10066     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10067     * use the root to look up the view.
10068     *
10069     * @param root the root view of the hierarchy containing this view
10070     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10071     * @return the user-specified next cluster, or {@code null} if there is none
10072     */
10073    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10074        switch (direction) {
10075            case FOCUS_FORWARD:
10076                if (mNextClusterForwardId == View.NO_ID) return null;
10077                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10078            case FOCUS_BACKWARD: {
10079                if (mID == View.NO_ID) return null;
10080                final int id = mID;
10081                return root.findViewByPredicateInsideOut(this,
10082                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10083            }
10084        }
10085        return null;
10086    }
10087
10088    private View findViewInsideOutShouldExist(View root, int id) {
10089        if (mMatchIdPredicate == null) {
10090            mMatchIdPredicate = new MatchIdPredicate();
10091        }
10092        mMatchIdPredicate.mId = id;
10093        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10094        if (result == null) {
10095            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10096        }
10097        return result;
10098    }
10099
10100    /**
10101     * Find and return all focusable views that are descendants of this view,
10102     * possibly including this view if it is focusable itself.
10103     *
10104     * @param direction The direction of the focus
10105     * @return A list of focusable views
10106     */
10107    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10108        ArrayList<View> result = new ArrayList<View>(24);
10109        addFocusables(result, direction);
10110        return result;
10111    }
10112
10113    /**
10114     * Add any focusable views that are descendants of this view (possibly
10115     * including this view if it is focusable itself) to views.  If we are in touch mode,
10116     * only add views that are also focusable in touch mode.
10117     *
10118     * @param views Focusable views found so far
10119     * @param direction The direction of the focus
10120     */
10121    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10122        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10123    }
10124
10125    /**
10126     * Adds any focusable views that are descendants of this view (possibly
10127     * including this view if it is focusable itself) to views. This method
10128     * adds all focusable views regardless if we are in touch mode or
10129     * only views focusable in touch mode if we are in touch mode or
10130     * only views that can take accessibility focus if accessibility is enabled
10131     * depending on the focusable mode parameter.
10132     *
10133     * @param views Focusable views found so far or null if all we are interested is
10134     *        the number of focusables.
10135     * @param direction The direction of the focus.
10136     * @param focusableMode The type of focusables to be added.
10137     *
10138     * @see #FOCUSABLES_ALL
10139     * @see #FOCUSABLES_TOUCH_MODE
10140     */
10141    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10142            @FocusableMode int focusableMode) {
10143        if (views == null) {
10144            return;
10145        }
10146        if (!isFocusable()) {
10147            return;
10148        }
10149        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10150                && !isFocusableInTouchMode()) {
10151            return;
10152        }
10153        views.add(this);
10154    }
10155
10156    /**
10157     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10158     * including this view if it is a cluster root itself) to views.
10159     *
10160     * @param views Keyboard navigation cluster roots found so far
10161     * @param direction Direction to look
10162     */
10163    public void addKeyboardNavigationClusters(
10164            @NonNull Collection<View> views,
10165            int direction) {
10166        if (!isKeyboardNavigationCluster()) {
10167            return;
10168        }
10169        if (!hasFocusable()) {
10170            return;
10171        }
10172        views.add(this);
10173    }
10174
10175    /**
10176     * Finds the Views that contain given text. The containment is case insensitive.
10177     * The search is performed by either the text that the View renders or the content
10178     * description that describes the view for accessibility purposes and the view does
10179     * not render or both. Clients can specify how the search is to be performed via
10180     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10181     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10182     *
10183     * @param outViews The output list of matching Views.
10184     * @param searched The text to match against.
10185     *
10186     * @see #FIND_VIEWS_WITH_TEXT
10187     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10188     * @see #setContentDescription(CharSequence)
10189     */
10190    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10191            @FindViewFlags int flags) {
10192        if (getAccessibilityNodeProvider() != null) {
10193            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10194                outViews.add(this);
10195            }
10196        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10197                && (searched != null && searched.length() > 0)
10198                && (mContentDescription != null && mContentDescription.length() > 0)) {
10199            String searchedLowerCase = searched.toString().toLowerCase();
10200            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10201            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10202                outViews.add(this);
10203            }
10204        }
10205    }
10206
10207    /**
10208     * Find and return all touchable views that are descendants of this view,
10209     * possibly including this view if it is touchable itself.
10210     *
10211     * @return A list of touchable views
10212     */
10213    public ArrayList<View> getTouchables() {
10214        ArrayList<View> result = new ArrayList<View>();
10215        addTouchables(result);
10216        return result;
10217    }
10218
10219    /**
10220     * Add any touchable views that are descendants of this view (possibly
10221     * including this view if it is touchable itself) to views.
10222     *
10223     * @param views Touchable views found so far
10224     */
10225    public void addTouchables(ArrayList<View> views) {
10226        final int viewFlags = mViewFlags;
10227
10228        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10229                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10230                && (viewFlags & ENABLED_MASK) == ENABLED) {
10231            views.add(this);
10232        }
10233    }
10234
10235    /**
10236     * Returns whether this View is accessibility focused.
10237     *
10238     * @return True if this View is accessibility focused.
10239     */
10240    public boolean isAccessibilityFocused() {
10241        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10242    }
10243
10244    /**
10245     * Call this to try to give accessibility focus to this view.
10246     *
10247     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10248     * returns false or the view is no visible or the view already has accessibility
10249     * focus.
10250     *
10251     * See also {@link #focusSearch(int)}, which is what you call to say that you
10252     * have focus, and you want your parent to look for the next one.
10253     *
10254     * @return Whether this view actually took accessibility focus.
10255     *
10256     * @hide
10257     */
10258    public boolean requestAccessibilityFocus() {
10259        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10260        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10261            return false;
10262        }
10263        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10264            return false;
10265        }
10266        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10267            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10268            ViewRootImpl viewRootImpl = getViewRootImpl();
10269            if (viewRootImpl != null) {
10270                viewRootImpl.setAccessibilityFocus(this, null);
10271            }
10272            invalidate();
10273            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10274            return true;
10275        }
10276        return false;
10277    }
10278
10279    /**
10280     * Call this to try to clear accessibility focus of this view.
10281     *
10282     * See also {@link #focusSearch(int)}, which is what you call to say that you
10283     * have focus, and you want your parent to look for the next one.
10284     *
10285     * @hide
10286     */
10287    public void clearAccessibilityFocus() {
10288        clearAccessibilityFocusNoCallbacks(0);
10289
10290        // Clear the global reference of accessibility focus if this view or
10291        // any of its descendants had accessibility focus. This will NOT send
10292        // an event or update internal state if focus is cleared from a
10293        // descendant view, which may leave views in inconsistent states.
10294        final ViewRootImpl viewRootImpl = getViewRootImpl();
10295        if (viewRootImpl != null) {
10296            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10297            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10298                viewRootImpl.setAccessibilityFocus(null, null);
10299            }
10300        }
10301    }
10302
10303    private void sendAccessibilityHoverEvent(int eventType) {
10304        // Since we are not delivering to a client accessibility events from not
10305        // important views (unless the clinet request that) we need to fire the
10306        // event from the deepest view exposed to the client. As a consequence if
10307        // the user crosses a not exposed view the client will see enter and exit
10308        // of the exposed predecessor followed by and enter and exit of that same
10309        // predecessor when entering and exiting the not exposed descendant. This
10310        // is fine since the client has a clear idea which view is hovered at the
10311        // price of a couple more events being sent. This is a simple and
10312        // working solution.
10313        View source = this;
10314        while (true) {
10315            if (source.includeForAccessibility()) {
10316                source.sendAccessibilityEvent(eventType);
10317                return;
10318            }
10319            ViewParent parent = source.getParent();
10320            if (parent instanceof View) {
10321                source = (View) parent;
10322            } else {
10323                return;
10324            }
10325        }
10326    }
10327
10328    /**
10329     * Clears accessibility focus without calling any callback methods
10330     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10331     * is used separately from that one for clearing accessibility focus when
10332     * giving this focus to another view.
10333     *
10334     * @param action The action, if any, that led to focus being cleared. Set to
10335     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10336     * the window.
10337     */
10338    void clearAccessibilityFocusNoCallbacks(int action) {
10339        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10340            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10341            invalidate();
10342            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10343                AccessibilityEvent event = AccessibilityEvent.obtain(
10344                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10345                event.setAction(action);
10346                if (mAccessibilityDelegate != null) {
10347                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10348                } else {
10349                    sendAccessibilityEventUnchecked(event);
10350                }
10351            }
10352        }
10353    }
10354
10355    /**
10356     * Call this to try to give focus to a specific view or to one of its
10357     * descendants.
10358     *
10359     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10360     * false), or if it is focusable and it is not focusable in touch mode
10361     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10362     *
10363     * See also {@link #focusSearch(int)}, which is what you call to say that you
10364     * have focus, and you want your parent to look for the next one.
10365     *
10366     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10367     * {@link #FOCUS_DOWN} and <code>null</code>.
10368     *
10369     * @return Whether this view or one of its descendants actually took focus.
10370     */
10371    public final boolean requestFocus() {
10372        return requestFocus(View.FOCUS_DOWN);
10373    }
10374
10375    /**
10376     * This will request focus for whichever View was last focused within this
10377     * cluster before a focus-jump out of it.
10378     *
10379     * @hide
10380     */
10381    @TestApi
10382    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10383        // Prioritize focusableByDefault over algorithmic focus selection.
10384        if (restoreDefaultFocus()) {
10385            return true;
10386        }
10387        return requestFocus(direction);
10388    }
10389
10390    /**
10391     * This will request focus for whichever View not in a cluster was last focused before a
10392     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10393     * the "first" focusable view it finds.
10394     *
10395     * @hide
10396     */
10397    @TestApi
10398    public boolean restoreFocusNotInCluster() {
10399        return requestFocus(View.FOCUS_DOWN);
10400    }
10401
10402    /**
10403     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10404     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10405     *
10406     * @return Whether this view or one of its descendants actually took focus
10407     */
10408    public boolean restoreDefaultFocus() {
10409        return requestFocus(View.FOCUS_DOWN);
10410    }
10411
10412    /**
10413     * Call this to try to give focus to a specific view or to one of its
10414     * descendants and give it a hint about what direction focus is heading.
10415     *
10416     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10417     * false), or if it is focusable and it is not focusable in touch mode
10418     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10419     *
10420     * See also {@link #focusSearch(int)}, which is what you call to say that you
10421     * have focus, and you want your parent to look for the next one.
10422     *
10423     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10424     * <code>null</code> set for the previously focused rectangle.
10425     *
10426     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10427     * @return Whether this view or one of its descendants actually took focus.
10428     */
10429    public final boolean requestFocus(int direction) {
10430        return requestFocus(direction, null);
10431    }
10432
10433    /**
10434     * Call this to try to give focus to a specific view or to one of its descendants
10435     * and give it hints about the direction and a specific rectangle that the focus
10436     * is coming from.  The rectangle can help give larger views a finer grained hint
10437     * about where focus is coming from, and therefore, where to show selection, or
10438     * forward focus change internally.
10439     *
10440     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10441     * false), or if it is focusable and it is not focusable in touch mode
10442     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10443     *
10444     * A View will not take focus if it is not visible.
10445     *
10446     * A View will not take focus if one of its parents has
10447     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10448     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10449     *
10450     * See also {@link #focusSearch(int)}, which is what you call to say that you
10451     * have focus, and you want your parent to look for the next one.
10452     *
10453     * You may wish to override this method if your custom {@link View} has an internal
10454     * {@link View} that it wishes to forward the request to.
10455     *
10456     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10457     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10458     *        to give a finer grained hint about where focus is coming from.  May be null
10459     *        if there is no hint.
10460     * @return Whether this view or one of its descendants actually took focus.
10461     */
10462    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10463        return requestFocusNoSearch(direction, previouslyFocusedRect);
10464    }
10465
10466    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10467        // need to be focusable
10468        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10469                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10470            return false;
10471        }
10472
10473        // need to be focusable in touch mode if in touch mode
10474        if (isInTouchMode() &&
10475            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10476               return false;
10477        }
10478
10479        // need to not have any parents blocking us
10480        if (hasAncestorThatBlocksDescendantFocus()) {
10481            return false;
10482        }
10483
10484        handleFocusGainInternal(direction, previouslyFocusedRect);
10485        return true;
10486    }
10487
10488    /**
10489     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10490     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10491     * touch mode to request focus when they are touched.
10492     *
10493     * @return Whether this view or one of its descendants actually took focus.
10494     *
10495     * @see #isInTouchMode()
10496     *
10497     */
10498    public final boolean requestFocusFromTouch() {
10499        // Leave touch mode if we need to
10500        if (isInTouchMode()) {
10501            ViewRootImpl viewRoot = getViewRootImpl();
10502            if (viewRoot != null) {
10503                viewRoot.ensureTouchMode(false);
10504            }
10505        }
10506        return requestFocus(View.FOCUS_DOWN);
10507    }
10508
10509    /**
10510     * @return Whether any ancestor of this view blocks descendant focus.
10511     */
10512    private boolean hasAncestorThatBlocksDescendantFocus() {
10513        final boolean focusableInTouchMode = isFocusableInTouchMode();
10514        ViewParent ancestor = mParent;
10515        while (ancestor instanceof ViewGroup) {
10516            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10517            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10518                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10519                return true;
10520            } else {
10521                ancestor = vgAncestor.getParent();
10522            }
10523        }
10524        return false;
10525    }
10526
10527    /**
10528     * Gets the mode for determining whether this View is important for accessibility.
10529     * A view is important for accessibility if it fires accessibility events and if it
10530     * is reported to accessibility services that query the screen.
10531     *
10532     * @return The mode for determining whether a view is important for accessibility, one
10533     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10534     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10535     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10536     *
10537     * @attr ref android.R.styleable#View_importantForAccessibility
10538     *
10539     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10540     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10541     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10542     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10543     */
10544    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10545            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10546            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10547            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10548            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10549                    to = "noHideDescendants")
10550        })
10551    public int getImportantForAccessibility() {
10552        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10553                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10554    }
10555
10556    /**
10557     * Sets the live region mode for this view. This indicates to accessibility
10558     * services whether they should automatically notify the user about changes
10559     * to the view's content description or text, or to the content descriptions
10560     * or text of the view's children (where applicable).
10561     * <p>
10562     * For example, in a login screen with a TextView that displays an "incorrect
10563     * password" notification, that view should be marked as a live region with
10564     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10565     * <p>
10566     * To disable change notifications for this view, use
10567     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10568     * mode for most views.
10569     * <p>
10570     * To indicate that the user should be notified of changes, use
10571     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10572     * <p>
10573     * If the view's changes should interrupt ongoing speech and notify the user
10574     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10575     *
10576     * @param mode The live region mode for this view, one of:
10577     *        <ul>
10578     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10579     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10580     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10581     *        </ul>
10582     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10583     */
10584    public void setAccessibilityLiveRegion(int mode) {
10585        if (mode != getAccessibilityLiveRegion()) {
10586            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10587            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10588                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10589            notifyViewAccessibilityStateChangedIfNeeded(
10590                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10591        }
10592    }
10593
10594    /**
10595     * Gets the live region mode for this View.
10596     *
10597     * @return The live region mode for the view.
10598     *
10599     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10600     *
10601     * @see #setAccessibilityLiveRegion(int)
10602     */
10603    public int getAccessibilityLiveRegion() {
10604        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10605                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10606    }
10607
10608    /**
10609     * Sets how to determine whether this view is important for accessibility
10610     * which is if it fires accessibility events and if it is reported to
10611     * accessibility services that query the screen.
10612     *
10613     * @param mode How to determine whether this view is important for accessibility.
10614     *
10615     * @attr ref android.R.styleable#View_importantForAccessibility
10616     *
10617     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10618     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10619     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10620     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10621     */
10622    public void setImportantForAccessibility(int mode) {
10623        final int oldMode = getImportantForAccessibility();
10624        if (mode != oldMode) {
10625            final boolean hideDescendants =
10626                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10627
10628            // If this node or its descendants are no longer important, try to
10629            // clear accessibility focus.
10630            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10631                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10632                if (focusHost != null) {
10633                    focusHost.clearAccessibilityFocus();
10634                }
10635            }
10636
10637            // If we're moving between AUTO and another state, we might not need
10638            // to send a subtree changed notification. We'll store the computed
10639            // importance, since we'll need to check it later to make sure.
10640            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10641                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10642            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10643            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10644            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10645                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10646            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10647                notifySubtreeAccessibilityStateChangedIfNeeded();
10648            } else {
10649                notifyViewAccessibilityStateChangedIfNeeded(
10650                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10651            }
10652        }
10653    }
10654
10655    /**
10656     * Returns the view within this view's hierarchy that is hosting
10657     * accessibility focus.
10658     *
10659     * @param searchDescendants whether to search for focus in descendant views
10660     * @return the view hosting accessibility focus, or {@code null}
10661     */
10662    private View findAccessibilityFocusHost(boolean searchDescendants) {
10663        if (isAccessibilityFocusedViewOrHost()) {
10664            return this;
10665        }
10666
10667        if (searchDescendants) {
10668            final ViewRootImpl viewRoot = getViewRootImpl();
10669            if (viewRoot != null) {
10670                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10671                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10672                    return focusHost;
10673                }
10674            }
10675        }
10676
10677        return null;
10678    }
10679
10680    /**
10681     * Computes whether this view should be exposed for accessibility. In
10682     * general, views that are interactive or provide information are exposed
10683     * while views that serve only as containers are hidden.
10684     * <p>
10685     * If an ancestor of this view has importance
10686     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10687     * returns <code>false</code>.
10688     * <p>
10689     * Otherwise, the value is computed according to the view's
10690     * {@link #getImportantForAccessibility()} value:
10691     * <ol>
10692     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10693     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10694     * </code>
10695     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10696     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10697     * view satisfies any of the following:
10698     * <ul>
10699     * <li>Is actionable, e.g. {@link #isClickable()},
10700     * {@link #isLongClickable()}, or {@link #isFocusable()}
10701     * <li>Has an {@link AccessibilityDelegate}
10702     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10703     * {@link OnKeyListener}, etc.
10704     * <li>Is an accessibility live region, e.g.
10705     * {@link #getAccessibilityLiveRegion()} is not
10706     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10707     * </ul>
10708     * </ol>
10709     *
10710     * @return Whether the view is exposed for accessibility.
10711     * @see #setImportantForAccessibility(int)
10712     * @see #getImportantForAccessibility()
10713     */
10714    public boolean isImportantForAccessibility() {
10715        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10716                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10717        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10718                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10719            return false;
10720        }
10721
10722        // Check parent mode to ensure we're not hidden.
10723        ViewParent parent = mParent;
10724        while (parent instanceof View) {
10725            if (((View) parent).getImportantForAccessibility()
10726                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10727                return false;
10728            }
10729            parent = parent.getParent();
10730        }
10731
10732        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10733                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10734                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10735    }
10736
10737    /**
10738     * Gets the parent for accessibility purposes. Note that the parent for
10739     * accessibility is not necessary the immediate parent. It is the first
10740     * predecessor that is important for accessibility.
10741     *
10742     * @return The parent for accessibility purposes.
10743     */
10744    public ViewParent getParentForAccessibility() {
10745        if (mParent instanceof View) {
10746            View parentView = (View) mParent;
10747            if (parentView.includeForAccessibility()) {
10748                return mParent;
10749            } else {
10750                return mParent.getParentForAccessibility();
10751            }
10752        }
10753        return null;
10754    }
10755
10756    /**
10757     * Adds the children of this View relevant for accessibility to the given list
10758     * as output. Since some Views are not important for accessibility the added
10759     * child views are not necessarily direct children of this view, rather they are
10760     * the first level of descendants important for accessibility.
10761     *
10762     * @param outChildren The output list that will receive children for accessibility.
10763     */
10764    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10765
10766    }
10767
10768    /**
10769     * Whether to regard this view for accessibility. A view is regarded for
10770     * accessibility if it is important for accessibility or the querying
10771     * accessibility service has explicitly requested that view not
10772     * important for accessibility are regarded.
10773     *
10774     * @return Whether to regard the view for accessibility.
10775     *
10776     * @hide
10777     */
10778    public boolean includeForAccessibility() {
10779        if (mAttachInfo != null) {
10780            return (mAttachInfo.mAccessibilityFetchFlags
10781                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10782                    || isImportantForAccessibility();
10783        }
10784        return false;
10785    }
10786
10787    /**
10788     * Returns whether the View is considered actionable from
10789     * accessibility perspective. Such view are important for
10790     * accessibility.
10791     *
10792     * @return True if the view is actionable for accessibility.
10793     *
10794     * @hide
10795     */
10796    public boolean isActionableForAccessibility() {
10797        return (isClickable() || isLongClickable() || isFocusable());
10798    }
10799
10800    /**
10801     * Returns whether the View has registered callbacks which makes it
10802     * important for accessibility.
10803     *
10804     * @return True if the view is actionable for accessibility.
10805     */
10806    private boolean hasListenersForAccessibility() {
10807        ListenerInfo info = getListenerInfo();
10808        return mTouchDelegate != null || info.mOnKeyListener != null
10809                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10810                || info.mOnHoverListener != null || info.mOnDragListener != null;
10811    }
10812
10813    /**
10814     * Notifies that the accessibility state of this view changed. The change
10815     * is local to this view and does not represent structural changes such
10816     * as children and parent. For example, the view became focusable. The
10817     * notification is at at most once every
10818     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10819     * to avoid unnecessary load to the system. Also once a view has a pending
10820     * notification this method is a NOP until the notification has been sent.
10821     *
10822     * @hide
10823     */
10824    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10825        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10826            return;
10827        }
10828        if (mSendViewStateChangedAccessibilityEvent == null) {
10829            mSendViewStateChangedAccessibilityEvent =
10830                    new SendViewStateChangedAccessibilityEvent();
10831        }
10832        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10833    }
10834
10835    /**
10836     * Notifies that the accessibility state of this view changed. The change
10837     * is *not* local to this view and does represent structural changes such
10838     * as children and parent. For example, the view size changed. The
10839     * notification is at at most once every
10840     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10841     * to avoid unnecessary load to the system. Also once a view has a pending
10842     * notification this method is a NOP until the notification has been sent.
10843     *
10844     * @hide
10845     */
10846    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10847        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10848            return;
10849        }
10850        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10851            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10852            if (mParent != null) {
10853                try {
10854                    mParent.notifySubtreeAccessibilityStateChanged(
10855                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10856                } catch (AbstractMethodError e) {
10857                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10858                            " does not fully implement ViewParent", e);
10859                }
10860            }
10861        }
10862    }
10863
10864    /**
10865     * Change the visibility of the View without triggering any other changes. This is
10866     * important for transitions, where visibility changes should not adjust focus or
10867     * trigger a new layout. This is only used when the visibility has already been changed
10868     * and we need a transient value during an animation. When the animation completes,
10869     * the original visibility value is always restored.
10870     *
10871     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10872     * @hide
10873     */
10874    public void setTransitionVisibility(@Visibility int visibility) {
10875        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10876    }
10877
10878    /**
10879     * Reset the flag indicating the accessibility state of the subtree rooted
10880     * at this view changed.
10881     */
10882    void resetSubtreeAccessibilityStateChanged() {
10883        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10884    }
10885
10886    /**
10887     * Report an accessibility action to this view's parents for delegated processing.
10888     *
10889     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10890     * call this method to delegate an accessibility action to a supporting parent. If the parent
10891     * returns true from its
10892     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10893     * method this method will return true to signify that the action was consumed.</p>
10894     *
10895     * <p>This method is useful for implementing nested scrolling child views. If
10896     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10897     * a custom view implementation may invoke this method to allow a parent to consume the
10898     * scroll first. If this method returns true the custom view should skip its own scrolling
10899     * behavior.</p>
10900     *
10901     * @param action Accessibility action to delegate
10902     * @param arguments Optional action arguments
10903     * @return true if the action was consumed by a parent
10904     */
10905    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10906        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10907            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10908                return true;
10909            }
10910        }
10911        return false;
10912    }
10913
10914    /**
10915     * Performs the specified accessibility action on the view. For
10916     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10917     * <p>
10918     * If an {@link AccessibilityDelegate} has been specified via calling
10919     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10920     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10921     * is responsible for handling this call.
10922     * </p>
10923     *
10924     * <p>The default implementation will delegate
10925     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10926     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10927     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10928     *
10929     * @param action The action to perform.
10930     * @param arguments Optional action arguments.
10931     * @return Whether the action was performed.
10932     */
10933    public boolean performAccessibilityAction(int action, Bundle arguments) {
10934      if (mAccessibilityDelegate != null) {
10935          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10936      } else {
10937          return performAccessibilityActionInternal(action, arguments);
10938      }
10939    }
10940
10941   /**
10942    * @see #performAccessibilityAction(int, Bundle)
10943    *
10944    * Note: Called from the default {@link AccessibilityDelegate}.
10945    *
10946    * @hide
10947    */
10948    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10949        if (isNestedScrollingEnabled()
10950                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10951                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10952                || action == R.id.accessibilityActionScrollUp
10953                || action == R.id.accessibilityActionScrollLeft
10954                || action == R.id.accessibilityActionScrollDown
10955                || action == R.id.accessibilityActionScrollRight)) {
10956            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10957                return true;
10958            }
10959        }
10960
10961        switch (action) {
10962            case AccessibilityNodeInfo.ACTION_CLICK: {
10963                if (isClickable()) {
10964                    performClick();
10965                    return true;
10966                }
10967            } break;
10968            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10969                if (isLongClickable()) {
10970                    performLongClick();
10971                    return true;
10972                }
10973            } break;
10974            case AccessibilityNodeInfo.ACTION_FOCUS: {
10975                if (!hasFocus()) {
10976                    // Get out of touch mode since accessibility
10977                    // wants to move focus around.
10978                    getViewRootImpl().ensureTouchMode(false);
10979                    return requestFocus();
10980                }
10981            } break;
10982            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10983                if (hasFocus()) {
10984                    clearFocus();
10985                    return !isFocused();
10986                }
10987            } break;
10988            case AccessibilityNodeInfo.ACTION_SELECT: {
10989                if (!isSelected()) {
10990                    setSelected(true);
10991                    return isSelected();
10992                }
10993            } break;
10994            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10995                if (isSelected()) {
10996                    setSelected(false);
10997                    return !isSelected();
10998                }
10999            } break;
11000            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11001                if (!isAccessibilityFocused()) {
11002                    return requestAccessibilityFocus();
11003                }
11004            } break;
11005            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11006                if (isAccessibilityFocused()) {
11007                    clearAccessibilityFocus();
11008                    return true;
11009                }
11010            } break;
11011            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11012                if (arguments != null) {
11013                    final int granularity = arguments.getInt(
11014                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11015                    final boolean extendSelection = arguments.getBoolean(
11016                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11017                    return traverseAtGranularity(granularity, true, extendSelection);
11018                }
11019            } break;
11020            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11021                if (arguments != null) {
11022                    final int granularity = arguments.getInt(
11023                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11024                    final boolean extendSelection = arguments.getBoolean(
11025                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11026                    return traverseAtGranularity(granularity, false, extendSelection);
11027                }
11028            } break;
11029            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11030                CharSequence text = getIterableTextForAccessibility();
11031                if (text == null) {
11032                    return false;
11033                }
11034                final int start = (arguments != null) ? arguments.getInt(
11035                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11036                final int end = (arguments != null) ? arguments.getInt(
11037                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11038                // Only cursor position can be specified (selection length == 0)
11039                if ((getAccessibilitySelectionStart() != start
11040                        || getAccessibilitySelectionEnd() != end)
11041                        && (start == end)) {
11042                    setAccessibilitySelection(start, end);
11043                    notifyViewAccessibilityStateChangedIfNeeded(
11044                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11045                    return true;
11046                }
11047            } break;
11048            case R.id.accessibilityActionShowOnScreen: {
11049                if (mAttachInfo != null) {
11050                    final Rect r = mAttachInfo.mTmpInvalRect;
11051                    getDrawingRect(r);
11052                    return requestRectangleOnScreen(r, true);
11053                }
11054            } break;
11055            case R.id.accessibilityActionContextClick: {
11056                if (isContextClickable()) {
11057                    performContextClick();
11058                    return true;
11059                }
11060            } break;
11061        }
11062        return false;
11063    }
11064
11065    private boolean traverseAtGranularity(int granularity, boolean forward,
11066            boolean extendSelection) {
11067        CharSequence text = getIterableTextForAccessibility();
11068        if (text == null || text.length() == 0) {
11069            return false;
11070        }
11071        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11072        if (iterator == null) {
11073            return false;
11074        }
11075        int current = getAccessibilitySelectionEnd();
11076        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11077            current = forward ? 0 : text.length();
11078        }
11079        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11080        if (range == null) {
11081            return false;
11082        }
11083        final int segmentStart = range[0];
11084        final int segmentEnd = range[1];
11085        int selectionStart;
11086        int selectionEnd;
11087        if (extendSelection && isAccessibilitySelectionExtendable()) {
11088            selectionStart = getAccessibilitySelectionStart();
11089            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11090                selectionStart = forward ? segmentStart : segmentEnd;
11091            }
11092            selectionEnd = forward ? segmentEnd : segmentStart;
11093        } else {
11094            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11095        }
11096        setAccessibilitySelection(selectionStart, selectionEnd);
11097        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11098                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11099        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11100        return true;
11101    }
11102
11103    /**
11104     * Gets the text reported for accessibility purposes.
11105     *
11106     * @return The accessibility text.
11107     *
11108     * @hide
11109     */
11110    public CharSequence getIterableTextForAccessibility() {
11111        return getContentDescription();
11112    }
11113
11114    /**
11115     * Gets whether accessibility selection can be extended.
11116     *
11117     * @return If selection is extensible.
11118     *
11119     * @hide
11120     */
11121    public boolean isAccessibilitySelectionExtendable() {
11122        return false;
11123    }
11124
11125    /**
11126     * @hide
11127     */
11128    public int getAccessibilitySelectionStart() {
11129        return mAccessibilityCursorPosition;
11130    }
11131
11132    /**
11133     * @hide
11134     */
11135    public int getAccessibilitySelectionEnd() {
11136        return getAccessibilitySelectionStart();
11137    }
11138
11139    /**
11140     * @hide
11141     */
11142    public void setAccessibilitySelection(int start, int end) {
11143        if (start ==  end && end == mAccessibilityCursorPosition) {
11144            return;
11145        }
11146        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11147            mAccessibilityCursorPosition = start;
11148        } else {
11149            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11150        }
11151        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11152    }
11153
11154    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11155            int fromIndex, int toIndex) {
11156        if (mParent == null) {
11157            return;
11158        }
11159        AccessibilityEvent event = AccessibilityEvent.obtain(
11160                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11161        onInitializeAccessibilityEvent(event);
11162        onPopulateAccessibilityEvent(event);
11163        event.setFromIndex(fromIndex);
11164        event.setToIndex(toIndex);
11165        event.setAction(action);
11166        event.setMovementGranularity(granularity);
11167        mParent.requestSendAccessibilityEvent(this, event);
11168    }
11169
11170    /**
11171     * @hide
11172     */
11173    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11174        switch (granularity) {
11175            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11176                CharSequence text = getIterableTextForAccessibility();
11177                if (text != null && text.length() > 0) {
11178                    CharacterTextSegmentIterator iterator =
11179                        CharacterTextSegmentIterator.getInstance(
11180                                mContext.getResources().getConfiguration().locale);
11181                    iterator.initialize(text.toString());
11182                    return iterator;
11183                }
11184            } break;
11185            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11186                CharSequence text = getIterableTextForAccessibility();
11187                if (text != null && text.length() > 0) {
11188                    WordTextSegmentIterator iterator =
11189                        WordTextSegmentIterator.getInstance(
11190                                mContext.getResources().getConfiguration().locale);
11191                    iterator.initialize(text.toString());
11192                    return iterator;
11193                }
11194            } break;
11195            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11196                CharSequence text = getIterableTextForAccessibility();
11197                if (text != null && text.length() > 0) {
11198                    ParagraphTextSegmentIterator iterator =
11199                        ParagraphTextSegmentIterator.getInstance();
11200                    iterator.initialize(text.toString());
11201                    return iterator;
11202                }
11203            } break;
11204        }
11205        return null;
11206    }
11207
11208    /**
11209     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11210     * and {@link #onFinishTemporaryDetach()}.
11211     *
11212     * <p>This method always returns {@code true} when called directly or indirectly from
11213     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11214     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11215     * <ul>
11216     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11217     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11218     * </ul>
11219     * </p>
11220     *
11221     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11222     * and {@link #onFinishTemporaryDetach()}.
11223     */
11224    public final boolean isTemporarilyDetached() {
11225        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11226    }
11227
11228    /**
11229     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11230     * a container View.
11231     */
11232    @CallSuper
11233    public void dispatchStartTemporaryDetach() {
11234        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11235        notifyEnterOrExitForAutoFillIfNeeded(false);
11236        onStartTemporaryDetach();
11237    }
11238
11239    /**
11240     * This is called when a container is going to temporarily detach a child, with
11241     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11242     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11243     * {@link #onDetachedFromWindow()} when the container is done.
11244     */
11245    public void onStartTemporaryDetach() {
11246        removeUnsetPressCallback();
11247        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11248    }
11249
11250    /**
11251     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11252     * a container View.
11253     */
11254    @CallSuper
11255    public void dispatchFinishTemporaryDetach() {
11256        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11257        onFinishTemporaryDetach();
11258        if (hasWindowFocus() && hasFocus()) {
11259            InputMethodManager.getInstance().focusIn(this);
11260        }
11261        notifyEnterOrExitForAutoFillIfNeeded(true);
11262    }
11263
11264    /**
11265     * Called after {@link #onStartTemporaryDetach} when the container is done
11266     * changing the view.
11267     */
11268    public void onFinishTemporaryDetach() {
11269    }
11270
11271    /**
11272     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11273     * for this view's window.  Returns null if the view is not currently attached
11274     * to the window.  Normally you will not need to use this directly, but
11275     * just use the standard high-level event callbacks like
11276     * {@link #onKeyDown(int, KeyEvent)}.
11277     */
11278    public KeyEvent.DispatcherState getKeyDispatcherState() {
11279        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11280    }
11281
11282    /**
11283     * Dispatch a key event before it is processed by any input method
11284     * associated with the view hierarchy.  This can be used to intercept
11285     * key events in special situations before the IME consumes them; a
11286     * typical example would be handling the BACK key to update the application's
11287     * UI instead of allowing the IME to see it and close itself.
11288     *
11289     * @param event The key event to be dispatched.
11290     * @return True if the event was handled, false otherwise.
11291     */
11292    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11293        return onKeyPreIme(event.getKeyCode(), event);
11294    }
11295
11296    /**
11297     * Dispatch a key event to the next view on the focus path. This path runs
11298     * from the top of the view tree down to the currently focused view. If this
11299     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11300     * the next node down the focus path. This method also fires any key
11301     * listeners.
11302     *
11303     * @param event The key event to be dispatched.
11304     * @return True if the event was handled, false otherwise.
11305     */
11306    public boolean dispatchKeyEvent(KeyEvent event) {
11307        if (mInputEventConsistencyVerifier != null) {
11308            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11309        }
11310
11311        // Give any attached key listener a first crack at the event.
11312        //noinspection SimplifiableIfStatement
11313        ListenerInfo li = mListenerInfo;
11314        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11315                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11316            return true;
11317        }
11318
11319        if (event.dispatch(this, mAttachInfo != null
11320                ? mAttachInfo.mKeyDispatchState : null, this)) {
11321            return true;
11322        }
11323
11324        if (mInputEventConsistencyVerifier != null) {
11325            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11326        }
11327        return false;
11328    }
11329
11330    /**
11331     * Dispatches a key shortcut event.
11332     *
11333     * @param event The key event to be dispatched.
11334     * @return True if the event was handled by the view, false otherwise.
11335     */
11336    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11337        return onKeyShortcut(event.getKeyCode(), event);
11338    }
11339
11340    /**
11341     * Pass the touch screen motion event down to the target view, or this
11342     * view if it is the target.
11343     *
11344     * @param event The motion event to be dispatched.
11345     * @return True if the event was handled by the view, false otherwise.
11346     */
11347    public boolean dispatchTouchEvent(MotionEvent event) {
11348        // If the event should be handled by accessibility focus first.
11349        if (event.isTargetAccessibilityFocus()) {
11350            // We don't have focus or no virtual descendant has it, do not handle the event.
11351            if (!isAccessibilityFocusedViewOrHost()) {
11352                return false;
11353            }
11354            // We have focus and got the event, then use normal event dispatch.
11355            event.setTargetAccessibilityFocus(false);
11356        }
11357
11358        boolean result = false;
11359
11360        if (mInputEventConsistencyVerifier != null) {
11361            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11362        }
11363
11364        final int actionMasked = event.getActionMasked();
11365        if (actionMasked == MotionEvent.ACTION_DOWN) {
11366            // Defensive cleanup for new gesture
11367            stopNestedScroll();
11368        }
11369
11370        if (onFilterTouchEventForSecurity(event)) {
11371            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11372                result = true;
11373            }
11374            //noinspection SimplifiableIfStatement
11375            ListenerInfo li = mListenerInfo;
11376            if (li != null && li.mOnTouchListener != null
11377                    && (mViewFlags & ENABLED_MASK) == ENABLED
11378                    && li.mOnTouchListener.onTouch(this, event)) {
11379                result = true;
11380            }
11381
11382            if (!result && onTouchEvent(event)) {
11383                result = true;
11384            }
11385        }
11386
11387        if (!result && mInputEventConsistencyVerifier != null) {
11388            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11389        }
11390
11391        // Clean up after nested scrolls if this is the end of a gesture;
11392        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11393        // of the gesture.
11394        if (actionMasked == MotionEvent.ACTION_UP ||
11395                actionMasked == MotionEvent.ACTION_CANCEL ||
11396                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11397            stopNestedScroll();
11398        }
11399
11400        return result;
11401    }
11402
11403    boolean isAccessibilityFocusedViewOrHost() {
11404        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11405                .getAccessibilityFocusedHost() == this);
11406    }
11407
11408    /**
11409     * Filter the touch event to apply security policies.
11410     *
11411     * @param event The motion event to be filtered.
11412     * @return True if the event should be dispatched, false if the event should be dropped.
11413     *
11414     * @see #getFilterTouchesWhenObscured
11415     */
11416    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11417        //noinspection RedundantIfStatement
11418        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11419                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11420            // Window is obscured, drop this touch.
11421            return false;
11422        }
11423        return true;
11424    }
11425
11426    /**
11427     * Pass a trackball motion event down to the focused view.
11428     *
11429     * @param event The motion event to be dispatched.
11430     * @return True if the event was handled by the view, false otherwise.
11431     */
11432    public boolean dispatchTrackballEvent(MotionEvent event) {
11433        if (mInputEventConsistencyVerifier != null) {
11434            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11435        }
11436
11437        return onTrackballEvent(event);
11438    }
11439
11440    /**
11441     * Pass a captured pointer event down to the focused view.
11442     *
11443     * @param event The motion event to be dispatched.
11444     * @return True if the event was handled by the view, false otherwise.
11445     */
11446    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11447        if (!hasPointerCapture()) {
11448            return false;
11449        }
11450        //noinspection SimplifiableIfStatement
11451        ListenerInfo li = mListenerInfo;
11452        if (li != null && li.mOnCapturedPointerListener != null
11453                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11454            return true;
11455        }
11456        return onCapturedPointerEvent(event);
11457    }
11458
11459    /**
11460     * Dispatch a generic motion event.
11461     * <p>
11462     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11463     * are delivered to the view under the pointer.  All other generic motion events are
11464     * delivered to the focused view.  Hover events are handled specially and are delivered
11465     * to {@link #onHoverEvent(MotionEvent)}.
11466     * </p>
11467     *
11468     * @param event The motion event to be dispatched.
11469     * @return True if the event was handled by the view, false otherwise.
11470     */
11471    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11472        if (mInputEventConsistencyVerifier != null) {
11473            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11474        }
11475
11476        final int source = event.getSource();
11477        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11478            final int action = event.getAction();
11479            if (action == MotionEvent.ACTION_HOVER_ENTER
11480                    || action == MotionEvent.ACTION_HOVER_MOVE
11481                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11482                if (dispatchHoverEvent(event)) {
11483                    return true;
11484                }
11485            } else if (dispatchGenericPointerEvent(event)) {
11486                return true;
11487            }
11488        } else if (dispatchGenericFocusedEvent(event)) {
11489            return true;
11490        }
11491
11492        if (dispatchGenericMotionEventInternal(event)) {
11493            return true;
11494        }
11495
11496        if (mInputEventConsistencyVerifier != null) {
11497            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11498        }
11499        return false;
11500    }
11501
11502    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11503        //noinspection SimplifiableIfStatement
11504        ListenerInfo li = mListenerInfo;
11505        if (li != null && li.mOnGenericMotionListener != null
11506                && (mViewFlags & ENABLED_MASK) == ENABLED
11507                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11508            return true;
11509        }
11510
11511        if (onGenericMotionEvent(event)) {
11512            return true;
11513        }
11514
11515        final int actionButton = event.getActionButton();
11516        switch (event.getActionMasked()) {
11517            case MotionEvent.ACTION_BUTTON_PRESS:
11518                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11519                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11520                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11521                    if (performContextClick(event.getX(), event.getY())) {
11522                        mInContextButtonPress = true;
11523                        setPressed(true, event.getX(), event.getY());
11524                        removeTapCallback();
11525                        removeLongPressCallback();
11526                        return true;
11527                    }
11528                }
11529                break;
11530
11531            case MotionEvent.ACTION_BUTTON_RELEASE:
11532                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11533                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11534                    mInContextButtonPress = false;
11535                    mIgnoreNextUpEvent = true;
11536                }
11537                break;
11538        }
11539
11540        if (mInputEventConsistencyVerifier != null) {
11541            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11542        }
11543        return false;
11544    }
11545
11546    /**
11547     * Dispatch a hover event.
11548     * <p>
11549     * Do not call this method directly.
11550     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11551     * </p>
11552     *
11553     * @param event The motion event to be dispatched.
11554     * @return True if the event was handled by the view, false otherwise.
11555     */
11556    protected boolean dispatchHoverEvent(MotionEvent event) {
11557        ListenerInfo li = mListenerInfo;
11558        //noinspection SimplifiableIfStatement
11559        if (li != null && li.mOnHoverListener != null
11560                && (mViewFlags & ENABLED_MASK) == ENABLED
11561                && li.mOnHoverListener.onHover(this, event)) {
11562            return true;
11563        }
11564
11565        return onHoverEvent(event);
11566    }
11567
11568    /**
11569     * Returns true if the view has a child to which it has recently sent
11570     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11571     * it does not have a hovered child, then it must be the innermost hovered view.
11572     * @hide
11573     */
11574    protected boolean hasHoveredChild() {
11575        return false;
11576    }
11577
11578    /**
11579     * Dispatch a generic motion event to the view under the first pointer.
11580     * <p>
11581     * Do not call this method directly.
11582     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11583     * </p>
11584     *
11585     * @param event The motion event to be dispatched.
11586     * @return True if the event was handled by the view, false otherwise.
11587     */
11588    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11589        return false;
11590    }
11591
11592    /**
11593     * Dispatch a generic motion event to the currently focused view.
11594     * <p>
11595     * Do not call this method directly.
11596     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11597     * </p>
11598     *
11599     * @param event The motion event to be dispatched.
11600     * @return True if the event was handled by the view, false otherwise.
11601     */
11602    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11603        return false;
11604    }
11605
11606    /**
11607     * Dispatch a pointer event.
11608     * <p>
11609     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11610     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11611     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11612     * and should not be expected to handle other pointing device features.
11613     * </p>
11614     *
11615     * @param event The motion event to be dispatched.
11616     * @return True if the event was handled by the view, false otherwise.
11617     * @hide
11618     */
11619    public final boolean dispatchPointerEvent(MotionEvent event) {
11620        if (event.isTouchEvent()) {
11621            return dispatchTouchEvent(event);
11622        } else {
11623            return dispatchGenericMotionEvent(event);
11624        }
11625    }
11626
11627    /**
11628     * Called when the window containing this view gains or loses window focus.
11629     * ViewGroups should override to route to their children.
11630     *
11631     * @param hasFocus True if the window containing this view now has focus,
11632     *        false otherwise.
11633     */
11634    public void dispatchWindowFocusChanged(boolean hasFocus) {
11635        onWindowFocusChanged(hasFocus);
11636    }
11637
11638    /**
11639     * Called when the window containing this view gains or loses focus.  Note
11640     * that this is separate from view focus: to receive key events, both
11641     * your view and its window must have focus.  If a window is displayed
11642     * on top of yours that takes input focus, then your own window will lose
11643     * focus but the view focus will remain unchanged.
11644     *
11645     * @param hasWindowFocus True if the window containing this view now has
11646     *        focus, false otherwise.
11647     */
11648    public void onWindowFocusChanged(boolean hasWindowFocus) {
11649        InputMethodManager imm = InputMethodManager.peekInstance();
11650        if (!hasWindowFocus) {
11651            if (isPressed()) {
11652                setPressed(false);
11653            }
11654            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11655            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11656                imm.focusOut(this);
11657            }
11658            removeLongPressCallback();
11659            removeTapCallback();
11660            onFocusLost();
11661        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11662            imm.focusIn(this);
11663        }
11664
11665        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11666
11667        refreshDrawableState();
11668    }
11669
11670    /**
11671     * Returns true if this view is in a window that currently has window focus.
11672     * Note that this is not the same as the view itself having focus.
11673     *
11674     * @return True if this view is in a window that currently has window focus.
11675     */
11676    public boolean hasWindowFocus() {
11677        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11678    }
11679
11680    /**
11681     * Dispatch a view visibility change down the view hierarchy.
11682     * ViewGroups should override to route to their children.
11683     * @param changedView The view whose visibility changed. Could be 'this' or
11684     * an ancestor view.
11685     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11686     * {@link #INVISIBLE} or {@link #GONE}.
11687     */
11688    protected void dispatchVisibilityChanged(@NonNull View changedView,
11689            @Visibility int visibility) {
11690        onVisibilityChanged(changedView, visibility);
11691    }
11692
11693    /**
11694     * Called when the visibility of the view or an ancestor of the view has
11695     * changed.
11696     *
11697     * @param changedView The view whose visibility changed. May be
11698     *                    {@code this} or an ancestor view.
11699     * @param visibility The new visibility, one of {@link #VISIBLE},
11700     *                   {@link #INVISIBLE} or {@link #GONE}.
11701     */
11702    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11703    }
11704
11705    /**
11706     * Dispatch a hint about whether this view is displayed. For instance, when
11707     * a View moves out of the screen, it might receives a display hint indicating
11708     * the view is not displayed. Applications should not <em>rely</em> on this hint
11709     * as there is no guarantee that they will receive one.
11710     *
11711     * @param hint A hint about whether or not this view is displayed:
11712     * {@link #VISIBLE} or {@link #INVISIBLE}.
11713     */
11714    public void dispatchDisplayHint(@Visibility int hint) {
11715        onDisplayHint(hint);
11716    }
11717
11718    /**
11719     * Gives this view a hint about whether is displayed or not. For instance, when
11720     * a View moves out of the screen, it might receives a display hint indicating
11721     * the view is not displayed. Applications should not <em>rely</em> on this hint
11722     * as there is no guarantee that they will receive one.
11723     *
11724     * @param hint A hint about whether or not this view is displayed:
11725     * {@link #VISIBLE} or {@link #INVISIBLE}.
11726     */
11727    protected void onDisplayHint(@Visibility int hint) {
11728    }
11729
11730    /**
11731     * Dispatch a window visibility change down the view hierarchy.
11732     * ViewGroups should override to route to their children.
11733     *
11734     * @param visibility The new visibility of the window.
11735     *
11736     * @see #onWindowVisibilityChanged(int)
11737     */
11738    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11739        onWindowVisibilityChanged(visibility);
11740    }
11741
11742    /**
11743     * Called when the window containing has change its visibility
11744     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11745     * that this tells you whether or not your window is being made visible
11746     * to the window manager; this does <em>not</em> tell you whether or not
11747     * your window is obscured by other windows on the screen, even if it
11748     * is itself visible.
11749     *
11750     * @param visibility The new visibility of the window.
11751     */
11752    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11753        if (visibility == VISIBLE) {
11754            initialAwakenScrollBars();
11755        }
11756    }
11757
11758    /**
11759     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11760     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11761     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11762     *
11763     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11764     *                  ancestors or by window visibility
11765     * @return true if this view is visible to the user, not counting clipping or overlapping
11766     */
11767    boolean dispatchVisibilityAggregated(boolean isVisible) {
11768        final boolean thisVisible = getVisibility() == VISIBLE;
11769        // If we're not visible but something is telling us we are, ignore it.
11770        if (thisVisible || !isVisible) {
11771            onVisibilityAggregated(isVisible);
11772        }
11773        return thisVisible && isVisible;
11774    }
11775
11776    /**
11777     * Called when the user-visibility of this View is potentially affected by a change
11778     * to this view itself, an ancestor view or the window this view is attached to.
11779     *
11780     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11781     *                  and this view's window is also visible
11782     */
11783    @CallSuper
11784    public void onVisibilityAggregated(boolean isVisible) {
11785        if (isVisible && mAttachInfo != null) {
11786            initialAwakenScrollBars();
11787        }
11788
11789        final Drawable dr = mBackground;
11790        if (dr != null && isVisible != dr.isVisible()) {
11791            dr.setVisible(isVisible, false);
11792        }
11793        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11794        if (fg != null && isVisible != fg.isVisible()) {
11795            fg.setVisible(isVisible, false);
11796        }
11797    }
11798
11799    /**
11800     * Returns the current visibility of the window this view is attached to
11801     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11802     *
11803     * @return Returns the current visibility of the view's window.
11804     */
11805    @Visibility
11806    public int getWindowVisibility() {
11807        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11808    }
11809
11810    /**
11811     * Retrieve the overall visible display size in which the window this view is
11812     * attached to has been positioned in.  This takes into account screen
11813     * decorations above the window, for both cases where the window itself
11814     * is being position inside of them or the window is being placed under
11815     * then and covered insets are used for the window to position its content
11816     * inside.  In effect, this tells you the available area where content can
11817     * be placed and remain visible to users.
11818     *
11819     * <p>This function requires an IPC back to the window manager to retrieve
11820     * the requested information, so should not be used in performance critical
11821     * code like drawing.
11822     *
11823     * @param outRect Filled in with the visible display frame.  If the view
11824     * is not attached to a window, this is simply the raw display size.
11825     */
11826    public void getWindowVisibleDisplayFrame(Rect outRect) {
11827        if (mAttachInfo != null) {
11828            try {
11829                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11830            } catch (RemoteException e) {
11831                return;
11832            }
11833            // XXX This is really broken, and probably all needs to be done
11834            // in the window manager, and we need to know more about whether
11835            // we want the area behind or in front of the IME.
11836            final Rect insets = mAttachInfo.mVisibleInsets;
11837            outRect.left += insets.left;
11838            outRect.top += insets.top;
11839            outRect.right -= insets.right;
11840            outRect.bottom -= insets.bottom;
11841            return;
11842        }
11843        // The view is not attached to a display so we don't have a context.
11844        // Make a best guess about the display size.
11845        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11846        d.getRectSize(outRect);
11847    }
11848
11849    /**
11850     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11851     * is currently in without any insets.
11852     *
11853     * @hide
11854     */
11855    public void getWindowDisplayFrame(Rect outRect) {
11856        if (mAttachInfo != null) {
11857            try {
11858                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11859            } catch (RemoteException e) {
11860                return;
11861            }
11862            return;
11863        }
11864        // The view is not attached to a display so we don't have a context.
11865        // Make a best guess about the display size.
11866        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11867        d.getRectSize(outRect);
11868    }
11869
11870    /**
11871     * Dispatch a notification about a resource configuration change down
11872     * the view hierarchy.
11873     * ViewGroups should override to route to their children.
11874     *
11875     * @param newConfig The new resource configuration.
11876     *
11877     * @see #onConfigurationChanged(android.content.res.Configuration)
11878     */
11879    public void dispatchConfigurationChanged(Configuration newConfig) {
11880        onConfigurationChanged(newConfig);
11881    }
11882
11883    /**
11884     * Called when the current configuration of the resources being used
11885     * by the application have changed.  You can use this to decide when
11886     * to reload resources that can changed based on orientation and other
11887     * configuration characteristics.  You only need to use this if you are
11888     * not relying on the normal {@link android.app.Activity} mechanism of
11889     * recreating the activity instance upon a configuration change.
11890     *
11891     * @param newConfig The new resource configuration.
11892     */
11893    protected void onConfigurationChanged(Configuration newConfig) {
11894    }
11895
11896    /**
11897     * Private function to aggregate all per-view attributes in to the view
11898     * root.
11899     */
11900    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11901        performCollectViewAttributes(attachInfo, visibility);
11902    }
11903
11904    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11905        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11906            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11907                attachInfo.mKeepScreenOn = true;
11908            }
11909            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11910            ListenerInfo li = mListenerInfo;
11911            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11912                attachInfo.mHasSystemUiListeners = true;
11913            }
11914        }
11915    }
11916
11917    void needGlobalAttributesUpdate(boolean force) {
11918        final AttachInfo ai = mAttachInfo;
11919        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11920            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11921                    || ai.mHasSystemUiListeners) {
11922                ai.mRecomputeGlobalAttributes = true;
11923            }
11924        }
11925    }
11926
11927    /**
11928     * Returns whether the device is currently in touch mode.  Touch mode is entered
11929     * once the user begins interacting with the device by touch, and affects various
11930     * things like whether focus is always visible to the user.
11931     *
11932     * @return Whether the device is in touch mode.
11933     */
11934    @ViewDebug.ExportedProperty
11935    public boolean isInTouchMode() {
11936        if (mAttachInfo != null) {
11937            return mAttachInfo.mInTouchMode;
11938        } else {
11939            return ViewRootImpl.isInTouchMode();
11940        }
11941    }
11942
11943    /**
11944     * Returns the context the view is running in, through which it can
11945     * access the current theme, resources, etc.
11946     *
11947     * @return The view's Context.
11948     */
11949    @ViewDebug.CapturedViewProperty
11950    public final Context getContext() {
11951        return mContext;
11952    }
11953
11954    /**
11955     * Handle a key event before it is processed by any input method
11956     * associated with the view hierarchy.  This can be used to intercept
11957     * key events in special situations before the IME consumes them; a
11958     * typical example would be handling the BACK key to update the application's
11959     * UI instead of allowing the IME to see it and close itself.
11960     *
11961     * @param keyCode The value in event.getKeyCode().
11962     * @param event Description of the key event.
11963     * @return If you handled the event, return true. If you want to allow the
11964     *         event to be handled by the next receiver, return false.
11965     */
11966    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11967        return false;
11968    }
11969
11970    /**
11971     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11972     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11973     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11974     * is released, if the view is enabled and clickable.
11975     * <p>
11976     * Key presses in software keyboards will generally NOT trigger this
11977     * listener, although some may elect to do so in some situations. Do not
11978     * rely on this to catch software key presses.
11979     *
11980     * @param keyCode a key code that represents the button pressed, from
11981     *                {@link android.view.KeyEvent}
11982     * @param event the KeyEvent object that defines the button action
11983     */
11984    public boolean onKeyDown(int keyCode, KeyEvent event) {
11985        if (KeyEvent.isConfirmKey(keyCode)) {
11986            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11987                return true;
11988            }
11989
11990            if (event.getRepeatCount() == 0) {
11991                // Long clickable items don't necessarily have to be clickable.
11992                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11993                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11994                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11995                    // For the purposes of menu anchoring and drawable hotspots,
11996                    // key events are considered to be at the center of the view.
11997                    final float x = getWidth() / 2f;
11998                    final float y = getHeight() / 2f;
11999                    if (clickable) {
12000                        setPressed(true, x, y);
12001                    }
12002                    checkForLongClick(0, x, y);
12003                    return true;
12004                }
12005            }
12006        }
12007
12008        return false;
12009    }
12010
12011    /**
12012     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12013     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12014     * the event).
12015     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12016     * although some may elect to do so in some situations. Do not rely on this to
12017     * catch software key presses.
12018     */
12019    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12020        return false;
12021    }
12022
12023    /**
12024     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12025     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12026     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12027     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12028     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12029     * although some may elect to do so in some situations. Do not rely on this to
12030     * catch software key presses.
12031     *
12032     * @param keyCode A key code that represents the button pressed, from
12033     *                {@link android.view.KeyEvent}.
12034     * @param event   The KeyEvent object that defines the button action.
12035     */
12036    public boolean onKeyUp(int keyCode, KeyEvent event) {
12037        if (KeyEvent.isConfirmKey(keyCode)) {
12038            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12039                return true;
12040            }
12041            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12042                setPressed(false);
12043
12044                if (!mHasPerformedLongPress) {
12045                    // This is a tap, so remove the longpress check
12046                    removeLongPressCallback();
12047                    if (!event.isCanceled()) {
12048                        return performClick();
12049                    }
12050                }
12051            }
12052        }
12053        return false;
12054    }
12055
12056    /**
12057     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12058     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12059     * the event).
12060     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12061     * although some may elect to do so in some situations. Do not rely on this to
12062     * catch software key presses.
12063     *
12064     * @param keyCode     A key code that represents the button pressed, from
12065     *                    {@link android.view.KeyEvent}.
12066     * @param repeatCount The number of times the action was made.
12067     * @param event       The KeyEvent object that defines the button action.
12068     */
12069    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12070        return false;
12071    }
12072
12073    /**
12074     * Called on the focused view when a key shortcut event is not handled.
12075     * Override this method to implement local key shortcuts for the View.
12076     * Key shortcuts can also be implemented by setting the
12077     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12078     *
12079     * @param keyCode The value in event.getKeyCode().
12080     * @param event Description of the key event.
12081     * @return If you handled the event, return true. If you want to allow the
12082     *         event to be handled by the next receiver, return false.
12083     */
12084    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12085        return false;
12086    }
12087
12088    /**
12089     * Check whether the called view is a text editor, in which case it
12090     * would make sense to automatically display a soft input window for
12091     * it.  Subclasses should override this if they implement
12092     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12093     * a call on that method would return a non-null InputConnection, and
12094     * they are really a first-class editor that the user would normally
12095     * start typing on when the go into a window containing your view.
12096     *
12097     * <p>The default implementation always returns false.  This does
12098     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12099     * will not be called or the user can not otherwise perform edits on your
12100     * view; it is just a hint to the system that this is not the primary
12101     * purpose of this view.
12102     *
12103     * @return Returns true if this view is a text editor, else false.
12104     */
12105    public boolean onCheckIsTextEditor() {
12106        return false;
12107    }
12108
12109    /**
12110     * Create a new InputConnection for an InputMethod to interact
12111     * with the view.  The default implementation returns null, since it doesn't
12112     * support input methods.  You can override this to implement such support.
12113     * This is only needed for views that take focus and text input.
12114     *
12115     * <p>When implementing this, you probably also want to implement
12116     * {@link #onCheckIsTextEditor()} to indicate you will return a
12117     * non-null InputConnection.</p>
12118     *
12119     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12120     * object correctly and in its entirety, so that the connected IME can rely
12121     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12122     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12123     * must be filled in with the correct cursor position for IMEs to work correctly
12124     * with your application.</p>
12125     *
12126     * @param outAttrs Fill in with attribute information about the connection.
12127     */
12128    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12129        return null;
12130    }
12131
12132    /**
12133     * Called by the {@link android.view.inputmethod.InputMethodManager}
12134     * when a view who is not the current
12135     * input connection target is trying to make a call on the manager.  The
12136     * default implementation returns false; you can override this to return
12137     * true for certain views if you are performing InputConnection proxying
12138     * to them.
12139     * @param view The View that is making the InputMethodManager call.
12140     * @return Return true to allow the call, false to reject.
12141     */
12142    public boolean checkInputConnectionProxy(View view) {
12143        return false;
12144    }
12145
12146    /**
12147     * Show the context menu for this view. It is not safe to hold on to the
12148     * menu after returning from this method.
12149     *
12150     * You should normally not overload this method. Overload
12151     * {@link #onCreateContextMenu(ContextMenu)} or define an
12152     * {@link OnCreateContextMenuListener} to add items to the context menu.
12153     *
12154     * @param menu The context menu to populate
12155     */
12156    public void createContextMenu(ContextMenu menu) {
12157        ContextMenuInfo menuInfo = getContextMenuInfo();
12158
12159        // Sets the current menu info so all items added to menu will have
12160        // my extra info set.
12161        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12162
12163        onCreateContextMenu(menu);
12164        ListenerInfo li = mListenerInfo;
12165        if (li != null && li.mOnCreateContextMenuListener != null) {
12166            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12167        }
12168
12169        // Clear the extra information so subsequent items that aren't mine don't
12170        // have my extra info.
12171        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12172
12173        if (mParent != null) {
12174            mParent.createContextMenu(menu);
12175        }
12176    }
12177
12178    /**
12179     * Views should implement this if they have extra information to associate
12180     * with the context menu. The return result is supplied as a parameter to
12181     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12182     * callback.
12183     *
12184     * @return Extra information about the item for which the context menu
12185     *         should be shown. This information will vary across different
12186     *         subclasses of View.
12187     */
12188    protected ContextMenuInfo getContextMenuInfo() {
12189        return null;
12190    }
12191
12192    /**
12193     * Views should implement this if the view itself is going to add items to
12194     * the context menu.
12195     *
12196     * @param menu the context menu to populate
12197     */
12198    protected void onCreateContextMenu(ContextMenu menu) {
12199    }
12200
12201    /**
12202     * Implement this method to handle trackball motion events.  The
12203     * <em>relative</em> movement of the trackball since the last event
12204     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12205     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12206     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12207     * they will often be fractional values, representing the more fine-grained
12208     * movement information available from a trackball).
12209     *
12210     * @param event The motion event.
12211     * @return True if the event was handled, false otherwise.
12212     */
12213    public boolean onTrackballEvent(MotionEvent event) {
12214        return false;
12215    }
12216
12217    /**
12218     * Implement this method to handle generic motion events.
12219     * <p>
12220     * Generic motion events describe joystick movements, mouse hovers, track pad
12221     * touches, scroll wheel movements and other input events.  The
12222     * {@link MotionEvent#getSource() source} of the motion event specifies
12223     * the class of input that was received.  Implementations of this method
12224     * must examine the bits in the source before processing the event.
12225     * The following code example shows how this is done.
12226     * </p><p>
12227     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12228     * are delivered to the view under the pointer.  All other generic motion events are
12229     * delivered to the focused view.
12230     * </p>
12231     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12232     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12233     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12234     *             // process the joystick movement...
12235     *             return true;
12236     *         }
12237     *     }
12238     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12239     *         switch (event.getAction()) {
12240     *             case MotionEvent.ACTION_HOVER_MOVE:
12241     *                 // process the mouse hover movement...
12242     *                 return true;
12243     *             case MotionEvent.ACTION_SCROLL:
12244     *                 // process the scroll wheel movement...
12245     *                 return true;
12246     *         }
12247     *     }
12248     *     return super.onGenericMotionEvent(event);
12249     * }</pre>
12250     *
12251     * @param event The generic motion event being processed.
12252     * @return True if the event was handled, false otherwise.
12253     */
12254    public boolean onGenericMotionEvent(MotionEvent event) {
12255        return false;
12256    }
12257
12258    /**
12259     * Implement this method to handle hover events.
12260     * <p>
12261     * This method is called whenever a pointer is hovering into, over, or out of the
12262     * bounds of a view and the view is not currently being touched.
12263     * Hover events are represented as pointer events with action
12264     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12265     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12266     * </p>
12267     * <ul>
12268     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12269     * when the pointer enters the bounds of the view.</li>
12270     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12271     * when the pointer has already entered the bounds of the view and has moved.</li>
12272     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12273     * when the pointer has exited the bounds of the view or when the pointer is
12274     * about to go down due to a button click, tap, or similar user action that
12275     * causes the view to be touched.</li>
12276     * </ul>
12277     * <p>
12278     * The view should implement this method to return true to indicate that it is
12279     * handling the hover event, such as by changing its drawable state.
12280     * </p><p>
12281     * The default implementation calls {@link #setHovered} to update the hovered state
12282     * of the view when a hover enter or hover exit event is received, if the view
12283     * is enabled and is clickable.  The default implementation also sends hover
12284     * accessibility events.
12285     * </p>
12286     *
12287     * @param event The motion event that describes the hover.
12288     * @return True if the view handled the hover event.
12289     *
12290     * @see #isHovered
12291     * @see #setHovered
12292     * @see #onHoverChanged
12293     */
12294    public boolean onHoverEvent(MotionEvent event) {
12295        // The root view may receive hover (or touch) events that are outside the bounds of
12296        // the window.  This code ensures that we only send accessibility events for
12297        // hovers that are actually within the bounds of the root view.
12298        final int action = event.getActionMasked();
12299        if (!mSendingHoverAccessibilityEvents) {
12300            if ((action == MotionEvent.ACTION_HOVER_ENTER
12301                    || action == MotionEvent.ACTION_HOVER_MOVE)
12302                    && !hasHoveredChild()
12303                    && pointInView(event.getX(), event.getY())) {
12304                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12305                mSendingHoverAccessibilityEvents = true;
12306            }
12307        } else {
12308            if (action == MotionEvent.ACTION_HOVER_EXIT
12309                    || (action == MotionEvent.ACTION_MOVE
12310                            && !pointInView(event.getX(), event.getY()))) {
12311                mSendingHoverAccessibilityEvents = false;
12312                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12313            }
12314        }
12315
12316        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12317                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12318                && isOnScrollbar(event.getX(), event.getY())) {
12319            awakenScrollBars();
12320        }
12321
12322        // If we consider ourself hoverable, or if we we're already hovered,
12323        // handle changing state in response to ENTER and EXIT events.
12324        if (isHoverable() || isHovered()) {
12325            switch (action) {
12326                case MotionEvent.ACTION_HOVER_ENTER:
12327                    setHovered(true);
12328                    break;
12329                case MotionEvent.ACTION_HOVER_EXIT:
12330                    setHovered(false);
12331                    break;
12332            }
12333
12334            // Dispatch the event to onGenericMotionEvent before returning true.
12335            // This is to provide compatibility with existing applications that
12336            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12337            // break because of the new default handling for hoverable views
12338            // in onHoverEvent.
12339            // Note that onGenericMotionEvent will be called by default when
12340            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12341            dispatchGenericMotionEventInternal(event);
12342            // The event was already handled by calling setHovered(), so always
12343            // return true.
12344            return true;
12345        }
12346
12347        return false;
12348    }
12349
12350    /**
12351     * Returns true if the view should handle {@link #onHoverEvent}
12352     * by calling {@link #setHovered} to change its hovered state.
12353     *
12354     * @return True if the view is hoverable.
12355     */
12356    private boolean isHoverable() {
12357        final int viewFlags = mViewFlags;
12358        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12359            return false;
12360        }
12361
12362        return (viewFlags & CLICKABLE) == CLICKABLE
12363                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12364                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12365    }
12366
12367    /**
12368     * Returns true if the view is currently hovered.
12369     *
12370     * @return True if the view is currently hovered.
12371     *
12372     * @see #setHovered
12373     * @see #onHoverChanged
12374     */
12375    @ViewDebug.ExportedProperty
12376    public boolean isHovered() {
12377        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12378    }
12379
12380    /**
12381     * Sets whether the view is currently hovered.
12382     * <p>
12383     * Calling this method also changes the drawable state of the view.  This
12384     * enables the view to react to hover by using different drawable resources
12385     * to change its appearance.
12386     * </p><p>
12387     * The {@link #onHoverChanged} method is called when the hovered state changes.
12388     * </p>
12389     *
12390     * @param hovered True if the view is hovered.
12391     *
12392     * @see #isHovered
12393     * @see #onHoverChanged
12394     */
12395    public void setHovered(boolean hovered) {
12396        if (hovered) {
12397            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12398                mPrivateFlags |= PFLAG_HOVERED;
12399                refreshDrawableState();
12400                onHoverChanged(true);
12401            }
12402        } else {
12403            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12404                mPrivateFlags &= ~PFLAG_HOVERED;
12405                refreshDrawableState();
12406                onHoverChanged(false);
12407            }
12408        }
12409    }
12410
12411    /**
12412     * Implement this method to handle hover state changes.
12413     * <p>
12414     * This method is called whenever the hover state changes as a result of a
12415     * call to {@link #setHovered}.
12416     * </p>
12417     *
12418     * @param hovered The current hover state, as returned by {@link #isHovered}.
12419     *
12420     * @see #isHovered
12421     * @see #setHovered
12422     */
12423    public void onHoverChanged(boolean hovered) {
12424    }
12425
12426    /**
12427     * Handles scroll bar dragging by mouse input.
12428     *
12429     * @hide
12430     * @param event The motion event.
12431     *
12432     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12433     */
12434    protected boolean handleScrollBarDragging(MotionEvent event) {
12435        if (mScrollCache == null) {
12436            return false;
12437        }
12438        final float x = event.getX();
12439        final float y = event.getY();
12440        final int action = event.getAction();
12441        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12442                && action != MotionEvent.ACTION_DOWN)
12443                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12444                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12445            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12446            return false;
12447        }
12448
12449        switch (action) {
12450            case MotionEvent.ACTION_MOVE:
12451                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12452                    return false;
12453                }
12454                if (mScrollCache.mScrollBarDraggingState
12455                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12456                    final Rect bounds = mScrollCache.mScrollBarBounds;
12457                    getVerticalScrollBarBounds(bounds, null);
12458                    final int range = computeVerticalScrollRange();
12459                    final int offset = computeVerticalScrollOffset();
12460                    final int extent = computeVerticalScrollExtent();
12461
12462                    final int thumbLength = ScrollBarUtils.getThumbLength(
12463                            bounds.height(), bounds.width(), extent, range);
12464                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12465                            bounds.height(), thumbLength, extent, range, offset);
12466
12467                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12468                    final float maxThumbOffset = bounds.height() - thumbLength;
12469                    final float newThumbOffset =
12470                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12471                    final int height = getHeight();
12472                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12473                            && height > 0 && extent > 0) {
12474                        final int newY = Math.round((range - extent)
12475                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12476                        if (newY != getScrollY()) {
12477                            mScrollCache.mScrollBarDraggingPos = y;
12478                            setScrollY(newY);
12479                        }
12480                    }
12481                    return true;
12482                }
12483                if (mScrollCache.mScrollBarDraggingState
12484                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12485                    final Rect bounds = mScrollCache.mScrollBarBounds;
12486                    getHorizontalScrollBarBounds(bounds, null);
12487                    final int range = computeHorizontalScrollRange();
12488                    final int offset = computeHorizontalScrollOffset();
12489                    final int extent = computeHorizontalScrollExtent();
12490
12491                    final int thumbLength = ScrollBarUtils.getThumbLength(
12492                            bounds.width(), bounds.height(), extent, range);
12493                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12494                            bounds.width(), thumbLength, extent, range, offset);
12495
12496                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12497                    final float maxThumbOffset = bounds.width() - thumbLength;
12498                    final float newThumbOffset =
12499                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12500                    final int width = getWidth();
12501                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12502                            && width > 0 && extent > 0) {
12503                        final int newX = Math.round((range - extent)
12504                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12505                        if (newX != getScrollX()) {
12506                            mScrollCache.mScrollBarDraggingPos = x;
12507                            setScrollX(newX);
12508                        }
12509                    }
12510                    return true;
12511                }
12512            case MotionEvent.ACTION_DOWN:
12513                if (mScrollCache.state == ScrollabilityCache.OFF) {
12514                    return false;
12515                }
12516                if (isOnVerticalScrollbarThumb(x, y)) {
12517                    mScrollCache.mScrollBarDraggingState =
12518                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12519                    mScrollCache.mScrollBarDraggingPos = y;
12520                    return true;
12521                }
12522                if (isOnHorizontalScrollbarThumb(x, y)) {
12523                    mScrollCache.mScrollBarDraggingState =
12524                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12525                    mScrollCache.mScrollBarDraggingPos = x;
12526                    return true;
12527                }
12528        }
12529        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12530        return false;
12531    }
12532
12533    /**
12534     * Implement this method to handle touch screen motion events.
12535     * <p>
12536     * If this method is used to detect click actions, it is recommended that
12537     * the actions be performed by implementing and calling
12538     * {@link #performClick()}. This will ensure consistent system behavior,
12539     * including:
12540     * <ul>
12541     * <li>obeying click sound preferences
12542     * <li>dispatching OnClickListener calls
12543     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12544     * accessibility features are enabled
12545     * </ul>
12546     *
12547     * @param event The motion event.
12548     * @return True if the event was handled, false otherwise.
12549     */
12550    public boolean onTouchEvent(MotionEvent event) {
12551        final float x = event.getX();
12552        final float y = event.getY();
12553        final int viewFlags = mViewFlags;
12554        final int action = event.getAction();
12555
12556        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12557                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12558                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12559
12560        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12561            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12562                setPressed(false);
12563            }
12564            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12565            // A disabled view that is clickable still consumes the touch
12566            // events, it just doesn't respond to them.
12567            return clickable;
12568        }
12569        if (mTouchDelegate != null) {
12570            if (mTouchDelegate.onTouchEvent(event)) {
12571                return true;
12572            }
12573        }
12574
12575        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12576            switch (action) {
12577                case MotionEvent.ACTION_UP:
12578                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12579                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12580                        handleTooltipUp();
12581                    }
12582                    if (!clickable) {
12583                        removeTapCallback();
12584                        removeLongPressCallback();
12585                        mInContextButtonPress = false;
12586                        mHasPerformedLongPress = false;
12587                        mIgnoreNextUpEvent = false;
12588                        break;
12589                    }
12590                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12591                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12592                        // take focus if we don't have it already and we should in
12593                        // touch mode.
12594                        boolean focusTaken = false;
12595                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12596                            focusTaken = requestFocus();
12597                        }
12598
12599                        if (prepressed) {
12600                            // The button is being released before we actually
12601                            // showed it as pressed.  Make it show the pressed
12602                            // state now (before scheduling the click) to ensure
12603                            // the user sees it.
12604                            setPressed(true, x, y);
12605                        }
12606
12607                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12608                            // This is a tap, so remove the longpress check
12609                            removeLongPressCallback();
12610
12611                            // Only perform take click actions if we were in the pressed state
12612                            if (!focusTaken) {
12613                                // Use a Runnable and post this rather than calling
12614                                // performClick directly. This lets other visual state
12615                                // of the view update before click actions start.
12616                                if (mPerformClick == null) {
12617                                    mPerformClick = new PerformClick();
12618                                }
12619                                if (!post(mPerformClick)) {
12620                                    performClick();
12621                                }
12622                            }
12623                        }
12624
12625                        if (mUnsetPressedState == null) {
12626                            mUnsetPressedState = new UnsetPressedState();
12627                        }
12628
12629                        if (prepressed) {
12630                            postDelayed(mUnsetPressedState,
12631                                    ViewConfiguration.getPressedStateDuration());
12632                        } else if (!post(mUnsetPressedState)) {
12633                            // If the post failed, unpress right now
12634                            mUnsetPressedState.run();
12635                        }
12636
12637                        removeTapCallback();
12638                    }
12639                    mIgnoreNextUpEvent = false;
12640                    break;
12641
12642                case MotionEvent.ACTION_DOWN:
12643                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12644                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12645                    }
12646                    mHasPerformedLongPress = false;
12647
12648                    if (!clickable) {
12649                        checkForLongClick(0, x, y);
12650                        break;
12651                    }
12652
12653                    if (performButtonActionOnTouchDown(event)) {
12654                        break;
12655                    }
12656
12657                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12658                    boolean isInScrollingContainer = isInScrollingContainer();
12659
12660                    // For views inside a scrolling container, delay the pressed feedback for
12661                    // a short period in case this is a scroll.
12662                    if (isInScrollingContainer) {
12663                        mPrivateFlags |= PFLAG_PREPRESSED;
12664                        if (mPendingCheckForTap == null) {
12665                            mPendingCheckForTap = new CheckForTap();
12666                        }
12667                        mPendingCheckForTap.x = event.getX();
12668                        mPendingCheckForTap.y = event.getY();
12669                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12670                    } else {
12671                        // Not inside a scrolling container, so show the feedback right away
12672                        setPressed(true, x, y);
12673                        checkForLongClick(0, x, y);
12674                    }
12675                    break;
12676
12677                case MotionEvent.ACTION_CANCEL:
12678                    if (clickable) {
12679                        setPressed(false);
12680                    }
12681                    removeTapCallback();
12682                    removeLongPressCallback();
12683                    mInContextButtonPress = false;
12684                    mHasPerformedLongPress = false;
12685                    mIgnoreNextUpEvent = false;
12686                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12687                    break;
12688
12689                case MotionEvent.ACTION_MOVE:
12690                    if (clickable) {
12691                        drawableHotspotChanged(x, y);
12692                    }
12693
12694                    // Be lenient about moving outside of buttons
12695                    if (!pointInView(x, y, mTouchSlop)) {
12696                        // Outside button
12697                        // Remove any future long press/tap checks
12698                        removeTapCallback();
12699                        removeLongPressCallback();
12700                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12701                            setPressed(false);
12702                        }
12703                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12704                    }
12705                    break;
12706            }
12707
12708            return true;
12709        }
12710
12711        return false;
12712    }
12713
12714    /**
12715     * @hide
12716     */
12717    public boolean isInScrollingContainer() {
12718        ViewParent p = getParent();
12719        while (p != null && p instanceof ViewGroup) {
12720            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12721                return true;
12722            }
12723            p = p.getParent();
12724        }
12725        return false;
12726    }
12727
12728    /**
12729     * Remove the longpress detection timer.
12730     */
12731    private void removeLongPressCallback() {
12732        if (mPendingCheckForLongPress != null) {
12733            removeCallbacks(mPendingCheckForLongPress);
12734        }
12735    }
12736
12737    /**
12738     * Remove the pending click action
12739     */
12740    private void removePerformClickCallback() {
12741        if (mPerformClick != null) {
12742            removeCallbacks(mPerformClick);
12743        }
12744    }
12745
12746    /**
12747     * Remove the prepress detection timer.
12748     */
12749    private void removeUnsetPressCallback() {
12750        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12751            setPressed(false);
12752            removeCallbacks(mUnsetPressedState);
12753        }
12754    }
12755
12756    /**
12757     * Remove the tap detection timer.
12758     */
12759    private void removeTapCallback() {
12760        if (mPendingCheckForTap != null) {
12761            mPrivateFlags &= ~PFLAG_PREPRESSED;
12762            removeCallbacks(mPendingCheckForTap);
12763        }
12764    }
12765
12766    /**
12767     * Cancels a pending long press.  Your subclass can use this if you
12768     * want the context menu to come up if the user presses and holds
12769     * at the same place, but you don't want it to come up if they press
12770     * and then move around enough to cause scrolling.
12771     */
12772    public void cancelLongPress() {
12773        removeLongPressCallback();
12774
12775        /*
12776         * The prepressed state handled by the tap callback is a display
12777         * construct, but the tap callback will post a long press callback
12778         * less its own timeout. Remove it here.
12779         */
12780        removeTapCallback();
12781    }
12782
12783    /**
12784     * Remove the pending callback for sending a
12785     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12786     */
12787    private void removeSendViewScrolledAccessibilityEventCallback() {
12788        if (mSendViewScrolledAccessibilityEvent != null) {
12789            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12790            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12791        }
12792    }
12793
12794    /**
12795     * Sets the TouchDelegate for this View.
12796     */
12797    public void setTouchDelegate(TouchDelegate delegate) {
12798        mTouchDelegate = delegate;
12799    }
12800
12801    /**
12802     * Gets the TouchDelegate for this View.
12803     */
12804    public TouchDelegate getTouchDelegate() {
12805        return mTouchDelegate;
12806    }
12807
12808    /**
12809     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12810     *
12811     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12812     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12813     * available. This method should only be called for touch events.
12814     *
12815     * <p class="note">This api is not intended for most applications. Buffered dispatch
12816     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12817     * streams will not improve your input latency. Side effects include: increased latency,
12818     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12819     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12820     * you.</p>
12821     */
12822    public final void requestUnbufferedDispatch(MotionEvent event) {
12823        final int action = event.getAction();
12824        if (mAttachInfo == null
12825                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12826                || !event.isTouchEvent()) {
12827            return;
12828        }
12829        mAttachInfo.mUnbufferedDispatchRequested = true;
12830    }
12831
12832    /**
12833     * Set flags controlling behavior of this view.
12834     *
12835     * @param flags Constant indicating the value which should be set
12836     * @param mask Constant indicating the bit range that should be changed
12837     */
12838    void setFlags(int flags, int mask) {
12839        final boolean accessibilityEnabled =
12840                AccessibilityManager.getInstance(mContext).isEnabled();
12841        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12842
12843        int old = mViewFlags;
12844        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12845
12846        int changed = mViewFlags ^ old;
12847        if (changed == 0) {
12848            return;
12849        }
12850        int privateFlags = mPrivateFlags;
12851
12852        // If focusable is auto, update the FOCUSABLE bit.
12853        int focusableChangedByAuto = 0;
12854        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12855                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12856            // Heuristic only takes into account whether view is clickable.
12857            final int newFocus;
12858            if ((mViewFlags & CLICKABLE) != 0) {
12859                newFocus = FOCUSABLE;
12860            } else {
12861                newFocus = NOT_FOCUSABLE;
12862            }
12863            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12864            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12865            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12866        }
12867
12868        /* Check if the FOCUSABLE bit has changed */
12869        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12870            if (((old & FOCUSABLE) == FOCUSABLE)
12871                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12872                /* Give up focus if we are no longer focusable */
12873                clearFocus();
12874            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12875                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12876                /*
12877                 * Tell the view system that we are now available to take focus
12878                 * if no one else already has it.
12879                 */
12880                if (mParent != null) {
12881                    ViewRootImpl viewRootImpl = getViewRootImpl();
12882                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12883                            || focusableChangedByAuto == 0
12884                            || viewRootImpl == null
12885                            || viewRootImpl.mThread == Thread.currentThread()) {
12886                        mParent.focusableViewAvailable(this);
12887                    }
12888                }
12889            }
12890        }
12891
12892        final int newVisibility = flags & VISIBILITY_MASK;
12893        if (newVisibility == VISIBLE) {
12894            if ((changed & VISIBILITY_MASK) != 0) {
12895                /*
12896                 * If this view is becoming visible, invalidate it in case it changed while
12897                 * it was not visible. Marking it drawn ensures that the invalidation will
12898                 * go through.
12899                 */
12900                mPrivateFlags |= PFLAG_DRAWN;
12901                invalidate(true);
12902
12903                needGlobalAttributesUpdate(true);
12904
12905                // a view becoming visible is worth notifying the parent
12906                // about in case nothing has focus.  even if this specific view
12907                // isn't focusable, it may contain something that is, so let
12908                // the root view try to give this focus if nothing else does.
12909                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12910                    mParent.focusableViewAvailable(this);
12911                }
12912            }
12913        }
12914
12915        /* Check if the GONE bit has changed */
12916        if ((changed & GONE) != 0) {
12917            needGlobalAttributesUpdate(false);
12918            requestLayout();
12919
12920            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12921                if (hasFocus()) clearFocus();
12922                clearAccessibilityFocus();
12923                destroyDrawingCache();
12924                if (mParent instanceof View) {
12925                    // GONE views noop invalidation, so invalidate the parent
12926                    ((View) mParent).invalidate(true);
12927                }
12928                // Mark the view drawn to ensure that it gets invalidated properly the next
12929                // time it is visible and gets invalidated
12930                mPrivateFlags |= PFLAG_DRAWN;
12931            }
12932            if (mAttachInfo != null) {
12933                mAttachInfo.mViewVisibilityChanged = true;
12934            }
12935        }
12936
12937        /* Check if the VISIBLE bit has changed */
12938        if ((changed & INVISIBLE) != 0) {
12939            needGlobalAttributesUpdate(false);
12940            /*
12941             * If this view is becoming invisible, set the DRAWN flag so that
12942             * the next invalidate() will not be skipped.
12943             */
12944            mPrivateFlags |= PFLAG_DRAWN;
12945
12946            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12947                // root view becoming invisible shouldn't clear focus and accessibility focus
12948                if (getRootView() != this) {
12949                    if (hasFocus()) clearFocus();
12950                    clearAccessibilityFocus();
12951                }
12952            }
12953            if (mAttachInfo != null) {
12954                mAttachInfo.mViewVisibilityChanged = true;
12955            }
12956        }
12957
12958        if ((changed & VISIBILITY_MASK) != 0) {
12959            // If the view is invisible, cleanup its display list to free up resources
12960            if (newVisibility != VISIBLE && mAttachInfo != null) {
12961                cleanupDraw();
12962            }
12963
12964            if (mParent instanceof ViewGroup) {
12965                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12966                        (changed & VISIBILITY_MASK), newVisibility);
12967                ((View) mParent).invalidate(true);
12968            } else if (mParent != null) {
12969                mParent.invalidateChild(this, null);
12970            }
12971
12972            if (mAttachInfo != null) {
12973                dispatchVisibilityChanged(this, newVisibility);
12974
12975                // Aggregated visibility changes are dispatched to attached views
12976                // in visible windows where the parent is currently shown/drawn
12977                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12978                // discounting clipping or overlapping. This makes it a good place
12979                // to change animation states.
12980                if (mParent != null && getWindowVisibility() == VISIBLE &&
12981                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12982                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12983                }
12984                notifySubtreeAccessibilityStateChangedIfNeeded();
12985            }
12986        }
12987
12988        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12989            destroyDrawingCache();
12990        }
12991
12992        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12993            destroyDrawingCache();
12994            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12995            invalidateParentCaches();
12996        }
12997
12998        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12999            destroyDrawingCache();
13000            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13001        }
13002
13003        if ((changed & DRAW_MASK) != 0) {
13004            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13005                if (mBackground != null
13006                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13007                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13008                } else {
13009                    mPrivateFlags |= PFLAG_SKIP_DRAW;
13010                }
13011            } else {
13012                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13013            }
13014            requestLayout();
13015            invalidate(true);
13016        }
13017
13018        if ((changed & KEEP_SCREEN_ON) != 0) {
13019            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13020                mParent.recomputeViewAttributes(this);
13021            }
13022        }
13023
13024        if (accessibilityEnabled) {
13025            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13026                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13027                    || (changed & CONTEXT_CLICKABLE) != 0) {
13028                if (oldIncludeForAccessibility != includeForAccessibility()) {
13029                    notifySubtreeAccessibilityStateChangedIfNeeded();
13030                } else {
13031                    notifyViewAccessibilityStateChangedIfNeeded(
13032                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13033                }
13034            } else if ((changed & ENABLED_MASK) != 0) {
13035                notifyViewAccessibilityStateChangedIfNeeded(
13036                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13037            }
13038        }
13039    }
13040
13041    /**
13042     * Change the view's z order in the tree, so it's on top of other sibling
13043     * views. This ordering change may affect layout, if the parent container
13044     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13045     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13046     * method should be followed by calls to {@link #requestLayout()} and
13047     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13048     * with the new child ordering.
13049     *
13050     * @see ViewGroup#bringChildToFront(View)
13051     */
13052    public void bringToFront() {
13053        if (mParent != null) {
13054            mParent.bringChildToFront(this);
13055        }
13056    }
13057
13058    /**
13059     * This is called in response to an internal scroll in this view (i.e., the
13060     * view scrolled its own contents). This is typically as a result of
13061     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13062     * called.
13063     *
13064     * @param l Current horizontal scroll origin.
13065     * @param t Current vertical scroll origin.
13066     * @param oldl Previous horizontal scroll origin.
13067     * @param oldt Previous vertical scroll origin.
13068     */
13069    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13070        notifySubtreeAccessibilityStateChangedIfNeeded();
13071
13072        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13073            postSendViewScrolledAccessibilityEventCallback();
13074        }
13075
13076        mBackgroundSizeChanged = true;
13077        if (mForegroundInfo != null) {
13078            mForegroundInfo.mBoundsChanged = true;
13079        }
13080
13081        final AttachInfo ai = mAttachInfo;
13082        if (ai != null) {
13083            ai.mViewScrollChanged = true;
13084        }
13085
13086        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13087            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13088        }
13089    }
13090
13091    /**
13092     * Interface definition for a callback to be invoked when the scroll
13093     * X or Y positions of a view change.
13094     * <p>
13095     * <b>Note:</b> Some views handle scrolling independently from View and may
13096     * have their own separate listeners for scroll-type events. For example,
13097     * {@link android.widget.ListView ListView} allows clients to register an
13098     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13099     * to listen for changes in list scroll position.
13100     *
13101     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13102     */
13103    public interface OnScrollChangeListener {
13104        /**
13105         * Called when the scroll position of a view changes.
13106         *
13107         * @param v The view whose scroll position has changed.
13108         * @param scrollX Current horizontal scroll origin.
13109         * @param scrollY Current vertical scroll origin.
13110         * @param oldScrollX Previous horizontal scroll origin.
13111         * @param oldScrollY Previous vertical scroll origin.
13112         */
13113        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13114    }
13115
13116    /**
13117     * Interface definition for a callback to be invoked when the layout bounds of a view
13118     * changes due to layout processing.
13119     */
13120    public interface OnLayoutChangeListener {
13121        /**
13122         * Called when the layout bounds of a view changes due to layout processing.
13123         *
13124         * @param v The view whose bounds have changed.
13125         * @param left The new value of the view's left property.
13126         * @param top The new value of the view's top property.
13127         * @param right The new value of the view's right property.
13128         * @param bottom The new value of the view's bottom property.
13129         * @param oldLeft The previous value of the view's left property.
13130         * @param oldTop The previous value of the view's top property.
13131         * @param oldRight The previous value of the view's right property.
13132         * @param oldBottom The previous value of the view's bottom property.
13133         */
13134        void onLayoutChange(View v, int left, int top, int right, int bottom,
13135            int oldLeft, int oldTop, int oldRight, int oldBottom);
13136    }
13137
13138    /**
13139     * This is called during layout when the size of this view has changed. If
13140     * you were just added to the view hierarchy, you're called with the old
13141     * values of 0.
13142     *
13143     * @param w Current width of this view.
13144     * @param h Current height of this view.
13145     * @param oldw Old width of this view.
13146     * @param oldh Old height of this view.
13147     */
13148    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13149    }
13150
13151    /**
13152     * Called by draw to draw the child views. This may be overridden
13153     * by derived classes to gain control just before its children are drawn
13154     * (but after its own view has been drawn).
13155     * @param canvas the canvas on which to draw the view
13156     */
13157    protected void dispatchDraw(Canvas canvas) {
13158
13159    }
13160
13161    /**
13162     * Gets the parent of this view. Note that the parent is a
13163     * ViewParent and not necessarily a View.
13164     *
13165     * @return Parent of this view.
13166     */
13167    public final ViewParent getParent() {
13168        return mParent;
13169    }
13170
13171    /**
13172     * Set the horizontal scrolled position of your view. This will cause a call to
13173     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13174     * invalidated.
13175     * @param value the x position to scroll to
13176     */
13177    public void setScrollX(int value) {
13178        scrollTo(value, mScrollY);
13179    }
13180
13181    /**
13182     * Set the vertical scrolled position of your view. This will cause a call to
13183     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13184     * invalidated.
13185     * @param value the y position to scroll to
13186     */
13187    public void setScrollY(int value) {
13188        scrollTo(mScrollX, value);
13189    }
13190
13191    /**
13192     * Return the scrolled left position of this view. This is the left edge of
13193     * the displayed part of your view. You do not need to draw any pixels
13194     * farther left, since those are outside of the frame of your view on
13195     * screen.
13196     *
13197     * @return The left edge of the displayed part of your view, in pixels.
13198     */
13199    public final int getScrollX() {
13200        return mScrollX;
13201    }
13202
13203    /**
13204     * Return the scrolled top position of this view. This is the top edge of
13205     * the displayed part of your view. You do not need to draw any pixels above
13206     * it, since those are outside of the frame of your view on screen.
13207     *
13208     * @return The top edge of the displayed part of your view, in pixels.
13209     */
13210    public final int getScrollY() {
13211        return mScrollY;
13212    }
13213
13214    /**
13215     * Return the width of the your view.
13216     *
13217     * @return The width of your view, in pixels.
13218     */
13219    @ViewDebug.ExportedProperty(category = "layout")
13220    public final int getWidth() {
13221        return mRight - mLeft;
13222    }
13223
13224    /**
13225     * Return the height of your view.
13226     *
13227     * @return The height of your view, in pixels.
13228     */
13229    @ViewDebug.ExportedProperty(category = "layout")
13230    public final int getHeight() {
13231        return mBottom - mTop;
13232    }
13233
13234    /**
13235     * Return the visible drawing bounds of your view. Fills in the output
13236     * rectangle with the values from getScrollX(), getScrollY(),
13237     * getWidth(), and getHeight(). These bounds do not account for any
13238     * transformation properties currently set on the view, such as
13239     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13240     *
13241     * @param outRect The (scrolled) drawing bounds of the view.
13242     */
13243    public void getDrawingRect(Rect outRect) {
13244        outRect.left = mScrollX;
13245        outRect.top = mScrollY;
13246        outRect.right = mScrollX + (mRight - mLeft);
13247        outRect.bottom = mScrollY + (mBottom - mTop);
13248    }
13249
13250    /**
13251     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13252     * raw width component (that is the result is masked by
13253     * {@link #MEASURED_SIZE_MASK}).
13254     *
13255     * @return The raw measured width of this view.
13256     */
13257    public final int getMeasuredWidth() {
13258        return mMeasuredWidth & MEASURED_SIZE_MASK;
13259    }
13260
13261    /**
13262     * Return the full width measurement information for this view as computed
13263     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13264     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13265     * This should be used during measurement and layout calculations only. Use
13266     * {@link #getWidth()} to see how wide a view is after layout.
13267     *
13268     * @return The measured width of this view as a bit mask.
13269     */
13270    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13271            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13272                    name = "MEASURED_STATE_TOO_SMALL"),
13273    })
13274    public final int getMeasuredWidthAndState() {
13275        return mMeasuredWidth;
13276    }
13277
13278    /**
13279     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13280     * raw height component (that is the result is masked by
13281     * {@link #MEASURED_SIZE_MASK}).
13282     *
13283     * @return The raw measured height of this view.
13284     */
13285    public final int getMeasuredHeight() {
13286        return mMeasuredHeight & MEASURED_SIZE_MASK;
13287    }
13288
13289    /**
13290     * Return the full height measurement information for this view as computed
13291     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13292     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13293     * This should be used during measurement and layout calculations only. Use
13294     * {@link #getHeight()} to see how wide a view is after layout.
13295     *
13296     * @return The measured height of this view as a bit mask.
13297     */
13298    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13299            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13300                    name = "MEASURED_STATE_TOO_SMALL"),
13301    })
13302    public final int getMeasuredHeightAndState() {
13303        return mMeasuredHeight;
13304    }
13305
13306    /**
13307     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13308     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13309     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13310     * and the height component is at the shifted bits
13311     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13312     */
13313    public final int getMeasuredState() {
13314        return (mMeasuredWidth&MEASURED_STATE_MASK)
13315                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13316                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13317    }
13318
13319    /**
13320     * The transform matrix of this view, which is calculated based on the current
13321     * rotation, scale, and pivot properties.
13322     *
13323     * @see #getRotation()
13324     * @see #getScaleX()
13325     * @see #getScaleY()
13326     * @see #getPivotX()
13327     * @see #getPivotY()
13328     * @return The current transform matrix for the view
13329     */
13330    public Matrix getMatrix() {
13331        ensureTransformationInfo();
13332        final Matrix matrix = mTransformationInfo.mMatrix;
13333        mRenderNode.getMatrix(matrix);
13334        return matrix;
13335    }
13336
13337    /**
13338     * Returns true if the transform matrix is the identity matrix.
13339     * Recomputes the matrix if necessary.
13340     *
13341     * @return True if the transform matrix is the identity matrix, false otherwise.
13342     */
13343    final boolean hasIdentityMatrix() {
13344        return mRenderNode.hasIdentityMatrix();
13345    }
13346
13347    void ensureTransformationInfo() {
13348        if (mTransformationInfo == null) {
13349            mTransformationInfo = new TransformationInfo();
13350        }
13351    }
13352
13353    /**
13354     * Utility method to retrieve the inverse of the current mMatrix property.
13355     * We cache the matrix to avoid recalculating it when transform properties
13356     * have not changed.
13357     *
13358     * @return The inverse of the current matrix of this view.
13359     * @hide
13360     */
13361    public final Matrix getInverseMatrix() {
13362        ensureTransformationInfo();
13363        if (mTransformationInfo.mInverseMatrix == null) {
13364            mTransformationInfo.mInverseMatrix = new Matrix();
13365        }
13366        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13367        mRenderNode.getInverseMatrix(matrix);
13368        return matrix;
13369    }
13370
13371    /**
13372     * Gets the distance along the Z axis from the camera to this view.
13373     *
13374     * @see #setCameraDistance(float)
13375     *
13376     * @return The distance along the Z axis.
13377     */
13378    public float getCameraDistance() {
13379        final float dpi = mResources.getDisplayMetrics().densityDpi;
13380        return -(mRenderNode.getCameraDistance() * dpi);
13381    }
13382
13383    /**
13384     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13385     * views are drawn) from the camera to this view. The camera's distance
13386     * affects 3D transformations, for instance rotations around the X and Y
13387     * axis. If the rotationX or rotationY properties are changed and this view is
13388     * large (more than half the size of the screen), it is recommended to always
13389     * use a camera distance that's greater than the height (X axis rotation) or
13390     * the width (Y axis rotation) of this view.</p>
13391     *
13392     * <p>The distance of the camera from the view plane can have an affect on the
13393     * perspective distortion of the view when it is rotated around the x or y axis.
13394     * For example, a large distance will result in a large viewing angle, and there
13395     * will not be much perspective distortion of the view as it rotates. A short
13396     * distance may cause much more perspective distortion upon rotation, and can
13397     * also result in some drawing artifacts if the rotated view ends up partially
13398     * behind the camera (which is why the recommendation is to use a distance at
13399     * least as far as the size of the view, if the view is to be rotated.)</p>
13400     *
13401     * <p>The distance is expressed in "depth pixels." The default distance depends
13402     * on the screen density. For instance, on a medium density display, the
13403     * default distance is 1280. On a high density display, the default distance
13404     * is 1920.</p>
13405     *
13406     * <p>If you want to specify a distance that leads to visually consistent
13407     * results across various densities, use the following formula:</p>
13408     * <pre>
13409     * float scale = context.getResources().getDisplayMetrics().density;
13410     * view.setCameraDistance(distance * scale);
13411     * </pre>
13412     *
13413     * <p>The density scale factor of a high density display is 1.5,
13414     * and 1920 = 1280 * 1.5.</p>
13415     *
13416     * @param distance The distance in "depth pixels", if negative the opposite
13417     *        value is used
13418     *
13419     * @see #setRotationX(float)
13420     * @see #setRotationY(float)
13421     */
13422    public void setCameraDistance(float distance) {
13423        final float dpi = mResources.getDisplayMetrics().densityDpi;
13424
13425        invalidateViewProperty(true, false);
13426        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13427        invalidateViewProperty(false, false);
13428
13429        invalidateParentIfNeededAndWasQuickRejected();
13430    }
13431
13432    /**
13433     * The degrees that the view is rotated around the pivot point.
13434     *
13435     * @see #setRotation(float)
13436     * @see #getPivotX()
13437     * @see #getPivotY()
13438     *
13439     * @return The degrees of rotation.
13440     */
13441    @ViewDebug.ExportedProperty(category = "drawing")
13442    public float getRotation() {
13443        return mRenderNode.getRotation();
13444    }
13445
13446    /**
13447     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13448     * result in clockwise rotation.
13449     *
13450     * @param rotation The degrees of rotation.
13451     *
13452     * @see #getRotation()
13453     * @see #getPivotX()
13454     * @see #getPivotY()
13455     * @see #setRotationX(float)
13456     * @see #setRotationY(float)
13457     *
13458     * @attr ref android.R.styleable#View_rotation
13459     */
13460    public void setRotation(float rotation) {
13461        if (rotation != getRotation()) {
13462            // Double-invalidation is necessary to capture view's old and new areas
13463            invalidateViewProperty(true, false);
13464            mRenderNode.setRotation(rotation);
13465            invalidateViewProperty(false, true);
13466
13467            invalidateParentIfNeededAndWasQuickRejected();
13468            notifySubtreeAccessibilityStateChangedIfNeeded();
13469        }
13470    }
13471
13472    /**
13473     * The degrees that the view is rotated around the vertical axis through the pivot point.
13474     *
13475     * @see #getPivotX()
13476     * @see #getPivotY()
13477     * @see #setRotationY(float)
13478     *
13479     * @return The degrees of Y rotation.
13480     */
13481    @ViewDebug.ExportedProperty(category = "drawing")
13482    public float getRotationY() {
13483        return mRenderNode.getRotationY();
13484    }
13485
13486    /**
13487     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13488     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13489     * down the y axis.
13490     *
13491     * When rotating large views, it is recommended to adjust the camera distance
13492     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13493     *
13494     * @param rotationY The degrees of Y rotation.
13495     *
13496     * @see #getRotationY()
13497     * @see #getPivotX()
13498     * @see #getPivotY()
13499     * @see #setRotation(float)
13500     * @see #setRotationX(float)
13501     * @see #setCameraDistance(float)
13502     *
13503     * @attr ref android.R.styleable#View_rotationY
13504     */
13505    public void setRotationY(float rotationY) {
13506        if (rotationY != getRotationY()) {
13507            invalidateViewProperty(true, false);
13508            mRenderNode.setRotationY(rotationY);
13509            invalidateViewProperty(false, true);
13510
13511            invalidateParentIfNeededAndWasQuickRejected();
13512            notifySubtreeAccessibilityStateChangedIfNeeded();
13513        }
13514    }
13515
13516    /**
13517     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13518     *
13519     * @see #getPivotX()
13520     * @see #getPivotY()
13521     * @see #setRotationX(float)
13522     *
13523     * @return The degrees of X rotation.
13524     */
13525    @ViewDebug.ExportedProperty(category = "drawing")
13526    public float getRotationX() {
13527        return mRenderNode.getRotationX();
13528    }
13529
13530    /**
13531     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13532     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13533     * x axis.
13534     *
13535     * When rotating large views, it is recommended to adjust the camera distance
13536     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13537     *
13538     * @param rotationX The degrees of X rotation.
13539     *
13540     * @see #getRotationX()
13541     * @see #getPivotX()
13542     * @see #getPivotY()
13543     * @see #setRotation(float)
13544     * @see #setRotationY(float)
13545     * @see #setCameraDistance(float)
13546     *
13547     * @attr ref android.R.styleable#View_rotationX
13548     */
13549    public void setRotationX(float rotationX) {
13550        if (rotationX != getRotationX()) {
13551            invalidateViewProperty(true, false);
13552            mRenderNode.setRotationX(rotationX);
13553            invalidateViewProperty(false, true);
13554
13555            invalidateParentIfNeededAndWasQuickRejected();
13556            notifySubtreeAccessibilityStateChangedIfNeeded();
13557        }
13558    }
13559
13560    /**
13561     * The amount that the view is scaled in x around the pivot point, as a proportion of
13562     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13563     *
13564     * <p>By default, this is 1.0f.
13565     *
13566     * @see #getPivotX()
13567     * @see #getPivotY()
13568     * @return The scaling factor.
13569     */
13570    @ViewDebug.ExportedProperty(category = "drawing")
13571    public float getScaleX() {
13572        return mRenderNode.getScaleX();
13573    }
13574
13575    /**
13576     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13577     * the view's unscaled width. A value of 1 means that no scaling is applied.
13578     *
13579     * @param scaleX The scaling factor.
13580     * @see #getPivotX()
13581     * @see #getPivotY()
13582     *
13583     * @attr ref android.R.styleable#View_scaleX
13584     */
13585    public void setScaleX(float scaleX) {
13586        if (scaleX != getScaleX()) {
13587            invalidateViewProperty(true, false);
13588            mRenderNode.setScaleX(scaleX);
13589            invalidateViewProperty(false, true);
13590
13591            invalidateParentIfNeededAndWasQuickRejected();
13592            notifySubtreeAccessibilityStateChangedIfNeeded();
13593        }
13594    }
13595
13596    /**
13597     * The amount that the view is scaled in y around the pivot point, as a proportion of
13598     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13599     *
13600     * <p>By default, this is 1.0f.
13601     *
13602     * @see #getPivotX()
13603     * @see #getPivotY()
13604     * @return The scaling factor.
13605     */
13606    @ViewDebug.ExportedProperty(category = "drawing")
13607    public float getScaleY() {
13608        return mRenderNode.getScaleY();
13609    }
13610
13611    /**
13612     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13613     * the view's unscaled width. A value of 1 means that no scaling is applied.
13614     *
13615     * @param scaleY The scaling factor.
13616     * @see #getPivotX()
13617     * @see #getPivotY()
13618     *
13619     * @attr ref android.R.styleable#View_scaleY
13620     */
13621    public void setScaleY(float scaleY) {
13622        if (scaleY != getScaleY()) {
13623            invalidateViewProperty(true, false);
13624            mRenderNode.setScaleY(scaleY);
13625            invalidateViewProperty(false, true);
13626
13627            invalidateParentIfNeededAndWasQuickRejected();
13628            notifySubtreeAccessibilityStateChangedIfNeeded();
13629        }
13630    }
13631
13632    /**
13633     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13634     * and {@link #setScaleX(float) scaled}.
13635     *
13636     * @see #getRotation()
13637     * @see #getScaleX()
13638     * @see #getScaleY()
13639     * @see #getPivotY()
13640     * @return The x location of the pivot point.
13641     *
13642     * @attr ref android.R.styleable#View_transformPivotX
13643     */
13644    @ViewDebug.ExportedProperty(category = "drawing")
13645    public float getPivotX() {
13646        return mRenderNode.getPivotX();
13647    }
13648
13649    /**
13650     * Sets the x location of the point around which the view is
13651     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13652     * By default, the pivot point is centered on the object.
13653     * Setting this property disables this behavior and causes the view to use only the
13654     * explicitly set pivotX and pivotY values.
13655     *
13656     * @param pivotX The x location of the pivot point.
13657     * @see #getRotation()
13658     * @see #getScaleX()
13659     * @see #getScaleY()
13660     * @see #getPivotY()
13661     *
13662     * @attr ref android.R.styleable#View_transformPivotX
13663     */
13664    public void setPivotX(float pivotX) {
13665        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13666            invalidateViewProperty(true, false);
13667            mRenderNode.setPivotX(pivotX);
13668            invalidateViewProperty(false, true);
13669
13670            invalidateParentIfNeededAndWasQuickRejected();
13671        }
13672    }
13673
13674    /**
13675     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13676     * and {@link #setScaleY(float) scaled}.
13677     *
13678     * @see #getRotation()
13679     * @see #getScaleX()
13680     * @see #getScaleY()
13681     * @see #getPivotY()
13682     * @return The y location of the pivot point.
13683     *
13684     * @attr ref android.R.styleable#View_transformPivotY
13685     */
13686    @ViewDebug.ExportedProperty(category = "drawing")
13687    public float getPivotY() {
13688        return mRenderNode.getPivotY();
13689    }
13690
13691    /**
13692     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13693     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13694     * Setting this property disables this behavior and causes the view to use only the
13695     * explicitly set pivotX and pivotY values.
13696     *
13697     * @param pivotY The y location of the pivot point.
13698     * @see #getRotation()
13699     * @see #getScaleX()
13700     * @see #getScaleY()
13701     * @see #getPivotY()
13702     *
13703     * @attr ref android.R.styleable#View_transformPivotY
13704     */
13705    public void setPivotY(float pivotY) {
13706        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13707            invalidateViewProperty(true, false);
13708            mRenderNode.setPivotY(pivotY);
13709            invalidateViewProperty(false, true);
13710
13711            invalidateParentIfNeededAndWasQuickRejected();
13712        }
13713    }
13714
13715    /**
13716     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13717     * completely transparent and 1 means the view is completely opaque.
13718     *
13719     * <p>By default this is 1.0f.
13720     * @return The opacity of the view.
13721     */
13722    @ViewDebug.ExportedProperty(category = "drawing")
13723    public float getAlpha() {
13724        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13725    }
13726
13727    /**
13728     * Sets the behavior for overlapping rendering for this view (see {@link
13729     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13730     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13731     * providing the value which is then used internally. That is, when {@link
13732     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13733     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13734     * instead.
13735     *
13736     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13737     * instead of that returned by {@link #hasOverlappingRendering()}.
13738     *
13739     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13740     */
13741    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13742        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13743        if (hasOverlappingRendering) {
13744            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13745        } else {
13746            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13747        }
13748    }
13749
13750    /**
13751     * Returns the value for overlapping rendering that is used internally. This is either
13752     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13753     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13754     *
13755     * @return The value for overlapping rendering being used internally.
13756     */
13757    public final boolean getHasOverlappingRendering() {
13758        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13759                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13760                hasOverlappingRendering();
13761    }
13762
13763    /**
13764     * Returns whether this View has content which overlaps.
13765     *
13766     * <p>This function, intended to be overridden by specific View types, is an optimization when
13767     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13768     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13769     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13770     * directly. An example of overlapping rendering is a TextView with a background image, such as
13771     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13772     * ImageView with only the foreground image. The default implementation returns true; subclasses
13773     * should override if they have cases which can be optimized.</p>
13774     *
13775     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13776     * necessitates that a View return true if it uses the methods internally without passing the
13777     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13778     *
13779     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13780     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13781     *
13782     * @return true if the content in this view might overlap, false otherwise.
13783     */
13784    @ViewDebug.ExportedProperty(category = "drawing")
13785    public boolean hasOverlappingRendering() {
13786        return true;
13787    }
13788
13789    /**
13790     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13791     * completely transparent and 1 means the view is completely opaque.
13792     *
13793     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13794     * can have significant performance implications, especially for large views. It is best to use
13795     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13796     *
13797     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13798     * strongly recommended for performance reasons to either override
13799     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13800     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13801     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13802     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13803     * of rendering cost, even for simple or small views. Starting with
13804     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13805     * applied to the view at the rendering level.</p>
13806     *
13807     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13808     * responsible for applying the opacity itself.</p>
13809     *
13810     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13811     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13812     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13813     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13814     *
13815     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13816     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13817     * {@link #hasOverlappingRendering}.</p>
13818     *
13819     * @param alpha The opacity of the view.
13820     *
13821     * @see #hasOverlappingRendering()
13822     * @see #setLayerType(int, android.graphics.Paint)
13823     *
13824     * @attr ref android.R.styleable#View_alpha
13825     */
13826    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13827        ensureTransformationInfo();
13828        if (mTransformationInfo.mAlpha != alpha) {
13829            // Report visibility changes, which can affect children, to accessibility
13830            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13831                notifySubtreeAccessibilityStateChangedIfNeeded();
13832            }
13833            mTransformationInfo.mAlpha = alpha;
13834            if (onSetAlpha((int) (alpha * 255))) {
13835                mPrivateFlags |= PFLAG_ALPHA_SET;
13836                // subclass is handling alpha - don't optimize rendering cache invalidation
13837                invalidateParentCaches();
13838                invalidate(true);
13839            } else {
13840                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13841                invalidateViewProperty(true, false);
13842                mRenderNode.setAlpha(getFinalAlpha());
13843            }
13844        }
13845    }
13846
13847    /**
13848     * Faster version of setAlpha() which performs the same steps except there are
13849     * no calls to invalidate(). The caller of this function should perform proper invalidation
13850     * on the parent and this object. The return value indicates whether the subclass handles
13851     * alpha (the return value for onSetAlpha()).
13852     *
13853     * @param alpha The new value for the alpha property
13854     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13855     *         the new value for the alpha property is different from the old value
13856     */
13857    boolean setAlphaNoInvalidation(float alpha) {
13858        ensureTransformationInfo();
13859        if (mTransformationInfo.mAlpha != alpha) {
13860            mTransformationInfo.mAlpha = alpha;
13861            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13862            if (subclassHandlesAlpha) {
13863                mPrivateFlags |= PFLAG_ALPHA_SET;
13864                return true;
13865            } else {
13866                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13867                mRenderNode.setAlpha(getFinalAlpha());
13868            }
13869        }
13870        return false;
13871    }
13872
13873    /**
13874     * This property is hidden and intended only for use by the Fade transition, which
13875     * animates it to produce a visual translucency that does not side-effect (or get
13876     * affected by) the real alpha property. This value is composited with the other
13877     * alpha value (and the AlphaAnimation value, when that is present) to produce
13878     * a final visual translucency result, which is what is passed into the DisplayList.
13879     *
13880     * @hide
13881     */
13882    public void setTransitionAlpha(float alpha) {
13883        ensureTransformationInfo();
13884        if (mTransformationInfo.mTransitionAlpha != alpha) {
13885            mTransformationInfo.mTransitionAlpha = alpha;
13886            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13887            invalidateViewProperty(true, false);
13888            mRenderNode.setAlpha(getFinalAlpha());
13889        }
13890    }
13891
13892    /**
13893     * Calculates the visual alpha of this view, which is a combination of the actual
13894     * alpha value and the transitionAlpha value (if set).
13895     */
13896    private float getFinalAlpha() {
13897        if (mTransformationInfo != null) {
13898            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13899        }
13900        return 1;
13901    }
13902
13903    /**
13904     * This property is hidden and intended only for use by the Fade transition, which
13905     * animates it to produce a visual translucency that does not side-effect (or get
13906     * affected by) the real alpha property. This value is composited with the other
13907     * alpha value (and the AlphaAnimation value, when that is present) to produce
13908     * a final visual translucency result, which is what is passed into the DisplayList.
13909     *
13910     * @hide
13911     */
13912    @ViewDebug.ExportedProperty(category = "drawing")
13913    public float getTransitionAlpha() {
13914        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13915    }
13916
13917    /**
13918     * Top position of this view relative to its parent.
13919     *
13920     * @return The top of this view, in pixels.
13921     */
13922    @ViewDebug.CapturedViewProperty
13923    public final int getTop() {
13924        return mTop;
13925    }
13926
13927    /**
13928     * Sets the top position of this view relative to its parent. This method is meant to be called
13929     * by the layout system and should not generally be called otherwise, because the property
13930     * may be changed at any time by the layout.
13931     *
13932     * @param top The top of this view, in pixels.
13933     */
13934    public final void setTop(int top) {
13935        if (top != mTop) {
13936            final boolean matrixIsIdentity = hasIdentityMatrix();
13937            if (matrixIsIdentity) {
13938                if (mAttachInfo != null) {
13939                    int minTop;
13940                    int yLoc;
13941                    if (top < mTop) {
13942                        minTop = top;
13943                        yLoc = top - mTop;
13944                    } else {
13945                        minTop = mTop;
13946                        yLoc = 0;
13947                    }
13948                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13949                }
13950            } else {
13951                // Double-invalidation is necessary to capture view's old and new areas
13952                invalidate(true);
13953            }
13954
13955            int width = mRight - mLeft;
13956            int oldHeight = mBottom - mTop;
13957
13958            mTop = top;
13959            mRenderNode.setTop(mTop);
13960
13961            sizeChange(width, mBottom - mTop, width, oldHeight);
13962
13963            if (!matrixIsIdentity) {
13964                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13965                invalidate(true);
13966            }
13967            mBackgroundSizeChanged = true;
13968            if (mForegroundInfo != null) {
13969                mForegroundInfo.mBoundsChanged = true;
13970            }
13971            invalidateParentIfNeeded();
13972            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13973                // View was rejected last time it was drawn by its parent; this may have changed
13974                invalidateParentIfNeeded();
13975            }
13976        }
13977    }
13978
13979    /**
13980     * Bottom position of this view relative to its parent.
13981     *
13982     * @return The bottom of this view, in pixels.
13983     */
13984    @ViewDebug.CapturedViewProperty
13985    public final int getBottom() {
13986        return mBottom;
13987    }
13988
13989    /**
13990     * True if this view has changed since the last time being drawn.
13991     *
13992     * @return The dirty state of this view.
13993     */
13994    public boolean isDirty() {
13995        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13996    }
13997
13998    /**
13999     * Sets the bottom position of this view relative to its parent. This method is meant to be
14000     * called by the layout system and should not generally be called otherwise, because the
14001     * property may be changed at any time by the layout.
14002     *
14003     * @param bottom The bottom of this view, in pixels.
14004     */
14005    public final void setBottom(int bottom) {
14006        if (bottom != mBottom) {
14007            final boolean matrixIsIdentity = hasIdentityMatrix();
14008            if (matrixIsIdentity) {
14009                if (mAttachInfo != null) {
14010                    int maxBottom;
14011                    if (bottom < mBottom) {
14012                        maxBottom = mBottom;
14013                    } else {
14014                        maxBottom = bottom;
14015                    }
14016                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14017                }
14018            } else {
14019                // Double-invalidation is necessary to capture view's old and new areas
14020                invalidate(true);
14021            }
14022
14023            int width = mRight - mLeft;
14024            int oldHeight = mBottom - mTop;
14025
14026            mBottom = bottom;
14027            mRenderNode.setBottom(mBottom);
14028
14029            sizeChange(width, mBottom - mTop, width, oldHeight);
14030
14031            if (!matrixIsIdentity) {
14032                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14033                invalidate(true);
14034            }
14035            mBackgroundSizeChanged = true;
14036            if (mForegroundInfo != null) {
14037                mForegroundInfo.mBoundsChanged = true;
14038            }
14039            invalidateParentIfNeeded();
14040            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14041                // View was rejected last time it was drawn by its parent; this may have changed
14042                invalidateParentIfNeeded();
14043            }
14044        }
14045    }
14046
14047    /**
14048     * Left position of this view relative to its parent.
14049     *
14050     * @return The left edge of this view, in pixels.
14051     */
14052    @ViewDebug.CapturedViewProperty
14053    public final int getLeft() {
14054        return mLeft;
14055    }
14056
14057    /**
14058     * Sets the left position of this view relative to its parent. This method is meant to be called
14059     * by the layout system and should not generally be called otherwise, because the property
14060     * may be changed at any time by the layout.
14061     *
14062     * @param left The left of this view, in pixels.
14063     */
14064    public final void setLeft(int left) {
14065        if (left != mLeft) {
14066            final boolean matrixIsIdentity = hasIdentityMatrix();
14067            if (matrixIsIdentity) {
14068                if (mAttachInfo != null) {
14069                    int minLeft;
14070                    int xLoc;
14071                    if (left < mLeft) {
14072                        minLeft = left;
14073                        xLoc = left - mLeft;
14074                    } else {
14075                        minLeft = mLeft;
14076                        xLoc = 0;
14077                    }
14078                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14079                }
14080            } else {
14081                // Double-invalidation is necessary to capture view's old and new areas
14082                invalidate(true);
14083            }
14084
14085            int oldWidth = mRight - mLeft;
14086            int height = mBottom - mTop;
14087
14088            mLeft = left;
14089            mRenderNode.setLeft(left);
14090
14091            sizeChange(mRight - mLeft, height, oldWidth, height);
14092
14093            if (!matrixIsIdentity) {
14094                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14095                invalidate(true);
14096            }
14097            mBackgroundSizeChanged = true;
14098            if (mForegroundInfo != null) {
14099                mForegroundInfo.mBoundsChanged = true;
14100            }
14101            invalidateParentIfNeeded();
14102            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14103                // View was rejected last time it was drawn by its parent; this may have changed
14104                invalidateParentIfNeeded();
14105            }
14106        }
14107    }
14108
14109    /**
14110     * Right position of this view relative to its parent.
14111     *
14112     * @return The right edge of this view, in pixels.
14113     */
14114    @ViewDebug.CapturedViewProperty
14115    public final int getRight() {
14116        return mRight;
14117    }
14118
14119    /**
14120     * Sets the right position of this view relative to its parent. This method is meant to be called
14121     * by the layout system and should not generally be called otherwise, because the property
14122     * may be changed at any time by the layout.
14123     *
14124     * @param right The right of this view, in pixels.
14125     */
14126    public final void setRight(int right) {
14127        if (right != mRight) {
14128            final boolean matrixIsIdentity = hasIdentityMatrix();
14129            if (matrixIsIdentity) {
14130                if (mAttachInfo != null) {
14131                    int maxRight;
14132                    if (right < mRight) {
14133                        maxRight = mRight;
14134                    } else {
14135                        maxRight = right;
14136                    }
14137                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14138                }
14139            } else {
14140                // Double-invalidation is necessary to capture view's old and new areas
14141                invalidate(true);
14142            }
14143
14144            int oldWidth = mRight - mLeft;
14145            int height = mBottom - mTop;
14146
14147            mRight = right;
14148            mRenderNode.setRight(mRight);
14149
14150            sizeChange(mRight - mLeft, height, oldWidth, height);
14151
14152            if (!matrixIsIdentity) {
14153                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14154                invalidate(true);
14155            }
14156            mBackgroundSizeChanged = true;
14157            if (mForegroundInfo != null) {
14158                mForegroundInfo.mBoundsChanged = true;
14159            }
14160            invalidateParentIfNeeded();
14161            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14162                // View was rejected last time it was drawn by its parent; this may have changed
14163                invalidateParentIfNeeded();
14164            }
14165        }
14166    }
14167
14168    /**
14169     * The visual x position of this view, in pixels. This is equivalent to the
14170     * {@link #setTranslationX(float) translationX} property plus the current
14171     * {@link #getLeft() left} property.
14172     *
14173     * @return The visual x position of this view, in pixels.
14174     */
14175    @ViewDebug.ExportedProperty(category = "drawing")
14176    public float getX() {
14177        return mLeft + getTranslationX();
14178    }
14179
14180    /**
14181     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14182     * {@link #setTranslationX(float) translationX} property to be the difference between
14183     * the x value passed in and the current {@link #getLeft() left} property.
14184     *
14185     * @param x The visual x position of this view, in pixels.
14186     */
14187    public void setX(float x) {
14188        setTranslationX(x - mLeft);
14189    }
14190
14191    /**
14192     * The visual y position of this view, in pixels. This is equivalent to the
14193     * {@link #setTranslationY(float) translationY} property plus the current
14194     * {@link #getTop() top} property.
14195     *
14196     * @return The visual y position of this view, in pixels.
14197     */
14198    @ViewDebug.ExportedProperty(category = "drawing")
14199    public float getY() {
14200        return mTop + getTranslationY();
14201    }
14202
14203    /**
14204     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14205     * {@link #setTranslationY(float) translationY} property to be the difference between
14206     * the y value passed in and the current {@link #getTop() top} property.
14207     *
14208     * @param y The visual y position of this view, in pixels.
14209     */
14210    public void setY(float y) {
14211        setTranslationY(y - mTop);
14212    }
14213
14214    /**
14215     * The visual z position of this view, in pixels. This is equivalent to the
14216     * {@link #setTranslationZ(float) translationZ} property plus the current
14217     * {@link #getElevation() elevation} property.
14218     *
14219     * @return The visual z position of this view, in pixels.
14220     */
14221    @ViewDebug.ExportedProperty(category = "drawing")
14222    public float getZ() {
14223        return getElevation() + getTranslationZ();
14224    }
14225
14226    /**
14227     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14228     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14229     * the x value passed in and the current {@link #getElevation() elevation} property.
14230     *
14231     * @param z The visual z position of this view, in pixels.
14232     */
14233    public void setZ(float z) {
14234        setTranslationZ(z - getElevation());
14235    }
14236
14237    /**
14238     * The base elevation of this view relative to its parent, in pixels.
14239     *
14240     * @return The base depth position of the view, in pixels.
14241     */
14242    @ViewDebug.ExportedProperty(category = "drawing")
14243    public float getElevation() {
14244        return mRenderNode.getElevation();
14245    }
14246
14247    /**
14248     * Sets the base elevation of this view, in pixels.
14249     *
14250     * @attr ref android.R.styleable#View_elevation
14251     */
14252    public void setElevation(float elevation) {
14253        if (elevation != getElevation()) {
14254            invalidateViewProperty(true, false);
14255            mRenderNode.setElevation(elevation);
14256            invalidateViewProperty(false, true);
14257
14258            invalidateParentIfNeededAndWasQuickRejected();
14259        }
14260    }
14261
14262    /**
14263     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14264     * This position is post-layout, in addition to wherever the object's
14265     * layout placed it.
14266     *
14267     * @return The horizontal position of this view relative to its left position, in pixels.
14268     */
14269    @ViewDebug.ExportedProperty(category = "drawing")
14270    public float getTranslationX() {
14271        return mRenderNode.getTranslationX();
14272    }
14273
14274    /**
14275     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14276     * This effectively positions the object post-layout, in addition to wherever the object's
14277     * layout placed it.
14278     *
14279     * @param translationX The horizontal position of this view relative to its left position,
14280     * in pixels.
14281     *
14282     * @attr ref android.R.styleable#View_translationX
14283     */
14284    public void setTranslationX(float translationX) {
14285        if (translationX != getTranslationX()) {
14286            invalidateViewProperty(true, false);
14287            mRenderNode.setTranslationX(translationX);
14288            invalidateViewProperty(false, true);
14289
14290            invalidateParentIfNeededAndWasQuickRejected();
14291            notifySubtreeAccessibilityStateChangedIfNeeded();
14292        }
14293    }
14294
14295    /**
14296     * The vertical location of this view relative to its {@link #getTop() top} position.
14297     * This position is post-layout, in addition to wherever the object's
14298     * layout placed it.
14299     *
14300     * @return The vertical position of this view relative to its top position,
14301     * in pixels.
14302     */
14303    @ViewDebug.ExportedProperty(category = "drawing")
14304    public float getTranslationY() {
14305        return mRenderNode.getTranslationY();
14306    }
14307
14308    /**
14309     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14310     * This effectively positions the object post-layout, in addition to wherever the object's
14311     * layout placed it.
14312     *
14313     * @param translationY The vertical position of this view relative to its top position,
14314     * in pixels.
14315     *
14316     * @attr ref android.R.styleable#View_translationY
14317     */
14318    public void setTranslationY(float translationY) {
14319        if (translationY != getTranslationY()) {
14320            invalidateViewProperty(true, false);
14321            mRenderNode.setTranslationY(translationY);
14322            invalidateViewProperty(false, true);
14323
14324            invalidateParentIfNeededAndWasQuickRejected();
14325            notifySubtreeAccessibilityStateChangedIfNeeded();
14326        }
14327    }
14328
14329    /**
14330     * The depth location of this view relative to its {@link #getElevation() elevation}.
14331     *
14332     * @return The depth of this view relative to its elevation.
14333     */
14334    @ViewDebug.ExportedProperty(category = "drawing")
14335    public float getTranslationZ() {
14336        return mRenderNode.getTranslationZ();
14337    }
14338
14339    /**
14340     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14341     *
14342     * @attr ref android.R.styleable#View_translationZ
14343     */
14344    public void setTranslationZ(float translationZ) {
14345        if (translationZ != getTranslationZ()) {
14346            invalidateViewProperty(true, false);
14347            mRenderNode.setTranslationZ(translationZ);
14348            invalidateViewProperty(false, true);
14349
14350            invalidateParentIfNeededAndWasQuickRejected();
14351        }
14352    }
14353
14354    /** @hide */
14355    public void setAnimationMatrix(Matrix matrix) {
14356        invalidateViewProperty(true, false);
14357        mRenderNode.setAnimationMatrix(matrix);
14358        invalidateViewProperty(false, true);
14359
14360        invalidateParentIfNeededAndWasQuickRejected();
14361    }
14362
14363    /**
14364     * Returns the current StateListAnimator if exists.
14365     *
14366     * @return StateListAnimator or null if it does not exists
14367     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14368     */
14369    public StateListAnimator getStateListAnimator() {
14370        return mStateListAnimator;
14371    }
14372
14373    /**
14374     * Attaches the provided StateListAnimator to this View.
14375     * <p>
14376     * Any previously attached StateListAnimator will be detached.
14377     *
14378     * @param stateListAnimator The StateListAnimator to update the view
14379     * @see android.animation.StateListAnimator
14380     */
14381    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14382        if (mStateListAnimator == stateListAnimator) {
14383            return;
14384        }
14385        if (mStateListAnimator != null) {
14386            mStateListAnimator.setTarget(null);
14387        }
14388        mStateListAnimator = stateListAnimator;
14389        if (stateListAnimator != null) {
14390            stateListAnimator.setTarget(this);
14391            if (isAttachedToWindow()) {
14392                stateListAnimator.setState(getDrawableState());
14393            }
14394        }
14395    }
14396
14397    /**
14398     * Returns whether the Outline should be used to clip the contents of the View.
14399     * <p>
14400     * Note that this flag will only be respected if the View's Outline returns true from
14401     * {@link Outline#canClip()}.
14402     *
14403     * @see #setOutlineProvider(ViewOutlineProvider)
14404     * @see #setClipToOutline(boolean)
14405     */
14406    public final boolean getClipToOutline() {
14407        return mRenderNode.getClipToOutline();
14408    }
14409
14410    /**
14411     * Sets whether the View's Outline should be used to clip the contents of the View.
14412     * <p>
14413     * Only a single non-rectangular clip can be applied on a View at any time.
14414     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14415     * circular reveal} animation take priority over Outline clipping, and
14416     * child Outline clipping takes priority over Outline clipping done by a
14417     * parent.
14418     * <p>
14419     * Note that this flag will only be respected if the View's Outline returns true from
14420     * {@link Outline#canClip()}.
14421     *
14422     * @see #setOutlineProvider(ViewOutlineProvider)
14423     * @see #getClipToOutline()
14424     */
14425    public void setClipToOutline(boolean clipToOutline) {
14426        damageInParent();
14427        if (getClipToOutline() != clipToOutline) {
14428            mRenderNode.setClipToOutline(clipToOutline);
14429        }
14430    }
14431
14432    // correspond to the enum values of View_outlineProvider
14433    private static final int PROVIDER_BACKGROUND = 0;
14434    private static final int PROVIDER_NONE = 1;
14435    private static final int PROVIDER_BOUNDS = 2;
14436    private static final int PROVIDER_PADDED_BOUNDS = 3;
14437    private void setOutlineProviderFromAttribute(int providerInt) {
14438        switch (providerInt) {
14439            case PROVIDER_BACKGROUND:
14440                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14441                break;
14442            case PROVIDER_NONE:
14443                setOutlineProvider(null);
14444                break;
14445            case PROVIDER_BOUNDS:
14446                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14447                break;
14448            case PROVIDER_PADDED_BOUNDS:
14449                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14450                break;
14451        }
14452    }
14453
14454    /**
14455     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14456     * the shape of the shadow it casts, and enables outline clipping.
14457     * <p>
14458     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14459     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14460     * outline provider with this method allows this behavior to be overridden.
14461     * <p>
14462     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14463     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14464     * <p>
14465     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14466     *
14467     * @see #setClipToOutline(boolean)
14468     * @see #getClipToOutline()
14469     * @see #getOutlineProvider()
14470     */
14471    public void setOutlineProvider(ViewOutlineProvider provider) {
14472        mOutlineProvider = provider;
14473        invalidateOutline();
14474    }
14475
14476    /**
14477     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14478     * that defines the shape of the shadow it casts, and enables outline clipping.
14479     *
14480     * @see #setOutlineProvider(ViewOutlineProvider)
14481     */
14482    public ViewOutlineProvider getOutlineProvider() {
14483        return mOutlineProvider;
14484    }
14485
14486    /**
14487     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14488     *
14489     * @see #setOutlineProvider(ViewOutlineProvider)
14490     */
14491    public void invalidateOutline() {
14492        rebuildOutline();
14493
14494        notifySubtreeAccessibilityStateChangedIfNeeded();
14495        invalidateViewProperty(false, false);
14496    }
14497
14498    /**
14499     * Internal version of {@link #invalidateOutline()} which invalidates the
14500     * outline without invalidating the view itself. This is intended to be called from
14501     * within methods in the View class itself which are the result of the view being
14502     * invalidated already. For example, when we are drawing the background of a View,
14503     * we invalidate the outline in case it changed in the meantime, but we do not
14504     * need to invalidate the view because we're already drawing the background as part
14505     * of drawing the view in response to an earlier invalidation of the view.
14506     */
14507    private void rebuildOutline() {
14508        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14509        if (mAttachInfo == null) return;
14510
14511        if (mOutlineProvider == null) {
14512            // no provider, remove outline
14513            mRenderNode.setOutline(null);
14514        } else {
14515            final Outline outline = mAttachInfo.mTmpOutline;
14516            outline.setEmpty();
14517            outline.setAlpha(1.0f);
14518
14519            mOutlineProvider.getOutline(this, outline);
14520            mRenderNode.setOutline(outline);
14521        }
14522    }
14523
14524    /**
14525     * HierarchyViewer only
14526     *
14527     * @hide
14528     */
14529    @ViewDebug.ExportedProperty(category = "drawing")
14530    public boolean hasShadow() {
14531        return mRenderNode.hasShadow();
14532    }
14533
14534
14535    /** @hide */
14536    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14537        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14538        invalidateViewProperty(false, false);
14539    }
14540
14541    /**
14542     * Hit rectangle in parent's coordinates
14543     *
14544     * @param outRect The hit rectangle of the view.
14545     */
14546    public void getHitRect(Rect outRect) {
14547        if (hasIdentityMatrix() || mAttachInfo == null) {
14548            outRect.set(mLeft, mTop, mRight, mBottom);
14549        } else {
14550            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14551            tmpRect.set(0, 0, getWidth(), getHeight());
14552            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14553            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14554                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14555        }
14556    }
14557
14558    /**
14559     * Determines whether the given point, in local coordinates is inside the view.
14560     */
14561    /*package*/ final boolean pointInView(float localX, float localY) {
14562        return pointInView(localX, localY, 0);
14563    }
14564
14565    /**
14566     * Utility method to determine whether the given point, in local coordinates,
14567     * is inside the view, where the area of the view is expanded by the slop factor.
14568     * This method is called while processing touch-move events to determine if the event
14569     * is still within the view.
14570     *
14571     * @hide
14572     */
14573    public boolean pointInView(float localX, float localY, float slop) {
14574        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14575                localY < ((mBottom - mTop) + slop);
14576    }
14577
14578    /**
14579     * When a view has focus and the user navigates away from it, the next view is searched for
14580     * starting from the rectangle filled in by this method.
14581     *
14582     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14583     * of the view.  However, if your view maintains some idea of internal selection,
14584     * such as a cursor, or a selected row or column, you should override this method and
14585     * fill in a more specific rectangle.
14586     *
14587     * @param r The rectangle to fill in, in this view's coordinates.
14588     */
14589    public void getFocusedRect(Rect r) {
14590        getDrawingRect(r);
14591    }
14592
14593    /**
14594     * If some part of this view is not clipped by any of its parents, then
14595     * return that area in r in global (root) coordinates. To convert r to local
14596     * coordinates (without taking possible View rotations into account), offset
14597     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14598     * If the view is completely clipped or translated out, return false.
14599     *
14600     * @param r If true is returned, r holds the global coordinates of the
14601     *        visible portion of this view.
14602     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14603     *        between this view and its root. globalOffet may be null.
14604     * @return true if r is non-empty (i.e. part of the view is visible at the
14605     *         root level.
14606     */
14607    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14608        int width = mRight - mLeft;
14609        int height = mBottom - mTop;
14610        if (width > 0 && height > 0) {
14611            r.set(0, 0, width, height);
14612            if (globalOffset != null) {
14613                globalOffset.set(-mScrollX, -mScrollY);
14614            }
14615            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14616        }
14617        return false;
14618    }
14619
14620    public final boolean getGlobalVisibleRect(Rect r) {
14621        return getGlobalVisibleRect(r, null);
14622    }
14623
14624    public final boolean getLocalVisibleRect(Rect r) {
14625        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14626        if (getGlobalVisibleRect(r, offset)) {
14627            r.offset(-offset.x, -offset.y); // make r local
14628            return true;
14629        }
14630        return false;
14631    }
14632
14633    /**
14634     * Offset this view's vertical location by the specified number of pixels.
14635     *
14636     * @param offset the number of pixels to offset the view by
14637     */
14638    public void offsetTopAndBottom(int offset) {
14639        if (offset != 0) {
14640            final boolean matrixIsIdentity = hasIdentityMatrix();
14641            if (matrixIsIdentity) {
14642                if (isHardwareAccelerated()) {
14643                    invalidateViewProperty(false, false);
14644                } else {
14645                    final ViewParent p = mParent;
14646                    if (p != null && mAttachInfo != null) {
14647                        final Rect r = mAttachInfo.mTmpInvalRect;
14648                        int minTop;
14649                        int maxBottom;
14650                        int yLoc;
14651                        if (offset < 0) {
14652                            minTop = mTop + offset;
14653                            maxBottom = mBottom;
14654                            yLoc = offset;
14655                        } else {
14656                            minTop = mTop;
14657                            maxBottom = mBottom + offset;
14658                            yLoc = 0;
14659                        }
14660                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14661                        p.invalidateChild(this, r);
14662                    }
14663                }
14664            } else {
14665                invalidateViewProperty(false, false);
14666            }
14667
14668            mTop += offset;
14669            mBottom += offset;
14670            mRenderNode.offsetTopAndBottom(offset);
14671            if (isHardwareAccelerated()) {
14672                invalidateViewProperty(false, false);
14673                invalidateParentIfNeededAndWasQuickRejected();
14674            } else {
14675                if (!matrixIsIdentity) {
14676                    invalidateViewProperty(false, true);
14677                }
14678                invalidateParentIfNeeded();
14679            }
14680            notifySubtreeAccessibilityStateChangedIfNeeded();
14681        }
14682    }
14683
14684    /**
14685     * Offset this view's horizontal location by the specified amount of pixels.
14686     *
14687     * @param offset the number of pixels to offset the view by
14688     */
14689    public void offsetLeftAndRight(int offset) {
14690        if (offset != 0) {
14691            final boolean matrixIsIdentity = hasIdentityMatrix();
14692            if (matrixIsIdentity) {
14693                if (isHardwareAccelerated()) {
14694                    invalidateViewProperty(false, false);
14695                } else {
14696                    final ViewParent p = mParent;
14697                    if (p != null && mAttachInfo != null) {
14698                        final Rect r = mAttachInfo.mTmpInvalRect;
14699                        int minLeft;
14700                        int maxRight;
14701                        if (offset < 0) {
14702                            minLeft = mLeft + offset;
14703                            maxRight = mRight;
14704                        } else {
14705                            minLeft = mLeft;
14706                            maxRight = mRight + offset;
14707                        }
14708                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14709                        p.invalidateChild(this, r);
14710                    }
14711                }
14712            } else {
14713                invalidateViewProperty(false, false);
14714            }
14715
14716            mLeft += offset;
14717            mRight += offset;
14718            mRenderNode.offsetLeftAndRight(offset);
14719            if (isHardwareAccelerated()) {
14720                invalidateViewProperty(false, false);
14721                invalidateParentIfNeededAndWasQuickRejected();
14722            } else {
14723                if (!matrixIsIdentity) {
14724                    invalidateViewProperty(false, true);
14725                }
14726                invalidateParentIfNeeded();
14727            }
14728            notifySubtreeAccessibilityStateChangedIfNeeded();
14729        }
14730    }
14731
14732    /**
14733     * Get the LayoutParams associated with this view. All views should have
14734     * layout parameters. These supply parameters to the <i>parent</i> of this
14735     * view specifying how it should be arranged. There are many subclasses of
14736     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14737     * of ViewGroup that are responsible for arranging their children.
14738     *
14739     * This method may return null if this View is not attached to a parent
14740     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14741     * was not invoked successfully. When a View is attached to a parent
14742     * ViewGroup, this method must not return null.
14743     *
14744     * @return The LayoutParams associated with this view, or null if no
14745     *         parameters have been set yet
14746     */
14747    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14748    public ViewGroup.LayoutParams getLayoutParams() {
14749        return mLayoutParams;
14750    }
14751
14752    /**
14753     * Set the layout parameters associated with this view. These supply
14754     * parameters to the <i>parent</i> of this view specifying how it should be
14755     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14756     * correspond to the different subclasses of ViewGroup that are responsible
14757     * for arranging their children.
14758     *
14759     * @param params The layout parameters for this view, cannot be null
14760     */
14761    public void setLayoutParams(ViewGroup.LayoutParams params) {
14762        if (params == null) {
14763            throw new NullPointerException("Layout parameters cannot be null");
14764        }
14765        mLayoutParams = params;
14766        resolveLayoutParams();
14767        if (mParent instanceof ViewGroup) {
14768            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14769        }
14770        requestLayout();
14771    }
14772
14773    /**
14774     * Resolve the layout parameters depending on the resolved layout direction
14775     *
14776     * @hide
14777     */
14778    public void resolveLayoutParams() {
14779        if (mLayoutParams != null) {
14780            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14781        }
14782    }
14783
14784    /**
14785     * Set the scrolled position of your view. This will cause a call to
14786     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14787     * invalidated.
14788     * @param x the x position to scroll to
14789     * @param y the y position to scroll to
14790     */
14791    public void scrollTo(int x, int y) {
14792        if (mScrollX != x || mScrollY != y) {
14793            int oldX = mScrollX;
14794            int oldY = mScrollY;
14795            mScrollX = x;
14796            mScrollY = y;
14797            invalidateParentCaches();
14798            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14799            if (!awakenScrollBars()) {
14800                postInvalidateOnAnimation();
14801            }
14802        }
14803    }
14804
14805    /**
14806     * Move the scrolled position of your view. This will cause a call to
14807     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14808     * invalidated.
14809     * @param x the amount of pixels to scroll by horizontally
14810     * @param y the amount of pixels to scroll by vertically
14811     */
14812    public void scrollBy(int x, int y) {
14813        scrollTo(mScrollX + x, mScrollY + y);
14814    }
14815
14816    /**
14817     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14818     * animation to fade the scrollbars out after a default delay. If a subclass
14819     * provides animated scrolling, the start delay should equal the duration
14820     * of the scrolling animation.</p>
14821     *
14822     * <p>The animation starts only if at least one of the scrollbars is
14823     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14824     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14825     * this method returns true, and false otherwise. If the animation is
14826     * started, this method calls {@link #invalidate()}; in that case the
14827     * caller should not call {@link #invalidate()}.</p>
14828     *
14829     * <p>This method should be invoked every time a subclass directly updates
14830     * the scroll parameters.</p>
14831     *
14832     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14833     * and {@link #scrollTo(int, int)}.</p>
14834     *
14835     * @return true if the animation is played, false otherwise
14836     *
14837     * @see #awakenScrollBars(int)
14838     * @see #scrollBy(int, int)
14839     * @see #scrollTo(int, int)
14840     * @see #isHorizontalScrollBarEnabled()
14841     * @see #isVerticalScrollBarEnabled()
14842     * @see #setHorizontalScrollBarEnabled(boolean)
14843     * @see #setVerticalScrollBarEnabled(boolean)
14844     */
14845    protected boolean awakenScrollBars() {
14846        return mScrollCache != null &&
14847                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14848    }
14849
14850    /**
14851     * Trigger the scrollbars to draw.
14852     * This method differs from awakenScrollBars() only in its default duration.
14853     * initialAwakenScrollBars() will show the scroll bars for longer than
14854     * usual to give the user more of a chance to notice them.
14855     *
14856     * @return true if the animation is played, false otherwise.
14857     */
14858    private boolean initialAwakenScrollBars() {
14859        return mScrollCache != null &&
14860                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14861    }
14862
14863    /**
14864     * <p>
14865     * Trigger the scrollbars to draw. When invoked this method starts an
14866     * animation to fade the scrollbars out after a fixed delay. If a subclass
14867     * provides animated scrolling, the start delay should equal the duration of
14868     * the scrolling animation.
14869     * </p>
14870     *
14871     * <p>
14872     * The animation starts only if at least one of the scrollbars is enabled,
14873     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14874     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14875     * this method returns true, and false otherwise. If the animation is
14876     * started, this method calls {@link #invalidate()}; in that case the caller
14877     * should not call {@link #invalidate()}.
14878     * </p>
14879     *
14880     * <p>
14881     * This method should be invoked every time a subclass directly updates the
14882     * scroll parameters.
14883     * </p>
14884     *
14885     * @param startDelay the delay, in milliseconds, after which the animation
14886     *        should start; when the delay is 0, the animation starts
14887     *        immediately
14888     * @return true if the animation is played, false otherwise
14889     *
14890     * @see #scrollBy(int, int)
14891     * @see #scrollTo(int, int)
14892     * @see #isHorizontalScrollBarEnabled()
14893     * @see #isVerticalScrollBarEnabled()
14894     * @see #setHorizontalScrollBarEnabled(boolean)
14895     * @see #setVerticalScrollBarEnabled(boolean)
14896     */
14897    protected boolean awakenScrollBars(int startDelay) {
14898        return awakenScrollBars(startDelay, true);
14899    }
14900
14901    /**
14902     * <p>
14903     * Trigger the scrollbars to draw. When invoked this method starts an
14904     * animation to fade the scrollbars out after a fixed delay. If a subclass
14905     * provides animated scrolling, the start delay should equal the duration of
14906     * the scrolling animation.
14907     * </p>
14908     *
14909     * <p>
14910     * The animation starts only if at least one of the scrollbars is enabled,
14911     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14912     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14913     * this method returns true, and false otherwise. If the animation is
14914     * started, this method calls {@link #invalidate()} if the invalidate parameter
14915     * is set to true; in that case the caller
14916     * should not call {@link #invalidate()}.
14917     * </p>
14918     *
14919     * <p>
14920     * This method should be invoked every time a subclass directly updates the
14921     * scroll parameters.
14922     * </p>
14923     *
14924     * @param startDelay the delay, in milliseconds, after which the animation
14925     *        should start; when the delay is 0, the animation starts
14926     *        immediately
14927     *
14928     * @param invalidate Whether this method should call invalidate
14929     *
14930     * @return true if the animation is played, false otherwise
14931     *
14932     * @see #scrollBy(int, int)
14933     * @see #scrollTo(int, int)
14934     * @see #isHorizontalScrollBarEnabled()
14935     * @see #isVerticalScrollBarEnabled()
14936     * @see #setHorizontalScrollBarEnabled(boolean)
14937     * @see #setVerticalScrollBarEnabled(boolean)
14938     */
14939    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14940        final ScrollabilityCache scrollCache = mScrollCache;
14941
14942        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14943            return false;
14944        }
14945
14946        if (scrollCache.scrollBar == null) {
14947            scrollCache.scrollBar = new ScrollBarDrawable();
14948            scrollCache.scrollBar.setState(getDrawableState());
14949            scrollCache.scrollBar.setCallback(this);
14950        }
14951
14952        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14953
14954            if (invalidate) {
14955                // Invalidate to show the scrollbars
14956                postInvalidateOnAnimation();
14957            }
14958
14959            if (scrollCache.state == ScrollabilityCache.OFF) {
14960                // FIXME: this is copied from WindowManagerService.
14961                // We should get this value from the system when it
14962                // is possible to do so.
14963                final int KEY_REPEAT_FIRST_DELAY = 750;
14964                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14965            }
14966
14967            // Tell mScrollCache when we should start fading. This may
14968            // extend the fade start time if one was already scheduled
14969            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14970            scrollCache.fadeStartTime = fadeStartTime;
14971            scrollCache.state = ScrollabilityCache.ON;
14972
14973            // Schedule our fader to run, unscheduling any old ones first
14974            if (mAttachInfo != null) {
14975                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14976                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14977            }
14978
14979            return true;
14980        }
14981
14982        return false;
14983    }
14984
14985    /**
14986     * Do not invalidate views which are not visible and which are not running an animation. They
14987     * will not get drawn and they should not set dirty flags as if they will be drawn
14988     */
14989    private boolean skipInvalidate() {
14990        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14991                (!(mParent instanceof ViewGroup) ||
14992                        !((ViewGroup) mParent).isViewTransitioning(this));
14993    }
14994
14995    /**
14996     * Mark the area defined by dirty as needing to be drawn. If the view is
14997     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14998     * point in the future.
14999     * <p>
15000     * This must be called from a UI thread. To call from a non-UI thread, call
15001     * {@link #postInvalidate()}.
15002     * <p>
15003     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15004     * {@code dirty}.
15005     *
15006     * @param dirty the rectangle representing the bounds of the dirty region
15007     */
15008    public void invalidate(Rect dirty) {
15009        final int scrollX = mScrollX;
15010        final int scrollY = mScrollY;
15011        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15012                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15013    }
15014
15015    /**
15016     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15017     * coordinates of the dirty rect are relative to the view. If the view is
15018     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15019     * point in the future.
15020     * <p>
15021     * This must be called from a UI thread. To call from a non-UI thread, call
15022     * {@link #postInvalidate()}.
15023     *
15024     * @param l the left position of the dirty region
15025     * @param t the top position of the dirty region
15026     * @param r the right position of the dirty region
15027     * @param b the bottom position of the dirty region
15028     */
15029    public void invalidate(int l, int t, int r, int b) {
15030        final int scrollX = mScrollX;
15031        final int scrollY = mScrollY;
15032        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15033    }
15034
15035    /**
15036     * Invalidate the whole view. If the view is visible,
15037     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15038     * the future.
15039     * <p>
15040     * This must be called from a UI thread. To call from a non-UI thread, call
15041     * {@link #postInvalidate()}.
15042     */
15043    public void invalidate() {
15044        invalidate(true);
15045    }
15046
15047    /**
15048     * This is where the invalidate() work actually happens. A full invalidate()
15049     * causes the drawing cache to be invalidated, but this function can be
15050     * called with invalidateCache set to false to skip that invalidation step
15051     * for cases that do not need it (for example, a component that remains at
15052     * the same dimensions with the same content).
15053     *
15054     * @param invalidateCache Whether the drawing cache for this view should be
15055     *            invalidated as well. This is usually true for a full
15056     *            invalidate, but may be set to false if the View's contents or
15057     *            dimensions have not changed.
15058     * @hide
15059     */
15060    public void invalidate(boolean invalidateCache) {
15061        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15062    }
15063
15064    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15065            boolean fullInvalidate) {
15066        if (mGhostView != null) {
15067            mGhostView.invalidate(true);
15068            return;
15069        }
15070
15071        if (skipInvalidate()) {
15072            return;
15073        }
15074
15075        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15076                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15077                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15078                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15079            if (fullInvalidate) {
15080                mLastIsOpaque = isOpaque();
15081                mPrivateFlags &= ~PFLAG_DRAWN;
15082            }
15083
15084            mPrivateFlags |= PFLAG_DIRTY;
15085
15086            if (invalidateCache) {
15087                mPrivateFlags |= PFLAG_INVALIDATED;
15088                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15089            }
15090
15091            // Propagate the damage rectangle to the parent view.
15092            final AttachInfo ai = mAttachInfo;
15093            final ViewParent p = mParent;
15094            if (p != null && ai != null && l < r && t < b) {
15095                final Rect damage = ai.mTmpInvalRect;
15096                damage.set(l, t, r, b);
15097                p.invalidateChild(this, damage);
15098            }
15099
15100            // Damage the entire projection receiver, if necessary.
15101            if (mBackground != null && mBackground.isProjected()) {
15102                final View receiver = getProjectionReceiver();
15103                if (receiver != null) {
15104                    receiver.damageInParent();
15105                }
15106            }
15107        }
15108    }
15109
15110    /**
15111     * @return this view's projection receiver, or {@code null} if none exists
15112     */
15113    private View getProjectionReceiver() {
15114        ViewParent p = getParent();
15115        while (p != null && p instanceof View) {
15116            final View v = (View) p;
15117            if (v.isProjectionReceiver()) {
15118                return v;
15119            }
15120            p = p.getParent();
15121        }
15122
15123        return null;
15124    }
15125
15126    /**
15127     * @return whether the view is a projection receiver
15128     */
15129    private boolean isProjectionReceiver() {
15130        return mBackground != null;
15131    }
15132
15133    /**
15134     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15135     * set any flags or handle all of the cases handled by the default invalidation methods.
15136     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15137     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15138     * walk up the hierarchy, transforming the dirty rect as necessary.
15139     *
15140     * The method also handles normal invalidation logic if display list properties are not
15141     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15142     * backup approach, to handle these cases used in the various property-setting methods.
15143     *
15144     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15145     * are not being used in this view
15146     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15147     * list properties are not being used in this view
15148     */
15149    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15150        if (!isHardwareAccelerated()
15151                || !mRenderNode.isValid()
15152                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15153            if (invalidateParent) {
15154                invalidateParentCaches();
15155            }
15156            if (forceRedraw) {
15157                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15158            }
15159            invalidate(false);
15160        } else {
15161            damageInParent();
15162        }
15163    }
15164
15165    /**
15166     * Tells the parent view to damage this view's bounds.
15167     *
15168     * @hide
15169     */
15170    protected void damageInParent() {
15171        if (mParent != null && mAttachInfo != null) {
15172            mParent.onDescendantInvalidated(this, this);
15173        }
15174    }
15175
15176    /**
15177     * Utility method to transform a given Rect by the current matrix of this view.
15178     */
15179    void transformRect(final Rect rect) {
15180        if (!getMatrix().isIdentity()) {
15181            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15182            boundingRect.set(rect);
15183            getMatrix().mapRect(boundingRect);
15184            rect.set((int) Math.floor(boundingRect.left),
15185                    (int) Math.floor(boundingRect.top),
15186                    (int) Math.ceil(boundingRect.right),
15187                    (int) Math.ceil(boundingRect.bottom));
15188        }
15189    }
15190
15191    /**
15192     * Used to indicate that the parent of this view should clear its caches. This functionality
15193     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15194     * which is necessary when various parent-managed properties of the view change, such as
15195     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15196     * clears the parent caches and does not causes an invalidate event.
15197     *
15198     * @hide
15199     */
15200    protected void invalidateParentCaches() {
15201        if (mParent instanceof View) {
15202            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15203        }
15204    }
15205
15206    /**
15207     * Used to indicate that the parent of this view should be invalidated. This functionality
15208     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15209     * which is necessary when various parent-managed properties of the view change, such as
15210     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15211     * an invalidation event to the parent.
15212     *
15213     * @hide
15214     */
15215    protected void invalidateParentIfNeeded() {
15216        if (isHardwareAccelerated() && mParent instanceof View) {
15217            ((View) mParent).invalidate(true);
15218        }
15219    }
15220
15221    /**
15222     * @hide
15223     */
15224    protected void invalidateParentIfNeededAndWasQuickRejected() {
15225        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15226            // View was rejected last time it was drawn by its parent; this may have changed
15227            invalidateParentIfNeeded();
15228        }
15229    }
15230
15231    /**
15232     * Indicates whether this View is opaque. An opaque View guarantees that it will
15233     * draw all the pixels overlapping its bounds using a fully opaque color.
15234     *
15235     * Subclasses of View should override this method whenever possible to indicate
15236     * whether an instance is opaque. Opaque Views are treated in a special way by
15237     * the View hierarchy, possibly allowing it to perform optimizations during
15238     * invalidate/draw passes.
15239     *
15240     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15241     */
15242    @ViewDebug.ExportedProperty(category = "drawing")
15243    public boolean isOpaque() {
15244        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15245                getFinalAlpha() >= 1.0f;
15246    }
15247
15248    /**
15249     * @hide
15250     */
15251    protected void computeOpaqueFlags() {
15252        // Opaque if:
15253        //   - Has a background
15254        //   - Background is opaque
15255        //   - Doesn't have scrollbars or scrollbars overlay
15256
15257        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15258            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15259        } else {
15260            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15261        }
15262
15263        final int flags = mViewFlags;
15264        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15265                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15266                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15267            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15268        } else {
15269            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15270        }
15271    }
15272
15273    /**
15274     * @hide
15275     */
15276    protected boolean hasOpaqueScrollbars() {
15277        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15278    }
15279
15280    /**
15281     * @return A handler associated with the thread running the View. This
15282     * handler can be used to pump events in the UI events queue.
15283     */
15284    public Handler getHandler() {
15285        final AttachInfo attachInfo = mAttachInfo;
15286        if (attachInfo != null) {
15287            return attachInfo.mHandler;
15288        }
15289        return null;
15290    }
15291
15292    /**
15293     * Returns the queue of runnable for this view.
15294     *
15295     * @return the queue of runnables for this view
15296     */
15297    private HandlerActionQueue getRunQueue() {
15298        if (mRunQueue == null) {
15299            mRunQueue = new HandlerActionQueue();
15300        }
15301        return mRunQueue;
15302    }
15303
15304    /**
15305     * Gets the view root associated with the View.
15306     * @return The view root, or null if none.
15307     * @hide
15308     */
15309    public ViewRootImpl getViewRootImpl() {
15310        if (mAttachInfo != null) {
15311            return mAttachInfo.mViewRootImpl;
15312        }
15313        return null;
15314    }
15315
15316    /**
15317     * @hide
15318     */
15319    public ThreadedRenderer getThreadedRenderer() {
15320        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15321    }
15322
15323    /**
15324     * <p>Causes the Runnable to be added to the message queue.
15325     * The runnable will be run on the user interface thread.</p>
15326     *
15327     * @param action The Runnable that will be executed.
15328     *
15329     * @return Returns true if the Runnable was successfully placed in to the
15330     *         message queue.  Returns false on failure, usually because the
15331     *         looper processing the message queue is exiting.
15332     *
15333     * @see #postDelayed
15334     * @see #removeCallbacks
15335     */
15336    public boolean post(Runnable action) {
15337        final AttachInfo attachInfo = mAttachInfo;
15338        if (attachInfo != null) {
15339            return attachInfo.mHandler.post(action);
15340        }
15341
15342        // Postpone the runnable until we know on which thread it needs to run.
15343        // Assume that the runnable will be successfully placed after attach.
15344        getRunQueue().post(action);
15345        return true;
15346    }
15347
15348    /**
15349     * <p>Causes the Runnable to be added to the message queue, to be run
15350     * after the specified amount of time elapses.
15351     * The runnable will be run on the user interface thread.</p>
15352     *
15353     * @param action The Runnable that will be executed.
15354     * @param delayMillis The delay (in milliseconds) until the Runnable
15355     *        will be executed.
15356     *
15357     * @return true if the Runnable was successfully placed in to the
15358     *         message queue.  Returns false on failure, usually because the
15359     *         looper processing the message queue is exiting.  Note that a
15360     *         result of true does not mean the Runnable will be processed --
15361     *         if the looper is quit before the delivery time of the message
15362     *         occurs then the message will be dropped.
15363     *
15364     * @see #post
15365     * @see #removeCallbacks
15366     */
15367    public boolean postDelayed(Runnable action, long delayMillis) {
15368        final AttachInfo attachInfo = mAttachInfo;
15369        if (attachInfo != null) {
15370            return attachInfo.mHandler.postDelayed(action, delayMillis);
15371        }
15372
15373        // Postpone the runnable until we know on which thread it needs to run.
15374        // Assume that the runnable will be successfully placed after attach.
15375        getRunQueue().postDelayed(action, delayMillis);
15376        return true;
15377    }
15378
15379    /**
15380     * <p>Causes the Runnable to execute on the next animation time step.
15381     * The runnable will be run on the user interface thread.</p>
15382     *
15383     * @param action The Runnable that will be executed.
15384     *
15385     * @see #postOnAnimationDelayed
15386     * @see #removeCallbacks
15387     */
15388    public void postOnAnimation(Runnable action) {
15389        final AttachInfo attachInfo = mAttachInfo;
15390        if (attachInfo != null) {
15391            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15392                    Choreographer.CALLBACK_ANIMATION, action, null);
15393        } else {
15394            // Postpone the runnable until we know
15395            // on which thread it needs to run.
15396            getRunQueue().post(action);
15397        }
15398    }
15399
15400    /**
15401     * <p>Causes the Runnable to execute on the next animation time step,
15402     * after the specified amount of time elapses.
15403     * The runnable will be run on the user interface thread.</p>
15404     *
15405     * @param action The Runnable that will be executed.
15406     * @param delayMillis The delay (in milliseconds) until the Runnable
15407     *        will be executed.
15408     *
15409     * @see #postOnAnimation
15410     * @see #removeCallbacks
15411     */
15412    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15413        final AttachInfo attachInfo = mAttachInfo;
15414        if (attachInfo != null) {
15415            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15416                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15417        } else {
15418            // Postpone the runnable until we know
15419            // on which thread it needs to run.
15420            getRunQueue().postDelayed(action, delayMillis);
15421        }
15422    }
15423
15424    /**
15425     * <p>Removes the specified Runnable from the message queue.</p>
15426     *
15427     * @param action The Runnable to remove from the message handling queue
15428     *
15429     * @return true if this view could ask the Handler to remove the Runnable,
15430     *         false otherwise. When the returned value is true, the Runnable
15431     *         may or may not have been actually removed from the message queue
15432     *         (for instance, if the Runnable was not in the queue already.)
15433     *
15434     * @see #post
15435     * @see #postDelayed
15436     * @see #postOnAnimation
15437     * @see #postOnAnimationDelayed
15438     */
15439    public boolean removeCallbacks(Runnable action) {
15440        if (action != null) {
15441            final AttachInfo attachInfo = mAttachInfo;
15442            if (attachInfo != null) {
15443                attachInfo.mHandler.removeCallbacks(action);
15444                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15445                        Choreographer.CALLBACK_ANIMATION, action, null);
15446            }
15447            getRunQueue().removeCallbacks(action);
15448        }
15449        return true;
15450    }
15451
15452    /**
15453     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15454     * Use this to invalidate the View from a non-UI thread.</p>
15455     *
15456     * <p>This method can be invoked from outside of the UI thread
15457     * only when this View is attached to a window.</p>
15458     *
15459     * @see #invalidate()
15460     * @see #postInvalidateDelayed(long)
15461     */
15462    public void postInvalidate() {
15463        postInvalidateDelayed(0);
15464    }
15465
15466    /**
15467     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15468     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15469     *
15470     * <p>This method can be invoked from outside of the UI thread
15471     * only when this View is attached to a window.</p>
15472     *
15473     * @param left The left coordinate of the rectangle to invalidate.
15474     * @param top The top coordinate of the rectangle to invalidate.
15475     * @param right The right coordinate of the rectangle to invalidate.
15476     * @param bottom The bottom coordinate of the rectangle to invalidate.
15477     *
15478     * @see #invalidate(int, int, int, int)
15479     * @see #invalidate(Rect)
15480     * @see #postInvalidateDelayed(long, int, int, int, int)
15481     */
15482    public void postInvalidate(int left, int top, int right, int bottom) {
15483        postInvalidateDelayed(0, left, top, right, bottom);
15484    }
15485
15486    /**
15487     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15488     * loop. Waits for the specified amount of time.</p>
15489     *
15490     * <p>This method can be invoked from outside of the UI thread
15491     * only when this View is attached to a window.</p>
15492     *
15493     * @param delayMilliseconds the duration in milliseconds to delay the
15494     *         invalidation by
15495     *
15496     * @see #invalidate()
15497     * @see #postInvalidate()
15498     */
15499    public void postInvalidateDelayed(long delayMilliseconds) {
15500        // We try only with the AttachInfo because there's no point in invalidating
15501        // if we are not attached to our window
15502        final AttachInfo attachInfo = mAttachInfo;
15503        if (attachInfo != null) {
15504            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15505        }
15506    }
15507
15508    /**
15509     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15510     * through the event loop. Waits for the specified amount of time.</p>
15511     *
15512     * <p>This method can be invoked from outside of the UI thread
15513     * only when this View is attached to a window.</p>
15514     *
15515     * @param delayMilliseconds the duration in milliseconds to delay the
15516     *         invalidation by
15517     * @param left The left coordinate of the rectangle to invalidate.
15518     * @param top The top coordinate of the rectangle to invalidate.
15519     * @param right The right coordinate of the rectangle to invalidate.
15520     * @param bottom The bottom coordinate of the rectangle to invalidate.
15521     *
15522     * @see #invalidate(int, int, int, int)
15523     * @see #invalidate(Rect)
15524     * @see #postInvalidate(int, int, int, int)
15525     */
15526    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15527            int right, int bottom) {
15528
15529        // We try only with the AttachInfo because there's no point in invalidating
15530        // if we are not attached to our window
15531        final AttachInfo attachInfo = mAttachInfo;
15532        if (attachInfo != null) {
15533            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15534            info.target = this;
15535            info.left = left;
15536            info.top = top;
15537            info.right = right;
15538            info.bottom = bottom;
15539
15540            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15541        }
15542    }
15543
15544    /**
15545     * <p>Cause an invalidate to happen on the next animation time step, typically the
15546     * next display frame.</p>
15547     *
15548     * <p>This method can be invoked from outside of the UI thread
15549     * only when this View is attached to a window.</p>
15550     *
15551     * @see #invalidate()
15552     */
15553    public void postInvalidateOnAnimation() {
15554        // We try only with the AttachInfo because there's no point in invalidating
15555        // if we are not attached to our window
15556        final AttachInfo attachInfo = mAttachInfo;
15557        if (attachInfo != null) {
15558            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15559        }
15560    }
15561
15562    /**
15563     * <p>Cause an invalidate of the specified area to happen on the next animation
15564     * time step, typically the next display frame.</p>
15565     *
15566     * <p>This method can be invoked from outside of the UI thread
15567     * only when this View is attached to a window.</p>
15568     *
15569     * @param left The left coordinate of the rectangle to invalidate.
15570     * @param top The top coordinate of the rectangle to invalidate.
15571     * @param right The right coordinate of the rectangle to invalidate.
15572     * @param bottom The bottom coordinate of the rectangle to invalidate.
15573     *
15574     * @see #invalidate(int, int, int, int)
15575     * @see #invalidate(Rect)
15576     */
15577    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15578        // We try only with the AttachInfo because there's no point in invalidating
15579        // if we are not attached to our window
15580        final AttachInfo attachInfo = mAttachInfo;
15581        if (attachInfo != null) {
15582            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15583            info.target = this;
15584            info.left = left;
15585            info.top = top;
15586            info.right = right;
15587            info.bottom = bottom;
15588
15589            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15590        }
15591    }
15592
15593    /**
15594     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15595     * This event is sent at most once every
15596     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15597     */
15598    private void postSendViewScrolledAccessibilityEventCallback() {
15599        if (mSendViewScrolledAccessibilityEvent == null) {
15600            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15601        }
15602        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15603            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15604            postDelayed(mSendViewScrolledAccessibilityEvent,
15605                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15606        }
15607    }
15608
15609    /**
15610     * Called by a parent to request that a child update its values for mScrollX
15611     * and mScrollY if necessary. This will typically be done if the child is
15612     * animating a scroll using a {@link android.widget.Scroller Scroller}
15613     * object.
15614     */
15615    public void computeScroll() {
15616    }
15617
15618    /**
15619     * <p>Indicate whether the horizontal edges are faded when the view is
15620     * scrolled horizontally.</p>
15621     *
15622     * @return true if the horizontal edges should are faded on scroll, false
15623     *         otherwise
15624     *
15625     * @see #setHorizontalFadingEdgeEnabled(boolean)
15626     *
15627     * @attr ref android.R.styleable#View_requiresFadingEdge
15628     */
15629    public boolean isHorizontalFadingEdgeEnabled() {
15630        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15631    }
15632
15633    /**
15634     * <p>Define whether the horizontal edges should be faded when this view
15635     * is scrolled horizontally.</p>
15636     *
15637     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15638     *                                    be faded when the view is scrolled
15639     *                                    horizontally
15640     *
15641     * @see #isHorizontalFadingEdgeEnabled()
15642     *
15643     * @attr ref android.R.styleable#View_requiresFadingEdge
15644     */
15645    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15646        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15647            if (horizontalFadingEdgeEnabled) {
15648                initScrollCache();
15649            }
15650
15651            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15652        }
15653    }
15654
15655    /**
15656     * <p>Indicate whether the vertical edges are faded when the view is
15657     * scrolled horizontally.</p>
15658     *
15659     * @return true if the vertical edges should are faded on scroll, false
15660     *         otherwise
15661     *
15662     * @see #setVerticalFadingEdgeEnabled(boolean)
15663     *
15664     * @attr ref android.R.styleable#View_requiresFadingEdge
15665     */
15666    public boolean isVerticalFadingEdgeEnabled() {
15667        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15668    }
15669
15670    /**
15671     * <p>Define whether the vertical edges should be faded when this view
15672     * is scrolled vertically.</p>
15673     *
15674     * @param verticalFadingEdgeEnabled true if the vertical edges should
15675     *                                  be faded when the view is scrolled
15676     *                                  vertically
15677     *
15678     * @see #isVerticalFadingEdgeEnabled()
15679     *
15680     * @attr ref android.R.styleable#View_requiresFadingEdge
15681     */
15682    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15683        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15684            if (verticalFadingEdgeEnabled) {
15685                initScrollCache();
15686            }
15687
15688            mViewFlags ^= FADING_EDGE_VERTICAL;
15689        }
15690    }
15691
15692    /**
15693     * Returns the strength, or intensity, of the top faded edge. The strength is
15694     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15695     * returns 0.0 or 1.0 but no value in between.
15696     *
15697     * Subclasses should override this method to provide a smoother fade transition
15698     * when scrolling occurs.
15699     *
15700     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15701     */
15702    protected float getTopFadingEdgeStrength() {
15703        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15704    }
15705
15706    /**
15707     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15708     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15709     * returns 0.0 or 1.0 but no value in between.
15710     *
15711     * Subclasses should override this method to provide a smoother fade transition
15712     * when scrolling occurs.
15713     *
15714     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15715     */
15716    protected float getBottomFadingEdgeStrength() {
15717        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15718                computeVerticalScrollRange() ? 1.0f : 0.0f;
15719    }
15720
15721    /**
15722     * Returns the strength, or intensity, of the left faded edge. The strength is
15723     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15724     * returns 0.0 or 1.0 but no value in between.
15725     *
15726     * Subclasses should override this method to provide a smoother fade transition
15727     * when scrolling occurs.
15728     *
15729     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15730     */
15731    protected float getLeftFadingEdgeStrength() {
15732        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15733    }
15734
15735    /**
15736     * Returns the strength, or intensity, of the right faded edge. The strength is
15737     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15738     * returns 0.0 or 1.0 but no value in between.
15739     *
15740     * Subclasses should override this method to provide a smoother fade transition
15741     * when scrolling occurs.
15742     *
15743     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15744     */
15745    protected float getRightFadingEdgeStrength() {
15746        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15747                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15748    }
15749
15750    /**
15751     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15752     * scrollbar is not drawn by default.</p>
15753     *
15754     * @return true if the horizontal scrollbar should be painted, false
15755     *         otherwise
15756     *
15757     * @see #setHorizontalScrollBarEnabled(boolean)
15758     */
15759    public boolean isHorizontalScrollBarEnabled() {
15760        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15761    }
15762
15763    /**
15764     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15765     * scrollbar is not drawn by default.</p>
15766     *
15767     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15768     *                                   be painted
15769     *
15770     * @see #isHorizontalScrollBarEnabled()
15771     */
15772    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15773        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15774            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15775            computeOpaqueFlags();
15776            resolvePadding();
15777        }
15778    }
15779
15780    /**
15781     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15782     * scrollbar is not drawn by default.</p>
15783     *
15784     * @return true if the vertical scrollbar should be painted, false
15785     *         otherwise
15786     *
15787     * @see #setVerticalScrollBarEnabled(boolean)
15788     */
15789    public boolean isVerticalScrollBarEnabled() {
15790        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15791    }
15792
15793    /**
15794     * <p>Define whether the vertical scrollbar should be drawn or not. The
15795     * scrollbar is not drawn by default.</p>
15796     *
15797     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15798     *                                 be painted
15799     *
15800     * @see #isVerticalScrollBarEnabled()
15801     */
15802    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15803        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15804            mViewFlags ^= SCROLLBARS_VERTICAL;
15805            computeOpaqueFlags();
15806            resolvePadding();
15807        }
15808    }
15809
15810    /**
15811     * @hide
15812     */
15813    protected void recomputePadding() {
15814        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15815    }
15816
15817    /**
15818     * Define whether scrollbars will fade when the view is not scrolling.
15819     *
15820     * @param fadeScrollbars whether to enable fading
15821     *
15822     * @attr ref android.R.styleable#View_fadeScrollbars
15823     */
15824    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15825        initScrollCache();
15826        final ScrollabilityCache scrollabilityCache = mScrollCache;
15827        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15828        if (fadeScrollbars) {
15829            scrollabilityCache.state = ScrollabilityCache.OFF;
15830        } else {
15831            scrollabilityCache.state = ScrollabilityCache.ON;
15832        }
15833    }
15834
15835    /**
15836     *
15837     * Returns true if scrollbars will fade when this view is not scrolling
15838     *
15839     * @return true if scrollbar fading is enabled
15840     *
15841     * @attr ref android.R.styleable#View_fadeScrollbars
15842     */
15843    public boolean isScrollbarFadingEnabled() {
15844        return mScrollCache != null && mScrollCache.fadeScrollBars;
15845    }
15846
15847    /**
15848     *
15849     * Returns the delay before scrollbars fade.
15850     *
15851     * @return the delay before scrollbars fade
15852     *
15853     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15854     */
15855    public int getScrollBarDefaultDelayBeforeFade() {
15856        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15857                mScrollCache.scrollBarDefaultDelayBeforeFade;
15858    }
15859
15860    /**
15861     * Define the delay before scrollbars fade.
15862     *
15863     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15864     *
15865     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15866     */
15867    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15868        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15869    }
15870
15871    /**
15872     *
15873     * Returns the scrollbar fade duration.
15874     *
15875     * @return the scrollbar fade duration, in milliseconds
15876     *
15877     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15878     */
15879    public int getScrollBarFadeDuration() {
15880        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15881                mScrollCache.scrollBarFadeDuration;
15882    }
15883
15884    /**
15885     * Define the scrollbar fade duration.
15886     *
15887     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15888     *
15889     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15890     */
15891    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15892        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15893    }
15894
15895    /**
15896     *
15897     * Returns the scrollbar size.
15898     *
15899     * @return the scrollbar size
15900     *
15901     * @attr ref android.R.styleable#View_scrollbarSize
15902     */
15903    public int getScrollBarSize() {
15904        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15905                mScrollCache.scrollBarSize;
15906    }
15907
15908    /**
15909     * Define the scrollbar size.
15910     *
15911     * @param scrollBarSize - the scrollbar size
15912     *
15913     * @attr ref android.R.styleable#View_scrollbarSize
15914     */
15915    public void setScrollBarSize(int scrollBarSize) {
15916        getScrollCache().scrollBarSize = scrollBarSize;
15917    }
15918
15919    /**
15920     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15921     * inset. When inset, they add to the padding of the view. And the scrollbars
15922     * can be drawn inside the padding area or on the edge of the view. For example,
15923     * if a view has a background drawable and you want to draw the scrollbars
15924     * inside the padding specified by the drawable, you can use
15925     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15926     * appear at the edge of the view, ignoring the padding, then you can use
15927     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15928     * @param style the style of the scrollbars. Should be one of
15929     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15930     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15931     * @see #SCROLLBARS_INSIDE_OVERLAY
15932     * @see #SCROLLBARS_INSIDE_INSET
15933     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15934     * @see #SCROLLBARS_OUTSIDE_INSET
15935     *
15936     * @attr ref android.R.styleable#View_scrollbarStyle
15937     */
15938    public void setScrollBarStyle(@ScrollBarStyle int style) {
15939        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15940            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15941            computeOpaqueFlags();
15942            resolvePadding();
15943        }
15944    }
15945
15946    /**
15947     * <p>Returns the current scrollbar style.</p>
15948     * @return the current scrollbar style
15949     * @see #SCROLLBARS_INSIDE_OVERLAY
15950     * @see #SCROLLBARS_INSIDE_INSET
15951     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15952     * @see #SCROLLBARS_OUTSIDE_INSET
15953     *
15954     * @attr ref android.R.styleable#View_scrollbarStyle
15955     */
15956    @ViewDebug.ExportedProperty(mapping = {
15957            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15958            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15959            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15960            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15961    })
15962    @ScrollBarStyle
15963    public int getScrollBarStyle() {
15964        return mViewFlags & SCROLLBARS_STYLE_MASK;
15965    }
15966
15967    /**
15968     * <p>Compute the horizontal range that the horizontal scrollbar
15969     * represents.</p>
15970     *
15971     * <p>The range is expressed in arbitrary units that must be the same as the
15972     * units used by {@link #computeHorizontalScrollExtent()} and
15973     * {@link #computeHorizontalScrollOffset()}.</p>
15974     *
15975     * <p>The default range is the drawing width of this view.</p>
15976     *
15977     * @return the total horizontal range represented by the horizontal
15978     *         scrollbar
15979     *
15980     * @see #computeHorizontalScrollExtent()
15981     * @see #computeHorizontalScrollOffset()
15982     * @see android.widget.ScrollBarDrawable
15983     */
15984    protected int computeHorizontalScrollRange() {
15985        return getWidth();
15986    }
15987
15988    /**
15989     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15990     * within the horizontal range. This value is used to compute the position
15991     * of the thumb within the scrollbar's track.</p>
15992     *
15993     * <p>The range is expressed in arbitrary units that must be the same as the
15994     * units used by {@link #computeHorizontalScrollRange()} and
15995     * {@link #computeHorizontalScrollExtent()}.</p>
15996     *
15997     * <p>The default offset is the scroll offset of this view.</p>
15998     *
15999     * @return the horizontal offset of the scrollbar's thumb
16000     *
16001     * @see #computeHorizontalScrollRange()
16002     * @see #computeHorizontalScrollExtent()
16003     * @see android.widget.ScrollBarDrawable
16004     */
16005    protected int computeHorizontalScrollOffset() {
16006        return mScrollX;
16007    }
16008
16009    /**
16010     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16011     * within the horizontal range. This value is used to compute the length
16012     * of the thumb within the scrollbar's track.</p>
16013     *
16014     * <p>The range is expressed in arbitrary units that must be the same as the
16015     * units used by {@link #computeHorizontalScrollRange()} and
16016     * {@link #computeHorizontalScrollOffset()}.</p>
16017     *
16018     * <p>The default extent is the drawing width of this view.</p>
16019     *
16020     * @return the horizontal extent of the scrollbar's thumb
16021     *
16022     * @see #computeHorizontalScrollRange()
16023     * @see #computeHorizontalScrollOffset()
16024     * @see android.widget.ScrollBarDrawable
16025     */
16026    protected int computeHorizontalScrollExtent() {
16027        return getWidth();
16028    }
16029
16030    /**
16031     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16032     *
16033     * <p>The range is expressed in arbitrary units that must be the same as the
16034     * units used by {@link #computeVerticalScrollExtent()} and
16035     * {@link #computeVerticalScrollOffset()}.</p>
16036     *
16037     * @return the total vertical range represented by the vertical scrollbar
16038     *
16039     * <p>The default range is the drawing height of this view.</p>
16040     *
16041     * @see #computeVerticalScrollExtent()
16042     * @see #computeVerticalScrollOffset()
16043     * @see android.widget.ScrollBarDrawable
16044     */
16045    protected int computeVerticalScrollRange() {
16046        return getHeight();
16047    }
16048
16049    /**
16050     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16051     * within the horizontal range. This value is used to compute the position
16052     * of the thumb within the scrollbar's track.</p>
16053     *
16054     * <p>The range is expressed in arbitrary units that must be the same as the
16055     * units used by {@link #computeVerticalScrollRange()} and
16056     * {@link #computeVerticalScrollExtent()}.</p>
16057     *
16058     * <p>The default offset is the scroll offset of this view.</p>
16059     *
16060     * @return the vertical offset of the scrollbar's thumb
16061     *
16062     * @see #computeVerticalScrollRange()
16063     * @see #computeVerticalScrollExtent()
16064     * @see android.widget.ScrollBarDrawable
16065     */
16066    protected int computeVerticalScrollOffset() {
16067        return mScrollY;
16068    }
16069
16070    /**
16071     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16072     * within the vertical range. This value is used to compute the length
16073     * of the thumb within the scrollbar's track.</p>
16074     *
16075     * <p>The range is expressed in arbitrary units that must be the same as the
16076     * units used by {@link #computeVerticalScrollRange()} and
16077     * {@link #computeVerticalScrollOffset()}.</p>
16078     *
16079     * <p>The default extent is the drawing height of this view.</p>
16080     *
16081     * @return the vertical extent of the scrollbar's thumb
16082     *
16083     * @see #computeVerticalScrollRange()
16084     * @see #computeVerticalScrollOffset()
16085     * @see android.widget.ScrollBarDrawable
16086     */
16087    protected int computeVerticalScrollExtent() {
16088        return getHeight();
16089    }
16090
16091    /**
16092     * Check if this view can be scrolled horizontally in a certain direction.
16093     *
16094     * @param direction Negative to check scrolling left, positive to check scrolling right.
16095     * @return true if this view can be scrolled in the specified direction, false otherwise.
16096     */
16097    public boolean canScrollHorizontally(int direction) {
16098        final int offset = computeHorizontalScrollOffset();
16099        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16100        if (range == 0) return false;
16101        if (direction < 0) {
16102            return offset > 0;
16103        } else {
16104            return offset < range - 1;
16105        }
16106    }
16107
16108    /**
16109     * Check if this view can be scrolled vertically in a certain direction.
16110     *
16111     * @param direction Negative to check scrolling up, positive to check scrolling down.
16112     * @return true if this view can be scrolled in the specified direction, false otherwise.
16113     */
16114    public boolean canScrollVertically(int direction) {
16115        final int offset = computeVerticalScrollOffset();
16116        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16117        if (range == 0) return false;
16118        if (direction < 0) {
16119            return offset > 0;
16120        } else {
16121            return offset < range - 1;
16122        }
16123    }
16124
16125    void getScrollIndicatorBounds(@NonNull Rect out) {
16126        out.left = mScrollX;
16127        out.right = mScrollX + mRight - mLeft;
16128        out.top = mScrollY;
16129        out.bottom = mScrollY + mBottom - mTop;
16130    }
16131
16132    private void onDrawScrollIndicators(Canvas c) {
16133        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16134            // No scroll indicators enabled.
16135            return;
16136        }
16137
16138        final Drawable dr = mScrollIndicatorDrawable;
16139        if (dr == null) {
16140            // Scroll indicators aren't supported here.
16141            return;
16142        }
16143
16144        final int h = dr.getIntrinsicHeight();
16145        final int w = dr.getIntrinsicWidth();
16146        final Rect rect = mAttachInfo.mTmpInvalRect;
16147        getScrollIndicatorBounds(rect);
16148
16149        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16150            final boolean canScrollUp = canScrollVertically(-1);
16151            if (canScrollUp) {
16152                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16153                dr.draw(c);
16154            }
16155        }
16156
16157        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16158            final boolean canScrollDown = canScrollVertically(1);
16159            if (canScrollDown) {
16160                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16161                dr.draw(c);
16162            }
16163        }
16164
16165        final int leftRtl;
16166        final int rightRtl;
16167        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16168            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16169            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16170        } else {
16171            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16172            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16173        }
16174
16175        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16176        if ((mPrivateFlags3 & leftMask) != 0) {
16177            final boolean canScrollLeft = canScrollHorizontally(-1);
16178            if (canScrollLeft) {
16179                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16180                dr.draw(c);
16181            }
16182        }
16183
16184        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16185        if ((mPrivateFlags3 & rightMask) != 0) {
16186            final boolean canScrollRight = canScrollHorizontally(1);
16187            if (canScrollRight) {
16188                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16189                dr.draw(c);
16190            }
16191        }
16192    }
16193
16194    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16195            @Nullable Rect touchBounds) {
16196        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16197        if (bounds == null) {
16198            return;
16199        }
16200        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16201        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16202                && !isVerticalScrollBarHidden();
16203        final int size = getHorizontalScrollbarHeight();
16204        final int verticalScrollBarGap = drawVerticalScrollBar ?
16205                getVerticalScrollbarWidth() : 0;
16206        final int width = mRight - mLeft;
16207        final int height = mBottom - mTop;
16208        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16209        bounds.left = mScrollX + (mPaddingLeft & inside);
16210        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16211        bounds.bottom = bounds.top + size;
16212
16213        if (touchBounds == null) {
16214            return;
16215        }
16216        if (touchBounds != bounds) {
16217            touchBounds.set(bounds);
16218        }
16219        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16220        if (touchBounds.height() < minTouchTarget) {
16221            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16222            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16223            touchBounds.top = touchBounds.bottom - minTouchTarget;
16224        }
16225        if (touchBounds.width() < minTouchTarget) {
16226            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16227            touchBounds.left -= adjust;
16228            touchBounds.right = touchBounds.left + minTouchTarget;
16229        }
16230    }
16231
16232    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16233        if (mRoundScrollbarRenderer == null) {
16234            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16235        } else {
16236            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16237        }
16238    }
16239
16240    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16241        final int width = mRight - mLeft;
16242        final int height = mBottom - mTop;
16243        // Do not take padding into account as we always want the scrollbars
16244        // to hug the screen for round wearable devices.
16245        bounds.left = mScrollX;
16246        bounds.top = mScrollY;
16247        bounds.right = bounds.left + width;
16248        bounds.bottom = mScrollY + height;
16249    }
16250
16251    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16252            @Nullable Rect touchBounds) {
16253        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16254        if (bounds == null) {
16255            return;
16256        }
16257        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16258        final int size = getVerticalScrollbarWidth();
16259        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16260        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16261            verticalScrollbarPosition = isLayoutRtl() ?
16262                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16263        }
16264        final int width = mRight - mLeft;
16265        final int height = mBottom - mTop;
16266        switch (verticalScrollbarPosition) {
16267            default:
16268            case SCROLLBAR_POSITION_RIGHT:
16269                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16270                break;
16271            case SCROLLBAR_POSITION_LEFT:
16272                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16273                break;
16274        }
16275        bounds.top = mScrollY + (mPaddingTop & inside);
16276        bounds.right = bounds.left + size;
16277        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16278
16279        if (touchBounds == null) {
16280            return;
16281        }
16282        if (touchBounds != bounds) {
16283            touchBounds.set(bounds);
16284        }
16285        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16286        if (touchBounds.width() < minTouchTarget) {
16287            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16288            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16289                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16290                touchBounds.left = touchBounds.right - minTouchTarget;
16291            } else {
16292                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16293                touchBounds.right = touchBounds.left + minTouchTarget;
16294            }
16295        }
16296        if (touchBounds.height() < minTouchTarget) {
16297            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16298            touchBounds.top -= adjust;
16299            touchBounds.bottom = touchBounds.top + minTouchTarget;
16300        }
16301    }
16302
16303    /**
16304     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16305     * scrollbars are painted only if they have been awakened first.</p>
16306     *
16307     * @param canvas the canvas on which to draw the scrollbars
16308     *
16309     * @see #awakenScrollBars(int)
16310     */
16311    protected final void onDrawScrollBars(Canvas canvas) {
16312        // scrollbars are drawn only when the animation is running
16313        final ScrollabilityCache cache = mScrollCache;
16314
16315        if (cache != null) {
16316
16317            int state = cache.state;
16318
16319            if (state == ScrollabilityCache.OFF) {
16320                return;
16321            }
16322
16323            boolean invalidate = false;
16324
16325            if (state == ScrollabilityCache.FADING) {
16326                // We're fading -- get our fade interpolation
16327                if (cache.interpolatorValues == null) {
16328                    cache.interpolatorValues = new float[1];
16329                }
16330
16331                float[] values = cache.interpolatorValues;
16332
16333                // Stops the animation if we're done
16334                if (cache.scrollBarInterpolator.timeToValues(values) ==
16335                        Interpolator.Result.FREEZE_END) {
16336                    cache.state = ScrollabilityCache.OFF;
16337                } else {
16338                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16339                }
16340
16341                // This will make the scroll bars inval themselves after
16342                // drawing. We only want this when we're fading so that
16343                // we prevent excessive redraws
16344                invalidate = true;
16345            } else {
16346                // We're just on -- but we may have been fading before so
16347                // reset alpha
16348                cache.scrollBar.mutate().setAlpha(255);
16349            }
16350
16351            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16352            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16353                    && !isVerticalScrollBarHidden();
16354
16355            // Fork out the scroll bar drawing for round wearable devices.
16356            if (mRoundScrollbarRenderer != null) {
16357                if (drawVerticalScrollBar) {
16358                    final Rect bounds = cache.mScrollBarBounds;
16359                    getVerticalScrollBarBounds(bounds, null);
16360                    mRoundScrollbarRenderer.drawRoundScrollbars(
16361                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16362                    if (invalidate) {
16363                        invalidate();
16364                    }
16365                }
16366                // Do not draw horizontal scroll bars for round wearable devices.
16367            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16368                final ScrollBarDrawable scrollBar = cache.scrollBar;
16369
16370                if (drawHorizontalScrollBar) {
16371                    scrollBar.setParameters(computeHorizontalScrollRange(),
16372                            computeHorizontalScrollOffset(),
16373                            computeHorizontalScrollExtent(), false);
16374                    final Rect bounds = cache.mScrollBarBounds;
16375                    getHorizontalScrollBarBounds(bounds, null);
16376                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16377                            bounds.right, bounds.bottom);
16378                    if (invalidate) {
16379                        invalidate(bounds);
16380                    }
16381                }
16382
16383                if (drawVerticalScrollBar) {
16384                    scrollBar.setParameters(computeVerticalScrollRange(),
16385                            computeVerticalScrollOffset(),
16386                            computeVerticalScrollExtent(), true);
16387                    final Rect bounds = cache.mScrollBarBounds;
16388                    getVerticalScrollBarBounds(bounds, null);
16389                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16390                            bounds.right, bounds.bottom);
16391                    if (invalidate) {
16392                        invalidate(bounds);
16393                    }
16394                }
16395            }
16396        }
16397    }
16398
16399    /**
16400     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16401     * FastScroller is visible.
16402     * @return whether to temporarily hide the vertical scrollbar
16403     * @hide
16404     */
16405    protected boolean isVerticalScrollBarHidden() {
16406        return false;
16407    }
16408
16409    /**
16410     * <p>Draw the horizontal scrollbar if
16411     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16412     *
16413     * @param canvas the canvas on which to draw the scrollbar
16414     * @param scrollBar the scrollbar's drawable
16415     *
16416     * @see #isHorizontalScrollBarEnabled()
16417     * @see #computeHorizontalScrollRange()
16418     * @see #computeHorizontalScrollExtent()
16419     * @see #computeHorizontalScrollOffset()
16420     * @see android.widget.ScrollBarDrawable
16421     * @hide
16422     */
16423    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16424            int l, int t, int r, int b) {
16425        scrollBar.setBounds(l, t, r, b);
16426        scrollBar.draw(canvas);
16427    }
16428
16429    /**
16430     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16431     * returns true.</p>
16432     *
16433     * @param canvas the canvas on which to draw the scrollbar
16434     * @param scrollBar the scrollbar's drawable
16435     *
16436     * @see #isVerticalScrollBarEnabled()
16437     * @see #computeVerticalScrollRange()
16438     * @see #computeVerticalScrollExtent()
16439     * @see #computeVerticalScrollOffset()
16440     * @see android.widget.ScrollBarDrawable
16441     * @hide
16442     */
16443    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16444            int l, int t, int r, int b) {
16445        scrollBar.setBounds(l, t, r, b);
16446        scrollBar.draw(canvas);
16447    }
16448
16449    /**
16450     * Implement this to do your drawing.
16451     *
16452     * @param canvas the canvas on which the background will be drawn
16453     */
16454    protected void onDraw(Canvas canvas) {
16455    }
16456
16457    /*
16458     * Caller is responsible for calling requestLayout if necessary.
16459     * (This allows addViewInLayout to not request a new layout.)
16460     */
16461    void assignParent(ViewParent parent) {
16462        if (mParent == null) {
16463            mParent = parent;
16464        } else if (parent == null) {
16465            mParent = null;
16466        } else {
16467            throw new RuntimeException("view " + this + " being added, but"
16468                    + " it already has a parent");
16469        }
16470    }
16471
16472    /**
16473     * This is called when the view is attached to a window.  At this point it
16474     * has a Surface and will start drawing.  Note that this function is
16475     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16476     * however it may be called any time before the first onDraw -- including
16477     * before or after {@link #onMeasure(int, int)}.
16478     *
16479     * @see #onDetachedFromWindow()
16480     */
16481    @CallSuper
16482    protected void onAttachedToWindow() {
16483        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16484            mParent.requestTransparentRegion(this);
16485        }
16486
16487        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16488
16489        jumpDrawablesToCurrentState();
16490
16491        resetSubtreeAccessibilityStateChanged();
16492
16493        // rebuild, since Outline not maintained while View is detached
16494        rebuildOutline();
16495
16496        if (isFocused()) {
16497            InputMethodManager imm = InputMethodManager.peekInstance();
16498            if (imm != null) {
16499                imm.focusIn(this);
16500            }
16501        }
16502    }
16503
16504    /**
16505     * Resolve all RTL related properties.
16506     *
16507     * @return true if resolution of RTL properties has been done
16508     *
16509     * @hide
16510     */
16511    public boolean resolveRtlPropertiesIfNeeded() {
16512        if (!needRtlPropertiesResolution()) return false;
16513
16514        // Order is important here: LayoutDirection MUST be resolved first
16515        if (!isLayoutDirectionResolved()) {
16516            resolveLayoutDirection();
16517            resolveLayoutParams();
16518        }
16519        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16520        if (!isTextDirectionResolved()) {
16521            resolveTextDirection();
16522        }
16523        if (!isTextAlignmentResolved()) {
16524            resolveTextAlignment();
16525        }
16526        // Should resolve Drawables before Padding because we need the layout direction of the
16527        // Drawable to correctly resolve Padding.
16528        if (!areDrawablesResolved()) {
16529            resolveDrawables();
16530        }
16531        if (!isPaddingResolved()) {
16532            resolvePadding();
16533        }
16534        onRtlPropertiesChanged(getLayoutDirection());
16535        return true;
16536    }
16537
16538    /**
16539     * Reset resolution of all RTL related properties.
16540     *
16541     * @hide
16542     */
16543    public void resetRtlProperties() {
16544        resetResolvedLayoutDirection();
16545        resetResolvedTextDirection();
16546        resetResolvedTextAlignment();
16547        resetResolvedPadding();
16548        resetResolvedDrawables();
16549    }
16550
16551    /**
16552     * @see #onScreenStateChanged(int)
16553     */
16554    void dispatchScreenStateChanged(int screenState) {
16555        onScreenStateChanged(screenState);
16556    }
16557
16558    /**
16559     * This method is called whenever the state of the screen this view is
16560     * attached to changes. A state change will usually occurs when the screen
16561     * turns on or off (whether it happens automatically or the user does it
16562     * manually.)
16563     *
16564     * @param screenState The new state of the screen. Can be either
16565     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16566     */
16567    public void onScreenStateChanged(int screenState) {
16568    }
16569
16570    /**
16571     * @see #onMovedToDisplay(int, Configuration)
16572     */
16573    void dispatchMovedToDisplay(Display display, Configuration config) {
16574        mAttachInfo.mDisplay = display;
16575        mAttachInfo.mDisplayState = display.getState();
16576        onMovedToDisplay(display.getDisplayId(), config);
16577    }
16578
16579    /**
16580     * Called by the system when the hosting activity is moved from one display to another without
16581     * recreation. This means that the activity is declared to handle all changes to configuration
16582     * that happened when it was switched to another display, so it wasn't destroyed and created
16583     * again.
16584     *
16585     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16586     * applied configuration actually changed. It is up to app developer to choose whether to handle
16587     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16588     * call.
16589     *
16590     * <p>Use this callback to track changes to the displays if some functionality relies on an
16591     * association with some display properties.
16592     *
16593     * @param displayId The id of the display to which the view was moved.
16594     * @param config Configuration of the resources on new display after move.
16595     *
16596     * @see #onConfigurationChanged(Configuration)
16597     */
16598    public void onMovedToDisplay(int displayId, Configuration config) {
16599    }
16600
16601    /**
16602     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16603     */
16604    private boolean hasRtlSupport() {
16605        return mContext.getApplicationInfo().hasRtlSupport();
16606    }
16607
16608    /**
16609     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16610     * RTL not supported)
16611     */
16612    private boolean isRtlCompatibilityMode() {
16613        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16614        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16615    }
16616
16617    /**
16618     * @return true if RTL properties need resolution.
16619     *
16620     */
16621    private boolean needRtlPropertiesResolution() {
16622        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16623    }
16624
16625    /**
16626     * Called when any RTL property (layout direction or text direction or text alignment) has
16627     * been changed.
16628     *
16629     * Subclasses need to override this method to take care of cached information that depends on the
16630     * resolved layout direction, or to inform child views that inherit their layout direction.
16631     *
16632     * The default implementation does nothing.
16633     *
16634     * @param layoutDirection the direction of the layout
16635     *
16636     * @see #LAYOUT_DIRECTION_LTR
16637     * @see #LAYOUT_DIRECTION_RTL
16638     */
16639    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16640    }
16641
16642    /**
16643     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16644     * that the parent directionality can and will be resolved before its children.
16645     *
16646     * @return true if resolution has been done, false otherwise.
16647     *
16648     * @hide
16649     */
16650    public boolean resolveLayoutDirection() {
16651        // Clear any previous layout direction resolution
16652        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16653
16654        if (hasRtlSupport()) {
16655            // Set resolved depending on layout direction
16656            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16657                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16658                case LAYOUT_DIRECTION_INHERIT:
16659                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16660                    // later to get the correct resolved value
16661                    if (!canResolveLayoutDirection()) return false;
16662
16663                    // Parent has not yet resolved, LTR is still the default
16664                    try {
16665                        if (!mParent.isLayoutDirectionResolved()) return false;
16666
16667                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16668                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16669                        }
16670                    } catch (AbstractMethodError e) {
16671                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16672                                " does not fully implement ViewParent", e);
16673                    }
16674                    break;
16675                case LAYOUT_DIRECTION_RTL:
16676                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16677                    break;
16678                case LAYOUT_DIRECTION_LOCALE:
16679                    if((LAYOUT_DIRECTION_RTL ==
16680                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16681                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16682                    }
16683                    break;
16684                default:
16685                    // Nothing to do, LTR by default
16686            }
16687        }
16688
16689        // Set to resolved
16690        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16691        return true;
16692    }
16693
16694    /**
16695     * Check if layout direction resolution can be done.
16696     *
16697     * @return true if layout direction resolution can be done otherwise return false.
16698     */
16699    public boolean canResolveLayoutDirection() {
16700        switch (getRawLayoutDirection()) {
16701            case LAYOUT_DIRECTION_INHERIT:
16702                if (mParent != null) {
16703                    try {
16704                        return mParent.canResolveLayoutDirection();
16705                    } catch (AbstractMethodError e) {
16706                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16707                                " does not fully implement ViewParent", e);
16708                    }
16709                }
16710                return false;
16711
16712            default:
16713                return true;
16714        }
16715    }
16716
16717    /**
16718     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16719     * {@link #onMeasure(int, int)}.
16720     *
16721     * @hide
16722     */
16723    public void resetResolvedLayoutDirection() {
16724        // Reset the current resolved bits
16725        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16726    }
16727
16728    /**
16729     * @return true if the layout direction is inherited.
16730     *
16731     * @hide
16732     */
16733    public boolean isLayoutDirectionInherited() {
16734        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16735    }
16736
16737    /**
16738     * @return true if layout direction has been resolved.
16739     */
16740    public boolean isLayoutDirectionResolved() {
16741        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16742    }
16743
16744    /**
16745     * Return if padding has been resolved
16746     *
16747     * @hide
16748     */
16749    boolean isPaddingResolved() {
16750        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16751    }
16752
16753    /**
16754     * Resolves padding depending on layout direction, if applicable, and
16755     * recomputes internal padding values to adjust for scroll bars.
16756     *
16757     * @hide
16758     */
16759    public void resolvePadding() {
16760        final int resolvedLayoutDirection = getLayoutDirection();
16761
16762        if (!isRtlCompatibilityMode()) {
16763            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16764            // If start / end padding are defined, they will be resolved (hence overriding) to
16765            // left / right or right / left depending on the resolved layout direction.
16766            // If start / end padding are not defined, use the left / right ones.
16767            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16768                Rect padding = sThreadLocal.get();
16769                if (padding == null) {
16770                    padding = new Rect();
16771                    sThreadLocal.set(padding);
16772                }
16773                mBackground.getPadding(padding);
16774                if (!mLeftPaddingDefined) {
16775                    mUserPaddingLeftInitial = padding.left;
16776                }
16777                if (!mRightPaddingDefined) {
16778                    mUserPaddingRightInitial = padding.right;
16779                }
16780            }
16781            switch (resolvedLayoutDirection) {
16782                case LAYOUT_DIRECTION_RTL:
16783                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16784                        mUserPaddingRight = mUserPaddingStart;
16785                    } else {
16786                        mUserPaddingRight = mUserPaddingRightInitial;
16787                    }
16788                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16789                        mUserPaddingLeft = mUserPaddingEnd;
16790                    } else {
16791                        mUserPaddingLeft = mUserPaddingLeftInitial;
16792                    }
16793                    break;
16794                case LAYOUT_DIRECTION_LTR:
16795                default:
16796                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16797                        mUserPaddingLeft = mUserPaddingStart;
16798                    } else {
16799                        mUserPaddingLeft = mUserPaddingLeftInitial;
16800                    }
16801                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16802                        mUserPaddingRight = mUserPaddingEnd;
16803                    } else {
16804                        mUserPaddingRight = mUserPaddingRightInitial;
16805                    }
16806            }
16807
16808            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16809        }
16810
16811        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16812        onRtlPropertiesChanged(resolvedLayoutDirection);
16813
16814        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16815    }
16816
16817    /**
16818     * Reset the resolved layout direction.
16819     *
16820     * @hide
16821     */
16822    public void resetResolvedPadding() {
16823        resetResolvedPaddingInternal();
16824    }
16825
16826    /**
16827     * Used when we only want to reset *this* view's padding and not trigger overrides
16828     * in ViewGroup that reset children too.
16829     */
16830    void resetResolvedPaddingInternal() {
16831        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16832    }
16833
16834    /**
16835     * This is called when the view is detached from a window.  At this point it
16836     * no longer has a surface for drawing.
16837     *
16838     * @see #onAttachedToWindow()
16839     */
16840    @CallSuper
16841    protected void onDetachedFromWindow() {
16842    }
16843
16844    /**
16845     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16846     * after onDetachedFromWindow().
16847     *
16848     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16849     * The super method should be called at the end of the overridden method to ensure
16850     * subclasses are destroyed first
16851     *
16852     * @hide
16853     */
16854    @CallSuper
16855    protected void onDetachedFromWindowInternal() {
16856        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16857        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16858        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16859
16860        removeUnsetPressCallback();
16861        removeLongPressCallback();
16862        removePerformClickCallback();
16863        removeSendViewScrolledAccessibilityEventCallback();
16864        stopNestedScroll();
16865
16866        // Anything that started animating right before detach should already
16867        // be in its final state when re-attached.
16868        jumpDrawablesToCurrentState();
16869
16870        destroyDrawingCache();
16871
16872        cleanupDraw();
16873        mCurrentAnimation = null;
16874
16875        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16876            hideTooltip();
16877        }
16878    }
16879
16880    private void cleanupDraw() {
16881        resetDisplayList();
16882        if (mAttachInfo != null) {
16883            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16884        }
16885    }
16886
16887    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16888    }
16889
16890    /**
16891     * @return The number of times this view has been attached to a window
16892     */
16893    protected int getWindowAttachCount() {
16894        return mWindowAttachCount;
16895    }
16896
16897    /**
16898     * Retrieve a unique token identifying the window this view is attached to.
16899     * @return Return the window's token for use in
16900     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16901     */
16902    public IBinder getWindowToken() {
16903        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16904    }
16905
16906    /**
16907     * Retrieve the {@link WindowId} for the window this view is
16908     * currently attached to.
16909     */
16910    public WindowId getWindowId() {
16911        if (mAttachInfo == null) {
16912            return null;
16913        }
16914        if (mAttachInfo.mWindowId == null) {
16915            try {
16916                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16917                        mAttachInfo.mWindowToken);
16918                mAttachInfo.mWindowId = new WindowId(
16919                        mAttachInfo.mIWindowId);
16920            } catch (RemoteException e) {
16921            }
16922        }
16923        return mAttachInfo.mWindowId;
16924    }
16925
16926    /**
16927     * Retrieve a unique token identifying the top-level "real" window of
16928     * the window that this view is attached to.  That is, this is like
16929     * {@link #getWindowToken}, except if the window this view in is a panel
16930     * window (attached to another containing window), then the token of
16931     * the containing window is returned instead.
16932     *
16933     * @return Returns the associated window token, either
16934     * {@link #getWindowToken()} or the containing window's token.
16935     */
16936    public IBinder getApplicationWindowToken() {
16937        AttachInfo ai = mAttachInfo;
16938        if (ai != null) {
16939            IBinder appWindowToken = ai.mPanelParentWindowToken;
16940            if (appWindowToken == null) {
16941                appWindowToken = ai.mWindowToken;
16942            }
16943            return appWindowToken;
16944        }
16945        return null;
16946    }
16947
16948    /**
16949     * Gets the logical display to which the view's window has been attached.
16950     *
16951     * @return The logical display, or null if the view is not currently attached to a window.
16952     */
16953    public Display getDisplay() {
16954        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16955    }
16956
16957    /**
16958     * Retrieve private session object this view hierarchy is using to
16959     * communicate with the window manager.
16960     * @return the session object to communicate with the window manager
16961     */
16962    /*package*/ IWindowSession getWindowSession() {
16963        return mAttachInfo != null ? mAttachInfo.mSession : null;
16964    }
16965
16966    /**
16967     * Return the visibility value of the least visible component passed.
16968     */
16969    int combineVisibility(int vis1, int vis2) {
16970        // This works because VISIBLE < INVISIBLE < GONE.
16971        return Math.max(vis1, vis2);
16972    }
16973
16974    /**
16975     * @param info the {@link android.view.View.AttachInfo} to associated with
16976     *        this view
16977     */
16978    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16979        mAttachInfo = info;
16980        if (mOverlay != null) {
16981            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16982        }
16983        mWindowAttachCount++;
16984        // We will need to evaluate the drawable state at least once.
16985        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16986        if (mFloatingTreeObserver != null) {
16987            info.mTreeObserver.merge(mFloatingTreeObserver);
16988            mFloatingTreeObserver = null;
16989        }
16990
16991        registerPendingFrameMetricsObservers();
16992
16993        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16994            mAttachInfo.mScrollContainers.add(this);
16995            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16996        }
16997        // Transfer all pending runnables.
16998        if (mRunQueue != null) {
16999            mRunQueue.executeActions(info.mHandler);
17000            mRunQueue = null;
17001        }
17002        performCollectViewAttributes(mAttachInfo, visibility);
17003        onAttachedToWindow();
17004
17005        ListenerInfo li = mListenerInfo;
17006        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17007                li != null ? li.mOnAttachStateChangeListeners : null;
17008        if (listeners != null && listeners.size() > 0) {
17009            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17010            // perform the dispatching. The iterator is a safe guard against listeners that
17011            // could mutate the list by calling the various add/remove methods. This prevents
17012            // the array from being modified while we iterate it.
17013            for (OnAttachStateChangeListener listener : listeners) {
17014                listener.onViewAttachedToWindow(this);
17015            }
17016        }
17017
17018        int vis = info.mWindowVisibility;
17019        if (vis != GONE) {
17020            onWindowVisibilityChanged(vis);
17021            if (isShown()) {
17022                // Calling onVisibilityAggregated directly here since the subtree will also
17023                // receive dispatchAttachedToWindow and this same call
17024                onVisibilityAggregated(vis == VISIBLE);
17025            }
17026        }
17027
17028        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17029        // As all views in the subtree will already receive dispatchAttachedToWindow
17030        // traversing the subtree again here is not desired.
17031        onVisibilityChanged(this, visibility);
17032
17033        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17034            // If nobody has evaluated the drawable state yet, then do it now.
17035            refreshDrawableState();
17036        }
17037        needGlobalAttributesUpdate(false);
17038
17039        notifyEnterOrExitForAutoFillIfNeeded(true);
17040    }
17041
17042    void dispatchDetachedFromWindow() {
17043        AttachInfo info = mAttachInfo;
17044        if (info != null) {
17045            int vis = info.mWindowVisibility;
17046            if (vis != GONE) {
17047                onWindowVisibilityChanged(GONE);
17048                if (isShown()) {
17049                    // Invoking onVisibilityAggregated directly here since the subtree
17050                    // will also receive detached from window
17051                    onVisibilityAggregated(false);
17052                }
17053            }
17054        }
17055
17056        onDetachedFromWindow();
17057        onDetachedFromWindowInternal();
17058
17059        InputMethodManager imm = InputMethodManager.peekInstance();
17060        if (imm != null) {
17061            imm.onViewDetachedFromWindow(this);
17062        }
17063
17064        ListenerInfo li = mListenerInfo;
17065        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17066                li != null ? li.mOnAttachStateChangeListeners : null;
17067        if (listeners != null && listeners.size() > 0) {
17068            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17069            // perform the dispatching. The iterator is a safe guard against listeners that
17070            // could mutate the list by calling the various add/remove methods. This prevents
17071            // the array from being modified while we iterate it.
17072            for (OnAttachStateChangeListener listener : listeners) {
17073                listener.onViewDetachedFromWindow(this);
17074            }
17075        }
17076
17077        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17078            mAttachInfo.mScrollContainers.remove(this);
17079            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17080        }
17081
17082        mAttachInfo = null;
17083        if (mOverlay != null) {
17084            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17085        }
17086
17087        notifyEnterOrExitForAutoFillIfNeeded(false);
17088    }
17089
17090    /**
17091     * Cancel any deferred high-level input events that were previously posted to the event queue.
17092     *
17093     * <p>Many views post high-level events such as click handlers to the event queue
17094     * to run deferred in order to preserve a desired user experience - clearing visible
17095     * pressed states before executing, etc. This method will abort any events of this nature
17096     * that are currently in flight.</p>
17097     *
17098     * <p>Custom views that generate their own high-level deferred input events should override
17099     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17100     *
17101     * <p>This will also cancel pending input events for any child views.</p>
17102     *
17103     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17104     * This will not impact newer events posted after this call that may occur as a result of
17105     * lower-level input events still waiting in the queue. If you are trying to prevent
17106     * double-submitted  events for the duration of some sort of asynchronous transaction
17107     * you should also take other steps to protect against unexpected double inputs e.g. calling
17108     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17109     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17110     */
17111    public final void cancelPendingInputEvents() {
17112        dispatchCancelPendingInputEvents();
17113    }
17114
17115    /**
17116     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17117     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17118     */
17119    void dispatchCancelPendingInputEvents() {
17120        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17121        onCancelPendingInputEvents();
17122        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17123            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17124                    " did not call through to super.onCancelPendingInputEvents()");
17125        }
17126    }
17127
17128    /**
17129     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17130     * a parent view.
17131     *
17132     * <p>This method is responsible for removing any pending high-level input events that were
17133     * posted to the event queue to run later. Custom view classes that post their own deferred
17134     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17135     * {@link android.os.Handler} should override this method, call
17136     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17137     * </p>
17138     */
17139    public void onCancelPendingInputEvents() {
17140        removePerformClickCallback();
17141        cancelLongPress();
17142        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17143    }
17144
17145    /**
17146     * Store this view hierarchy's frozen state into the given container.
17147     *
17148     * @param container The SparseArray in which to save the view's state.
17149     *
17150     * @see #restoreHierarchyState(android.util.SparseArray)
17151     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17152     * @see #onSaveInstanceState()
17153     */
17154    public void saveHierarchyState(SparseArray<Parcelable> container) {
17155        dispatchSaveInstanceState(container);
17156    }
17157
17158    /**
17159     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17160     * this view and its children. May be overridden to modify how freezing happens to a
17161     * view's children; for example, some views may want to not store state for their children.
17162     *
17163     * @param container The SparseArray in which to save the view's state.
17164     *
17165     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17166     * @see #saveHierarchyState(android.util.SparseArray)
17167     * @see #onSaveInstanceState()
17168     */
17169    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17170        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17171            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17172            Parcelable state = onSaveInstanceState();
17173            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17174                throw new IllegalStateException(
17175                        "Derived class did not call super.onSaveInstanceState()");
17176            }
17177            if (state != null) {
17178                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17179                // + ": " + state);
17180                container.put(mID, state);
17181            }
17182        }
17183    }
17184
17185    /**
17186     * Hook allowing a view to generate a representation of its internal state
17187     * that can later be used to create a new instance with that same state.
17188     * This state should only contain information that is not persistent or can
17189     * not be reconstructed later. For example, you will never store your
17190     * current position on screen because that will be computed again when a
17191     * new instance of the view is placed in its view hierarchy.
17192     * <p>
17193     * Some examples of things you may store here: the current cursor position
17194     * in a text view (but usually not the text itself since that is stored in a
17195     * content provider or other persistent storage), the currently selected
17196     * item in a list view.
17197     *
17198     * @return Returns a Parcelable object containing the view's current dynamic
17199     *         state, or null if there is nothing interesting to save. The
17200     *         default implementation returns null.
17201     * @see #onRestoreInstanceState(android.os.Parcelable)
17202     * @see #saveHierarchyState(android.util.SparseArray)
17203     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17204     * @see #setSaveEnabled(boolean)
17205     */
17206    @CallSuper
17207    protected Parcelable onSaveInstanceState() {
17208        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17209        if (mStartActivityRequestWho != null || isAutofilled()
17210                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17211            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17212
17213            if (mStartActivityRequestWho != null) {
17214                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17215            }
17216
17217            if (isAutofilled()) {
17218                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17219            }
17220
17221            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17222                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17223            }
17224
17225            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17226            state.mIsAutofilled = isAutofilled();
17227            state.mAccessibilityViewId = mAccessibilityViewId;
17228            return state;
17229        }
17230        return BaseSavedState.EMPTY_STATE;
17231    }
17232
17233    /**
17234     * Restore this view hierarchy's frozen state from the given container.
17235     *
17236     * @param container The SparseArray which holds previously frozen states.
17237     *
17238     * @see #saveHierarchyState(android.util.SparseArray)
17239     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17240     * @see #onRestoreInstanceState(android.os.Parcelable)
17241     */
17242    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17243        dispatchRestoreInstanceState(container);
17244    }
17245
17246    /**
17247     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17248     * state for this view and its children. May be overridden to modify how restoring
17249     * happens to a view's children; for example, some views may want to not store state
17250     * for their children.
17251     *
17252     * @param container The SparseArray which holds previously saved state.
17253     *
17254     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17255     * @see #restoreHierarchyState(android.util.SparseArray)
17256     * @see #onRestoreInstanceState(android.os.Parcelable)
17257     */
17258    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17259        if (mID != NO_ID) {
17260            Parcelable state = container.get(mID);
17261            if (state != null) {
17262                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17263                // + ": " + state);
17264                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17265                onRestoreInstanceState(state);
17266                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17267                    throw new IllegalStateException(
17268                            "Derived class did not call super.onRestoreInstanceState()");
17269                }
17270            }
17271        }
17272    }
17273
17274    /**
17275     * Hook allowing a view to re-apply a representation of its internal state that had previously
17276     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17277     * null state.
17278     *
17279     * @param state The frozen state that had previously been returned by
17280     *        {@link #onSaveInstanceState}.
17281     *
17282     * @see #onSaveInstanceState()
17283     * @see #restoreHierarchyState(android.util.SparseArray)
17284     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17285     */
17286    @CallSuper
17287    protected void onRestoreInstanceState(Parcelable state) {
17288        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17289        if (state != null && !(state instanceof AbsSavedState)) {
17290            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17291                    + "received " + state.getClass().toString() + " instead. This usually happens "
17292                    + "when two views of different type have the same id in the same hierarchy. "
17293                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17294                    + "other views do not use the same id.");
17295        }
17296        if (state != null && state instanceof BaseSavedState) {
17297            BaseSavedState baseState = (BaseSavedState) state;
17298
17299            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17300                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17301            }
17302            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17303                setAutofilled(baseState.mIsAutofilled);
17304            }
17305            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17306                mAccessibilityViewId = baseState.mAccessibilityViewId;
17307            }
17308        }
17309    }
17310
17311    /**
17312     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17313     *
17314     * @return the drawing start time in milliseconds
17315     */
17316    public long getDrawingTime() {
17317        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17318    }
17319
17320    /**
17321     * <p>Enables or disables the duplication of the parent's state into this view. When
17322     * duplication is enabled, this view gets its drawable state from its parent rather
17323     * than from its own internal properties.</p>
17324     *
17325     * <p>Note: in the current implementation, setting this property to true after the
17326     * view was added to a ViewGroup might have no effect at all. This property should
17327     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17328     *
17329     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17330     * property is enabled, an exception will be thrown.</p>
17331     *
17332     * <p>Note: if the child view uses and updates additional states which are unknown to the
17333     * parent, these states should not be affected by this method.</p>
17334     *
17335     * @param enabled True to enable duplication of the parent's drawable state, false
17336     *                to disable it.
17337     *
17338     * @see #getDrawableState()
17339     * @see #isDuplicateParentStateEnabled()
17340     */
17341    public void setDuplicateParentStateEnabled(boolean enabled) {
17342        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17343    }
17344
17345    /**
17346     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17347     *
17348     * @return True if this view's drawable state is duplicated from the parent,
17349     *         false otherwise
17350     *
17351     * @see #getDrawableState()
17352     * @see #setDuplicateParentStateEnabled(boolean)
17353     */
17354    public boolean isDuplicateParentStateEnabled() {
17355        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17356    }
17357
17358    /**
17359     * <p>Specifies the type of layer backing this view. The layer can be
17360     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17361     * {@link #LAYER_TYPE_HARDWARE}.</p>
17362     *
17363     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17364     * instance that controls how the layer is composed on screen. The following
17365     * properties of the paint are taken into account when composing the layer:</p>
17366     * <ul>
17367     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17368     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17369     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17370     * </ul>
17371     *
17372     * <p>If this view has an alpha value set to < 1.0 by calling
17373     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17374     * by this view's alpha value.</p>
17375     *
17376     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17377     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17378     * for more information on when and how to use layers.</p>
17379     *
17380     * @param layerType The type of layer to use with this view, must be one of
17381     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17382     *        {@link #LAYER_TYPE_HARDWARE}
17383     * @param paint The paint used to compose the layer. This argument is optional
17384     *        and can be null. It is ignored when the layer type is
17385     *        {@link #LAYER_TYPE_NONE}
17386     *
17387     * @see #getLayerType()
17388     * @see #LAYER_TYPE_NONE
17389     * @see #LAYER_TYPE_SOFTWARE
17390     * @see #LAYER_TYPE_HARDWARE
17391     * @see #setAlpha(float)
17392     *
17393     * @attr ref android.R.styleable#View_layerType
17394     */
17395    public void setLayerType(int layerType, @Nullable Paint paint) {
17396        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17397            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17398                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17399        }
17400
17401        boolean typeChanged = mRenderNode.setLayerType(layerType);
17402
17403        if (!typeChanged) {
17404            setLayerPaint(paint);
17405            return;
17406        }
17407
17408        if (layerType != LAYER_TYPE_SOFTWARE) {
17409            // Destroy any previous software drawing cache if present
17410            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17411            // drawing cache created in View#draw when drawing to a SW canvas.
17412            destroyDrawingCache();
17413        }
17414
17415        mLayerType = layerType;
17416        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17417        mRenderNode.setLayerPaint(mLayerPaint);
17418
17419        // draw() behaves differently if we are on a layer, so we need to
17420        // invalidate() here
17421        invalidateParentCaches();
17422        invalidate(true);
17423    }
17424
17425    /**
17426     * Updates the {@link Paint} object used with the current layer (used only if the current
17427     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17428     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17429     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17430     * ensure that the view gets redrawn immediately.
17431     *
17432     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17433     * instance that controls how the layer is composed on screen. The following
17434     * properties of the paint are taken into account when composing the layer:</p>
17435     * <ul>
17436     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17437     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17438     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17439     * </ul>
17440     *
17441     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17442     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17443     *
17444     * @param paint The paint used to compose the layer. This argument is optional
17445     *        and can be null. It is ignored when the layer type is
17446     *        {@link #LAYER_TYPE_NONE}
17447     *
17448     * @see #setLayerType(int, android.graphics.Paint)
17449     */
17450    public void setLayerPaint(@Nullable Paint paint) {
17451        int layerType = getLayerType();
17452        if (layerType != LAYER_TYPE_NONE) {
17453            mLayerPaint = paint;
17454            if (layerType == LAYER_TYPE_HARDWARE) {
17455                if (mRenderNode.setLayerPaint(paint)) {
17456                    invalidateViewProperty(false, false);
17457                }
17458            } else {
17459                invalidate();
17460            }
17461        }
17462    }
17463
17464    /**
17465     * Indicates what type of layer is currently associated with this view. By default
17466     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17467     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17468     * for more information on the different types of layers.
17469     *
17470     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17471     *         {@link #LAYER_TYPE_HARDWARE}
17472     *
17473     * @see #setLayerType(int, android.graphics.Paint)
17474     * @see #buildLayer()
17475     * @see #LAYER_TYPE_NONE
17476     * @see #LAYER_TYPE_SOFTWARE
17477     * @see #LAYER_TYPE_HARDWARE
17478     */
17479    public int getLayerType() {
17480        return mLayerType;
17481    }
17482
17483    /**
17484     * Forces this view's layer to be created and this view to be rendered
17485     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17486     * invoking this method will have no effect.
17487     *
17488     * This method can for instance be used to render a view into its layer before
17489     * starting an animation. If this view is complex, rendering into the layer
17490     * before starting the animation will avoid skipping frames.
17491     *
17492     * @throws IllegalStateException If this view is not attached to a window
17493     *
17494     * @see #setLayerType(int, android.graphics.Paint)
17495     */
17496    public void buildLayer() {
17497        if (mLayerType == LAYER_TYPE_NONE) return;
17498
17499        final AttachInfo attachInfo = mAttachInfo;
17500        if (attachInfo == null) {
17501            throw new IllegalStateException("This view must be attached to a window first");
17502        }
17503
17504        if (getWidth() == 0 || getHeight() == 0) {
17505            return;
17506        }
17507
17508        switch (mLayerType) {
17509            case LAYER_TYPE_HARDWARE:
17510                updateDisplayListIfDirty();
17511                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17512                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17513                }
17514                break;
17515            case LAYER_TYPE_SOFTWARE:
17516                buildDrawingCache(true);
17517                break;
17518        }
17519    }
17520
17521    /**
17522     * Destroys all hardware rendering resources. This method is invoked
17523     * when the system needs to reclaim resources. Upon execution of this
17524     * method, you should free any OpenGL resources created by the view.
17525     *
17526     * Note: you <strong>must</strong> call
17527     * <code>super.destroyHardwareResources()</code> when overriding
17528     * this method.
17529     *
17530     * @hide
17531     */
17532    @CallSuper
17533    protected void destroyHardwareResources() {
17534        if (mOverlay != null) {
17535            mOverlay.getOverlayView().destroyHardwareResources();
17536        }
17537        if (mGhostView != null) {
17538            mGhostView.destroyHardwareResources();
17539        }
17540    }
17541
17542    /**
17543     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17544     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17545     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17546     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17547     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17548     * null.</p>
17549     *
17550     * <p>Enabling the drawing cache is similar to
17551     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17552     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17553     * drawing cache has no effect on rendering because the system uses a different mechanism
17554     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17555     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17556     * for information on how to enable software and hardware layers.</p>
17557     *
17558     * <p>This API can be used to manually generate
17559     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17560     * {@link #getDrawingCache()}.</p>
17561     *
17562     * @param enabled true to enable the drawing cache, false otherwise
17563     *
17564     * @see #isDrawingCacheEnabled()
17565     * @see #getDrawingCache()
17566     * @see #buildDrawingCache()
17567     * @see #setLayerType(int, android.graphics.Paint)
17568     */
17569    public void setDrawingCacheEnabled(boolean enabled) {
17570        mCachingFailed = false;
17571        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17572    }
17573
17574    /**
17575     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17576     *
17577     * @return true if the drawing cache is enabled
17578     *
17579     * @see #setDrawingCacheEnabled(boolean)
17580     * @see #getDrawingCache()
17581     */
17582    @ViewDebug.ExportedProperty(category = "drawing")
17583    public boolean isDrawingCacheEnabled() {
17584        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17585    }
17586
17587    /**
17588     * Debugging utility which recursively outputs the dirty state of a view and its
17589     * descendants.
17590     *
17591     * @hide
17592     */
17593    @SuppressWarnings({"UnusedDeclaration"})
17594    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17595        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17596                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17597                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17598                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17599        if (clear) {
17600            mPrivateFlags &= clearMask;
17601        }
17602        if (this instanceof ViewGroup) {
17603            ViewGroup parent = (ViewGroup) this;
17604            final int count = parent.getChildCount();
17605            for (int i = 0; i < count; i++) {
17606                final View child = parent.getChildAt(i);
17607                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17608            }
17609        }
17610    }
17611
17612    /**
17613     * This method is used by ViewGroup to cause its children to restore or recreate their
17614     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17615     * to recreate its own display list, which would happen if it went through the normal
17616     * draw/dispatchDraw mechanisms.
17617     *
17618     * @hide
17619     */
17620    protected void dispatchGetDisplayList() {}
17621
17622    /**
17623     * A view that is not attached or hardware accelerated cannot create a display list.
17624     * This method checks these conditions and returns the appropriate result.
17625     *
17626     * @return true if view has the ability to create a display list, false otherwise.
17627     *
17628     * @hide
17629     */
17630    public boolean canHaveDisplayList() {
17631        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17632    }
17633
17634    /**
17635     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17636     * @hide
17637     */
17638    @NonNull
17639    public RenderNode updateDisplayListIfDirty() {
17640        final RenderNode renderNode = mRenderNode;
17641        if (!canHaveDisplayList()) {
17642            // can't populate RenderNode, don't try
17643            return renderNode;
17644        }
17645
17646        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17647                || !renderNode.isValid()
17648                || (mRecreateDisplayList)) {
17649            // Don't need to recreate the display list, just need to tell our
17650            // children to restore/recreate theirs
17651            if (renderNode.isValid()
17652                    && !mRecreateDisplayList) {
17653                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17654                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17655                dispatchGetDisplayList();
17656
17657                return renderNode; // no work needed
17658            }
17659
17660            // If we got here, we're recreating it. Mark it as such to ensure that
17661            // we copy in child display lists into ours in drawChild()
17662            mRecreateDisplayList = true;
17663
17664            int width = mRight - mLeft;
17665            int height = mBottom - mTop;
17666            int layerType = getLayerType();
17667
17668            final DisplayListCanvas canvas = renderNode.start(width, height);
17669            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17670
17671            try {
17672                if (layerType == LAYER_TYPE_SOFTWARE) {
17673                    buildDrawingCache(true);
17674                    Bitmap cache = getDrawingCache(true);
17675                    if (cache != null) {
17676                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17677                    }
17678                } else {
17679                    computeScroll();
17680
17681                    canvas.translate(-mScrollX, -mScrollY);
17682                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17683                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17684
17685                    // Fast path for layouts with no backgrounds
17686                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17687                        dispatchDraw(canvas);
17688                        drawAutofilledHighlight(canvas);
17689                        if (mOverlay != null && !mOverlay.isEmpty()) {
17690                            mOverlay.getOverlayView().draw(canvas);
17691                        }
17692                        if (debugDraw()) {
17693                            debugDrawFocus(canvas);
17694                        }
17695                    } else {
17696                        draw(canvas);
17697                    }
17698                }
17699            } finally {
17700                renderNode.end(canvas);
17701                setDisplayListProperties(renderNode);
17702            }
17703        } else {
17704            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17705            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17706        }
17707        return renderNode;
17708    }
17709
17710    private void resetDisplayList() {
17711        mRenderNode.discardDisplayList();
17712        if (mBackgroundRenderNode != null) {
17713            mBackgroundRenderNode.discardDisplayList();
17714        }
17715    }
17716
17717    /**
17718     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17719     *
17720     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17721     *
17722     * @see #getDrawingCache(boolean)
17723     */
17724    public Bitmap getDrawingCache() {
17725        return getDrawingCache(false);
17726    }
17727
17728    /**
17729     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17730     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17731     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17732     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17733     * request the drawing cache by calling this method and draw it on screen if the
17734     * returned bitmap is not null.</p>
17735     *
17736     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17737     * this method will create a bitmap of the same size as this view. Because this bitmap
17738     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17739     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17740     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17741     * size than the view. This implies that your application must be able to handle this
17742     * size.</p>
17743     *
17744     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17745     *        the current density of the screen when the application is in compatibility
17746     *        mode.
17747     *
17748     * @return A bitmap representing this view or null if cache is disabled.
17749     *
17750     * @see #setDrawingCacheEnabled(boolean)
17751     * @see #isDrawingCacheEnabled()
17752     * @see #buildDrawingCache(boolean)
17753     * @see #destroyDrawingCache()
17754     */
17755    public Bitmap getDrawingCache(boolean autoScale) {
17756        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17757            return null;
17758        }
17759        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17760            buildDrawingCache(autoScale);
17761        }
17762        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17763    }
17764
17765    /**
17766     * <p>Frees the resources used by the drawing cache. If you call
17767     * {@link #buildDrawingCache()} manually without calling
17768     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17769     * should cleanup the cache with this method afterwards.</p>
17770     *
17771     * @see #setDrawingCacheEnabled(boolean)
17772     * @see #buildDrawingCache()
17773     * @see #getDrawingCache()
17774     */
17775    public void destroyDrawingCache() {
17776        if (mDrawingCache != null) {
17777            mDrawingCache.recycle();
17778            mDrawingCache = null;
17779        }
17780        if (mUnscaledDrawingCache != null) {
17781            mUnscaledDrawingCache.recycle();
17782            mUnscaledDrawingCache = null;
17783        }
17784    }
17785
17786    /**
17787     * Setting a solid background color for the drawing cache's bitmaps will improve
17788     * performance and memory usage. Note, though that this should only be used if this
17789     * view will always be drawn on top of a solid color.
17790     *
17791     * @param color The background color to use for the drawing cache's bitmap
17792     *
17793     * @see #setDrawingCacheEnabled(boolean)
17794     * @see #buildDrawingCache()
17795     * @see #getDrawingCache()
17796     */
17797    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17798        if (color != mDrawingCacheBackgroundColor) {
17799            mDrawingCacheBackgroundColor = color;
17800            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17801        }
17802    }
17803
17804    /**
17805     * @see #setDrawingCacheBackgroundColor(int)
17806     *
17807     * @return The background color to used for the drawing cache's bitmap
17808     */
17809    @ColorInt
17810    public int getDrawingCacheBackgroundColor() {
17811        return mDrawingCacheBackgroundColor;
17812    }
17813
17814    /**
17815     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17816     *
17817     * @see #buildDrawingCache(boolean)
17818     */
17819    public void buildDrawingCache() {
17820        buildDrawingCache(false);
17821    }
17822
17823    /**
17824     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17825     *
17826     * <p>If you call {@link #buildDrawingCache()} manually without calling
17827     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17828     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17829     *
17830     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17831     * this method will create a bitmap of the same size as this view. Because this bitmap
17832     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17833     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17834     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17835     * size than the view. This implies that your application must be able to handle this
17836     * size.</p>
17837     *
17838     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17839     * you do not need the drawing cache bitmap, calling this method will increase memory
17840     * usage and cause the view to be rendered in software once, thus negatively impacting
17841     * performance.</p>
17842     *
17843     * @see #getDrawingCache()
17844     * @see #destroyDrawingCache()
17845     */
17846    public void buildDrawingCache(boolean autoScale) {
17847        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17848                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17849            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17850                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17851                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17852            }
17853            try {
17854                buildDrawingCacheImpl(autoScale);
17855            } finally {
17856                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17857            }
17858        }
17859    }
17860
17861    /**
17862     * private, internal implementation of buildDrawingCache, used to enable tracing
17863     */
17864    private void buildDrawingCacheImpl(boolean autoScale) {
17865        mCachingFailed = false;
17866
17867        int width = mRight - mLeft;
17868        int height = mBottom - mTop;
17869
17870        final AttachInfo attachInfo = mAttachInfo;
17871        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17872
17873        if (autoScale && scalingRequired) {
17874            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17875            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17876        }
17877
17878        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17879        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17880        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17881
17882        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17883        final long drawingCacheSize =
17884                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17885        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17886            if (width > 0 && height > 0) {
17887                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17888                        + " too large to fit into a software layer (or drawing cache), needs "
17889                        + projectedBitmapSize + " bytes, only "
17890                        + drawingCacheSize + " available");
17891            }
17892            destroyDrawingCache();
17893            mCachingFailed = true;
17894            return;
17895        }
17896
17897        boolean clear = true;
17898        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17899
17900        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17901            Bitmap.Config quality;
17902            if (!opaque) {
17903                // Never pick ARGB_4444 because it looks awful
17904                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17905                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17906                    case DRAWING_CACHE_QUALITY_AUTO:
17907                    case DRAWING_CACHE_QUALITY_LOW:
17908                    case DRAWING_CACHE_QUALITY_HIGH:
17909                    default:
17910                        quality = Bitmap.Config.ARGB_8888;
17911                        break;
17912                }
17913            } else {
17914                // Optimization for translucent windows
17915                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17916                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17917            }
17918
17919            // Try to cleanup memory
17920            if (bitmap != null) bitmap.recycle();
17921
17922            try {
17923                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17924                        width, height, quality);
17925                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17926                if (autoScale) {
17927                    mDrawingCache = bitmap;
17928                } else {
17929                    mUnscaledDrawingCache = bitmap;
17930                }
17931                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17932            } catch (OutOfMemoryError e) {
17933                // If there is not enough memory to create the bitmap cache, just
17934                // ignore the issue as bitmap caches are not required to draw the
17935                // view hierarchy
17936                if (autoScale) {
17937                    mDrawingCache = null;
17938                } else {
17939                    mUnscaledDrawingCache = null;
17940                }
17941                mCachingFailed = true;
17942                return;
17943            }
17944
17945            clear = drawingCacheBackgroundColor != 0;
17946        }
17947
17948        Canvas canvas;
17949        if (attachInfo != null) {
17950            canvas = attachInfo.mCanvas;
17951            if (canvas == null) {
17952                canvas = new Canvas();
17953            }
17954            canvas.setBitmap(bitmap);
17955            // Temporarily clobber the cached Canvas in case one of our children
17956            // is also using a drawing cache. Without this, the children would
17957            // steal the canvas by attaching their own bitmap to it and bad, bad
17958            // thing would happen (invisible views, corrupted drawings, etc.)
17959            attachInfo.mCanvas = null;
17960        } else {
17961            // This case should hopefully never or seldom happen
17962            canvas = new Canvas(bitmap);
17963        }
17964
17965        if (clear) {
17966            bitmap.eraseColor(drawingCacheBackgroundColor);
17967        }
17968
17969        computeScroll();
17970        final int restoreCount = canvas.save();
17971
17972        if (autoScale && scalingRequired) {
17973            final float scale = attachInfo.mApplicationScale;
17974            canvas.scale(scale, scale);
17975        }
17976
17977        canvas.translate(-mScrollX, -mScrollY);
17978
17979        mPrivateFlags |= PFLAG_DRAWN;
17980        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17981                mLayerType != LAYER_TYPE_NONE) {
17982            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17983        }
17984
17985        // Fast path for layouts with no backgrounds
17986        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17987            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17988            dispatchDraw(canvas);
17989            drawAutofilledHighlight(canvas);
17990            if (mOverlay != null && !mOverlay.isEmpty()) {
17991                mOverlay.getOverlayView().draw(canvas);
17992            }
17993        } else {
17994            draw(canvas);
17995        }
17996
17997        canvas.restoreToCount(restoreCount);
17998        canvas.setBitmap(null);
17999
18000        if (attachInfo != null) {
18001            // Restore the cached Canvas for our siblings
18002            attachInfo.mCanvas = canvas;
18003        }
18004    }
18005
18006    /**
18007     * Create a snapshot of the view into a bitmap.  We should probably make
18008     * some form of this public, but should think about the API.
18009     *
18010     * @hide
18011     */
18012    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18013        int width = mRight - mLeft;
18014        int height = mBottom - mTop;
18015
18016        final AttachInfo attachInfo = mAttachInfo;
18017        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18018        width = (int) ((width * scale) + 0.5f);
18019        height = (int) ((height * scale) + 0.5f);
18020
18021        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18022                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18023        if (bitmap == null) {
18024            throw new OutOfMemoryError();
18025        }
18026
18027        Resources resources = getResources();
18028        if (resources != null) {
18029            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18030        }
18031
18032        Canvas canvas;
18033        if (attachInfo != null) {
18034            canvas = attachInfo.mCanvas;
18035            if (canvas == null) {
18036                canvas = new Canvas();
18037            }
18038            canvas.setBitmap(bitmap);
18039            // Temporarily clobber the cached Canvas in case one of our children
18040            // is also using a drawing cache. Without this, the children would
18041            // steal the canvas by attaching their own bitmap to it and bad, bad
18042            // things would happen (invisible views, corrupted drawings, etc.)
18043            attachInfo.mCanvas = null;
18044        } else {
18045            // This case should hopefully never or seldom happen
18046            canvas = new Canvas(bitmap);
18047        }
18048        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18049        canvas.setHwBitmapsInSwModeEnabled(true);
18050        if ((backgroundColor & 0xff000000) != 0) {
18051            bitmap.eraseColor(backgroundColor);
18052        }
18053
18054        computeScroll();
18055        final int restoreCount = canvas.save();
18056        canvas.scale(scale, scale);
18057        canvas.translate(-mScrollX, -mScrollY);
18058
18059        // Temporarily remove the dirty mask
18060        int flags = mPrivateFlags;
18061        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18062
18063        // Fast path for layouts with no backgrounds
18064        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18065            dispatchDraw(canvas);
18066            drawAutofilledHighlight(canvas);
18067            if (mOverlay != null && !mOverlay.isEmpty()) {
18068                mOverlay.getOverlayView().draw(canvas);
18069            }
18070        } else {
18071            draw(canvas);
18072        }
18073
18074        mPrivateFlags = flags;
18075
18076        canvas.restoreToCount(restoreCount);
18077        canvas.setBitmap(null);
18078        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18079
18080        if (attachInfo != null) {
18081            // Restore the cached Canvas for our siblings
18082            attachInfo.mCanvas = canvas;
18083        }
18084
18085        return bitmap;
18086    }
18087
18088    /**
18089     * Indicates whether this View is currently in edit mode. A View is usually
18090     * in edit mode when displayed within a developer tool. For instance, if
18091     * this View is being drawn by a visual user interface builder, this method
18092     * should return true.
18093     *
18094     * Subclasses should check the return value of this method to provide
18095     * different behaviors if their normal behavior might interfere with the
18096     * host environment. For instance: the class spawns a thread in its
18097     * constructor, the drawing code relies on device-specific features, etc.
18098     *
18099     * This method is usually checked in the drawing code of custom widgets.
18100     *
18101     * @return True if this View is in edit mode, false otherwise.
18102     */
18103    public boolean isInEditMode() {
18104        return false;
18105    }
18106
18107    /**
18108     * If the View draws content inside its padding and enables fading edges,
18109     * it needs to support padding offsets. Padding offsets are added to the
18110     * fading edges to extend the length of the fade so that it covers pixels
18111     * drawn inside the padding.
18112     *
18113     * Subclasses of this class should override this method if they need
18114     * to draw content inside the padding.
18115     *
18116     * @return True if padding offset must be applied, false otherwise.
18117     *
18118     * @see #getLeftPaddingOffset()
18119     * @see #getRightPaddingOffset()
18120     * @see #getTopPaddingOffset()
18121     * @see #getBottomPaddingOffset()
18122     *
18123     * @since CURRENT
18124     */
18125    protected boolean isPaddingOffsetRequired() {
18126        return false;
18127    }
18128
18129    /**
18130     * Amount by which to extend the left fading region. Called only when
18131     * {@link #isPaddingOffsetRequired()} returns true.
18132     *
18133     * @return The left padding offset in pixels.
18134     *
18135     * @see #isPaddingOffsetRequired()
18136     *
18137     * @since CURRENT
18138     */
18139    protected int getLeftPaddingOffset() {
18140        return 0;
18141    }
18142
18143    /**
18144     * Amount by which to extend the right fading region. Called only when
18145     * {@link #isPaddingOffsetRequired()} returns true.
18146     *
18147     * @return The right padding offset in pixels.
18148     *
18149     * @see #isPaddingOffsetRequired()
18150     *
18151     * @since CURRENT
18152     */
18153    protected int getRightPaddingOffset() {
18154        return 0;
18155    }
18156
18157    /**
18158     * Amount by which to extend the top fading region. Called only when
18159     * {@link #isPaddingOffsetRequired()} returns true.
18160     *
18161     * @return The top padding offset in pixels.
18162     *
18163     * @see #isPaddingOffsetRequired()
18164     *
18165     * @since CURRENT
18166     */
18167    protected int getTopPaddingOffset() {
18168        return 0;
18169    }
18170
18171    /**
18172     * Amount by which to extend the bottom fading region. Called only when
18173     * {@link #isPaddingOffsetRequired()} returns true.
18174     *
18175     * @return The bottom padding offset in pixels.
18176     *
18177     * @see #isPaddingOffsetRequired()
18178     *
18179     * @since CURRENT
18180     */
18181    protected int getBottomPaddingOffset() {
18182        return 0;
18183    }
18184
18185    /**
18186     * @hide
18187     * @param offsetRequired
18188     */
18189    protected int getFadeTop(boolean offsetRequired) {
18190        int top = mPaddingTop;
18191        if (offsetRequired) top += getTopPaddingOffset();
18192        return top;
18193    }
18194
18195    /**
18196     * @hide
18197     * @param offsetRequired
18198     */
18199    protected int getFadeHeight(boolean offsetRequired) {
18200        int padding = mPaddingTop;
18201        if (offsetRequired) padding += getTopPaddingOffset();
18202        return mBottom - mTop - mPaddingBottom - padding;
18203    }
18204
18205    /**
18206     * <p>Indicates whether this view is attached to a hardware accelerated
18207     * window or not.</p>
18208     *
18209     * <p>Even if this method returns true, it does not mean that every call
18210     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18211     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18212     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18213     * window is hardware accelerated,
18214     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18215     * return false, and this method will return true.</p>
18216     *
18217     * @return True if the view is attached to a window and the window is
18218     *         hardware accelerated; false in any other case.
18219     */
18220    @ViewDebug.ExportedProperty(category = "drawing")
18221    public boolean isHardwareAccelerated() {
18222        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18223    }
18224
18225    /**
18226     * Sets a rectangular area on this view to which the view will be clipped
18227     * when it is drawn. Setting the value to null will remove the clip bounds
18228     * and the view will draw normally, using its full bounds.
18229     *
18230     * @param clipBounds The rectangular area, in the local coordinates of
18231     * this view, to which future drawing operations will be clipped.
18232     */
18233    public void setClipBounds(Rect clipBounds) {
18234        if (clipBounds == mClipBounds
18235                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18236            return;
18237        }
18238        if (clipBounds != null) {
18239            if (mClipBounds == null) {
18240                mClipBounds = new Rect(clipBounds);
18241            } else {
18242                mClipBounds.set(clipBounds);
18243            }
18244        } else {
18245            mClipBounds = null;
18246        }
18247        mRenderNode.setClipBounds(mClipBounds);
18248        invalidateViewProperty(false, false);
18249    }
18250
18251    /**
18252     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18253     *
18254     * @return A copy of the current clip bounds if clip bounds are set,
18255     * otherwise null.
18256     */
18257    public Rect getClipBounds() {
18258        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18259    }
18260
18261
18262    /**
18263     * Populates an output rectangle with the clip bounds of the view,
18264     * returning {@code true} if successful or {@code false} if the view's
18265     * clip bounds are {@code null}.
18266     *
18267     * @param outRect rectangle in which to place the clip bounds of the view
18268     * @return {@code true} if successful or {@code false} if the view's
18269     *         clip bounds are {@code null}
18270     */
18271    public boolean getClipBounds(Rect outRect) {
18272        if (mClipBounds != null) {
18273            outRect.set(mClipBounds);
18274            return true;
18275        }
18276        return false;
18277    }
18278
18279    /**
18280     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18281     * case of an active Animation being run on the view.
18282     */
18283    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18284            Animation a, boolean scalingRequired) {
18285        Transformation invalidationTransform;
18286        final int flags = parent.mGroupFlags;
18287        final boolean initialized = a.isInitialized();
18288        if (!initialized) {
18289            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18290            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18291            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18292            onAnimationStart();
18293        }
18294
18295        final Transformation t = parent.getChildTransformation();
18296        boolean more = a.getTransformation(drawingTime, t, 1f);
18297        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18298            if (parent.mInvalidationTransformation == null) {
18299                parent.mInvalidationTransformation = new Transformation();
18300            }
18301            invalidationTransform = parent.mInvalidationTransformation;
18302            a.getTransformation(drawingTime, invalidationTransform, 1f);
18303        } else {
18304            invalidationTransform = t;
18305        }
18306
18307        if (more) {
18308            if (!a.willChangeBounds()) {
18309                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18310                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18311                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18312                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18313                    // The child need to draw an animation, potentially offscreen, so
18314                    // make sure we do not cancel invalidate requests
18315                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18316                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18317                }
18318            } else {
18319                if (parent.mInvalidateRegion == null) {
18320                    parent.mInvalidateRegion = new RectF();
18321                }
18322                final RectF region = parent.mInvalidateRegion;
18323                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18324                        invalidationTransform);
18325
18326                // The child need to draw an animation, potentially offscreen, so
18327                // make sure we do not cancel invalidate requests
18328                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18329
18330                final int left = mLeft + (int) region.left;
18331                final int top = mTop + (int) region.top;
18332                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18333                        top + (int) (region.height() + .5f));
18334            }
18335        }
18336        return more;
18337    }
18338
18339    /**
18340     * This method is called by getDisplayList() when a display list is recorded for a View.
18341     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18342     */
18343    void setDisplayListProperties(RenderNode renderNode) {
18344        if (renderNode != null) {
18345            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18346            renderNode.setClipToBounds(mParent instanceof ViewGroup
18347                    && ((ViewGroup) mParent).getClipChildren());
18348
18349            float alpha = 1;
18350            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18351                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18352                ViewGroup parentVG = (ViewGroup) mParent;
18353                final Transformation t = parentVG.getChildTransformation();
18354                if (parentVG.getChildStaticTransformation(this, t)) {
18355                    final int transformType = t.getTransformationType();
18356                    if (transformType != Transformation.TYPE_IDENTITY) {
18357                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18358                            alpha = t.getAlpha();
18359                        }
18360                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18361                            renderNode.setStaticMatrix(t.getMatrix());
18362                        }
18363                    }
18364                }
18365            }
18366            if (mTransformationInfo != null) {
18367                alpha *= getFinalAlpha();
18368                if (alpha < 1) {
18369                    final int multipliedAlpha = (int) (255 * alpha);
18370                    if (onSetAlpha(multipliedAlpha)) {
18371                        alpha = 1;
18372                    }
18373                }
18374                renderNode.setAlpha(alpha);
18375            } else if (alpha < 1) {
18376                renderNode.setAlpha(alpha);
18377            }
18378        }
18379    }
18380
18381    /**
18382     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18383     *
18384     * This is where the View specializes rendering behavior based on layer type,
18385     * and hardware acceleration.
18386     */
18387    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18388        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18389        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18390         *
18391         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18392         * HW accelerated, it can't handle drawing RenderNodes.
18393         */
18394        boolean drawingWithRenderNode = mAttachInfo != null
18395                && mAttachInfo.mHardwareAccelerated
18396                && hardwareAcceleratedCanvas;
18397
18398        boolean more = false;
18399        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18400        final int parentFlags = parent.mGroupFlags;
18401
18402        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18403            parent.getChildTransformation().clear();
18404            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18405        }
18406
18407        Transformation transformToApply = null;
18408        boolean concatMatrix = false;
18409        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18410        final Animation a = getAnimation();
18411        if (a != null) {
18412            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18413            concatMatrix = a.willChangeTransformationMatrix();
18414            if (concatMatrix) {
18415                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18416            }
18417            transformToApply = parent.getChildTransformation();
18418        } else {
18419            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18420                // No longer animating: clear out old animation matrix
18421                mRenderNode.setAnimationMatrix(null);
18422                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18423            }
18424            if (!drawingWithRenderNode
18425                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18426                final Transformation t = parent.getChildTransformation();
18427                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18428                if (hasTransform) {
18429                    final int transformType = t.getTransformationType();
18430                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18431                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18432                }
18433            }
18434        }
18435
18436        concatMatrix |= !childHasIdentityMatrix;
18437
18438        // Sets the flag as early as possible to allow draw() implementations
18439        // to call invalidate() successfully when doing animations
18440        mPrivateFlags |= PFLAG_DRAWN;
18441
18442        if (!concatMatrix &&
18443                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18444                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18445                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18446                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18447            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18448            return more;
18449        }
18450        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18451
18452        if (hardwareAcceleratedCanvas) {
18453            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18454            // retain the flag's value temporarily in the mRecreateDisplayList flag
18455            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18456            mPrivateFlags &= ~PFLAG_INVALIDATED;
18457        }
18458
18459        RenderNode renderNode = null;
18460        Bitmap cache = null;
18461        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18462        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18463             if (layerType != LAYER_TYPE_NONE) {
18464                 // If not drawing with RenderNode, treat HW layers as SW
18465                 layerType = LAYER_TYPE_SOFTWARE;
18466                 buildDrawingCache(true);
18467            }
18468            cache = getDrawingCache(true);
18469        }
18470
18471        if (drawingWithRenderNode) {
18472            // Delay getting the display list until animation-driven alpha values are
18473            // set up and possibly passed on to the view
18474            renderNode = updateDisplayListIfDirty();
18475            if (!renderNode.isValid()) {
18476                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18477                // to getDisplayList(), the display list will be marked invalid and we should not
18478                // try to use it again.
18479                renderNode = null;
18480                drawingWithRenderNode = false;
18481            }
18482        }
18483
18484        int sx = 0;
18485        int sy = 0;
18486        if (!drawingWithRenderNode) {
18487            computeScroll();
18488            sx = mScrollX;
18489            sy = mScrollY;
18490        }
18491
18492        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18493        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18494
18495        int restoreTo = -1;
18496        if (!drawingWithRenderNode || transformToApply != null) {
18497            restoreTo = canvas.save();
18498        }
18499        if (offsetForScroll) {
18500            canvas.translate(mLeft - sx, mTop - sy);
18501        } else {
18502            if (!drawingWithRenderNode) {
18503                canvas.translate(mLeft, mTop);
18504            }
18505            if (scalingRequired) {
18506                if (drawingWithRenderNode) {
18507                    // TODO: Might not need this if we put everything inside the DL
18508                    restoreTo = canvas.save();
18509                }
18510                // mAttachInfo cannot be null, otherwise scalingRequired == false
18511                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18512                canvas.scale(scale, scale);
18513            }
18514        }
18515
18516        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18517        if (transformToApply != null
18518                || alpha < 1
18519                || !hasIdentityMatrix()
18520                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18521            if (transformToApply != null || !childHasIdentityMatrix) {
18522                int transX = 0;
18523                int transY = 0;
18524
18525                if (offsetForScroll) {
18526                    transX = -sx;
18527                    transY = -sy;
18528                }
18529
18530                if (transformToApply != null) {
18531                    if (concatMatrix) {
18532                        if (drawingWithRenderNode) {
18533                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18534                        } else {
18535                            // Undo the scroll translation, apply the transformation matrix,
18536                            // then redo the scroll translate to get the correct result.
18537                            canvas.translate(-transX, -transY);
18538                            canvas.concat(transformToApply.getMatrix());
18539                            canvas.translate(transX, transY);
18540                        }
18541                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18542                    }
18543
18544                    float transformAlpha = transformToApply.getAlpha();
18545                    if (transformAlpha < 1) {
18546                        alpha *= transformAlpha;
18547                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18548                    }
18549                }
18550
18551                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18552                    canvas.translate(-transX, -transY);
18553                    canvas.concat(getMatrix());
18554                    canvas.translate(transX, transY);
18555                }
18556            }
18557
18558            // Deal with alpha if it is or used to be <1
18559            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18560                if (alpha < 1) {
18561                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18562                } else {
18563                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18564                }
18565                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18566                if (!drawingWithDrawingCache) {
18567                    final int multipliedAlpha = (int) (255 * alpha);
18568                    if (!onSetAlpha(multipliedAlpha)) {
18569                        if (drawingWithRenderNode) {
18570                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18571                        } else if (layerType == LAYER_TYPE_NONE) {
18572                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18573                                    multipliedAlpha);
18574                        }
18575                    } else {
18576                        // Alpha is handled by the child directly, clobber the layer's alpha
18577                        mPrivateFlags |= PFLAG_ALPHA_SET;
18578                    }
18579                }
18580            }
18581        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18582            onSetAlpha(255);
18583            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18584        }
18585
18586        if (!drawingWithRenderNode) {
18587            // apply clips directly, since RenderNode won't do it for this draw
18588            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18589                if (offsetForScroll) {
18590                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18591                } else {
18592                    if (!scalingRequired || cache == null) {
18593                        canvas.clipRect(0, 0, getWidth(), getHeight());
18594                    } else {
18595                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18596                    }
18597                }
18598            }
18599
18600            if (mClipBounds != null) {
18601                // clip bounds ignore scroll
18602                canvas.clipRect(mClipBounds);
18603            }
18604        }
18605
18606        if (!drawingWithDrawingCache) {
18607            if (drawingWithRenderNode) {
18608                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18609                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18610            } else {
18611                // Fast path for layouts with no backgrounds
18612                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18613                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18614                    dispatchDraw(canvas);
18615                } else {
18616                    draw(canvas);
18617                }
18618            }
18619        } else if (cache != null) {
18620            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18621            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18622                // no layer paint, use temporary paint to draw bitmap
18623                Paint cachePaint = parent.mCachePaint;
18624                if (cachePaint == null) {
18625                    cachePaint = new Paint();
18626                    cachePaint.setDither(false);
18627                    parent.mCachePaint = cachePaint;
18628                }
18629                cachePaint.setAlpha((int) (alpha * 255));
18630                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18631            } else {
18632                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18633                int layerPaintAlpha = mLayerPaint.getAlpha();
18634                if (alpha < 1) {
18635                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18636                }
18637                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18638                if (alpha < 1) {
18639                    mLayerPaint.setAlpha(layerPaintAlpha);
18640                }
18641            }
18642        }
18643
18644        if (restoreTo >= 0) {
18645            canvas.restoreToCount(restoreTo);
18646        }
18647
18648        if (a != null && !more) {
18649            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18650                onSetAlpha(255);
18651            }
18652            parent.finishAnimatingView(this, a);
18653        }
18654
18655        if (more && hardwareAcceleratedCanvas) {
18656            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18657                // alpha animations should cause the child to recreate its display list
18658                invalidate(true);
18659            }
18660        }
18661
18662        mRecreateDisplayList = false;
18663
18664        return more;
18665    }
18666
18667    static Paint getDebugPaint() {
18668        if (sDebugPaint == null) {
18669            sDebugPaint = new Paint();
18670            sDebugPaint.setAntiAlias(false);
18671        }
18672        return sDebugPaint;
18673    }
18674
18675    final int dipsToPixels(int dips) {
18676        float scale = getContext().getResources().getDisplayMetrics().density;
18677        return (int) (dips * scale + 0.5f);
18678    }
18679
18680    final private void debugDrawFocus(Canvas canvas) {
18681        if (isFocused()) {
18682            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18683            final int l = mScrollX;
18684            final int r = l + mRight - mLeft;
18685            final int t = mScrollY;
18686            final int b = t + mBottom - mTop;
18687
18688            final Paint paint = getDebugPaint();
18689            paint.setColor(DEBUG_CORNERS_COLOR);
18690
18691            // Draw squares in corners.
18692            paint.setStyle(Paint.Style.FILL);
18693            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18694            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18695            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18696            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18697
18698            // Draw big X across the view.
18699            paint.setStyle(Paint.Style.STROKE);
18700            canvas.drawLine(l, t, r, b, paint);
18701            canvas.drawLine(l, b, r, t, paint);
18702        }
18703    }
18704
18705    /**
18706     * Manually render this view (and all of its children) to the given Canvas.
18707     * The view must have already done a full layout before this function is
18708     * called.  When implementing a view, implement
18709     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18710     * If you do need to override this method, call the superclass version.
18711     *
18712     * @param canvas The Canvas to which the View is rendered.
18713     */
18714    @CallSuper
18715    public void draw(Canvas canvas) {
18716        final int privateFlags = mPrivateFlags;
18717        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18718                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18719        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18720
18721        /*
18722         * Draw traversal performs several drawing steps which must be executed
18723         * in the appropriate order:
18724         *
18725         *      1. Draw the background
18726         *      2. If necessary, save the canvas' layers to prepare for fading
18727         *      3. Draw view's content
18728         *      4. Draw children
18729         *      5. If necessary, draw the fading edges and restore layers
18730         *      6. Draw decorations (scrollbars for instance)
18731         */
18732
18733        // Step 1, draw the background, if needed
18734        int saveCount;
18735
18736        if (!dirtyOpaque) {
18737            drawBackground(canvas);
18738        }
18739
18740        // skip step 2 & 5 if possible (common case)
18741        final int viewFlags = mViewFlags;
18742        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18743        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18744        if (!verticalEdges && !horizontalEdges) {
18745            // Step 3, draw the content
18746            if (!dirtyOpaque) onDraw(canvas);
18747
18748            // Step 4, draw the children
18749            dispatchDraw(canvas);
18750
18751            drawAutofilledHighlight(canvas);
18752
18753            // Overlay is part of the content and draws beneath Foreground
18754            if (mOverlay != null && !mOverlay.isEmpty()) {
18755                mOverlay.getOverlayView().dispatchDraw(canvas);
18756            }
18757
18758            // Step 6, draw decorations (foreground, scrollbars)
18759            onDrawForeground(canvas);
18760
18761            if (debugDraw()) {
18762                debugDrawFocus(canvas);
18763            }
18764
18765            // we're done...
18766            return;
18767        }
18768
18769        /*
18770         * Here we do the full fledged routine...
18771         * (this is an uncommon case where speed matters less,
18772         * this is why we repeat some of the tests that have been
18773         * done above)
18774         */
18775
18776        boolean drawTop = false;
18777        boolean drawBottom = false;
18778        boolean drawLeft = false;
18779        boolean drawRight = false;
18780
18781        float topFadeStrength = 0.0f;
18782        float bottomFadeStrength = 0.0f;
18783        float leftFadeStrength = 0.0f;
18784        float rightFadeStrength = 0.0f;
18785
18786        // Step 2, save the canvas' layers
18787        int paddingLeft = mPaddingLeft;
18788
18789        final boolean offsetRequired = isPaddingOffsetRequired();
18790        if (offsetRequired) {
18791            paddingLeft += getLeftPaddingOffset();
18792        }
18793
18794        int left = mScrollX + paddingLeft;
18795        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18796        int top = mScrollY + getFadeTop(offsetRequired);
18797        int bottom = top + getFadeHeight(offsetRequired);
18798
18799        if (offsetRequired) {
18800            right += getRightPaddingOffset();
18801            bottom += getBottomPaddingOffset();
18802        }
18803
18804        final ScrollabilityCache scrollabilityCache = mScrollCache;
18805        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18806        int length = (int) fadeHeight;
18807
18808        // clip the fade length if top and bottom fades overlap
18809        // overlapping fades produce odd-looking artifacts
18810        if (verticalEdges && (top + length > bottom - length)) {
18811            length = (bottom - top) / 2;
18812        }
18813
18814        // also clip horizontal fades if necessary
18815        if (horizontalEdges && (left + length > right - length)) {
18816            length = (right - left) / 2;
18817        }
18818
18819        if (verticalEdges) {
18820            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18821            drawTop = topFadeStrength * fadeHeight > 1.0f;
18822            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18823            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18824        }
18825
18826        if (horizontalEdges) {
18827            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18828            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18829            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18830            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18831        }
18832
18833        saveCount = canvas.getSaveCount();
18834
18835        int solidColor = getSolidColor();
18836        if (solidColor == 0) {
18837            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18838
18839            if (drawTop) {
18840                canvas.saveLayer(left, top, right, top + length, null, flags);
18841            }
18842
18843            if (drawBottom) {
18844                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18845            }
18846
18847            if (drawLeft) {
18848                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18849            }
18850
18851            if (drawRight) {
18852                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18853            }
18854        } else {
18855            scrollabilityCache.setFadeColor(solidColor);
18856        }
18857
18858        // Step 3, draw the content
18859        if (!dirtyOpaque) onDraw(canvas);
18860
18861        // Step 4, draw the children
18862        dispatchDraw(canvas);
18863
18864        // Step 5, draw the fade effect and restore layers
18865        final Paint p = scrollabilityCache.paint;
18866        final Matrix matrix = scrollabilityCache.matrix;
18867        final Shader fade = scrollabilityCache.shader;
18868
18869        if (drawTop) {
18870            matrix.setScale(1, fadeHeight * topFadeStrength);
18871            matrix.postTranslate(left, top);
18872            fade.setLocalMatrix(matrix);
18873            p.setShader(fade);
18874            canvas.drawRect(left, top, right, top + length, p);
18875        }
18876
18877        if (drawBottom) {
18878            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18879            matrix.postRotate(180);
18880            matrix.postTranslate(left, bottom);
18881            fade.setLocalMatrix(matrix);
18882            p.setShader(fade);
18883            canvas.drawRect(left, bottom - length, right, bottom, p);
18884        }
18885
18886        if (drawLeft) {
18887            matrix.setScale(1, fadeHeight * leftFadeStrength);
18888            matrix.postRotate(-90);
18889            matrix.postTranslate(left, top);
18890            fade.setLocalMatrix(matrix);
18891            p.setShader(fade);
18892            canvas.drawRect(left, top, left + length, bottom, p);
18893        }
18894
18895        if (drawRight) {
18896            matrix.setScale(1, fadeHeight * rightFadeStrength);
18897            matrix.postRotate(90);
18898            matrix.postTranslate(right, top);
18899            fade.setLocalMatrix(matrix);
18900            p.setShader(fade);
18901            canvas.drawRect(right - length, top, right, bottom, p);
18902        }
18903
18904        canvas.restoreToCount(saveCount);
18905
18906        drawAutofilledHighlight(canvas);
18907
18908        // Overlay is part of the content and draws beneath Foreground
18909        if (mOverlay != null && !mOverlay.isEmpty()) {
18910            mOverlay.getOverlayView().dispatchDraw(canvas);
18911        }
18912
18913        // Step 6, draw decorations (foreground, scrollbars)
18914        onDrawForeground(canvas);
18915
18916        if (debugDraw()) {
18917            debugDrawFocus(canvas);
18918        }
18919    }
18920
18921    /**
18922     * Draws the background onto the specified canvas.
18923     *
18924     * @param canvas Canvas on which to draw the background
18925     */
18926    private void drawBackground(Canvas canvas) {
18927        final Drawable background = mBackground;
18928        if (background == null) {
18929            return;
18930        }
18931
18932        setBackgroundBounds();
18933
18934        // Attempt to use a display list if requested.
18935        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18936                && mAttachInfo.mThreadedRenderer != null) {
18937            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18938
18939            final RenderNode renderNode = mBackgroundRenderNode;
18940            if (renderNode != null && renderNode.isValid()) {
18941                setBackgroundRenderNodeProperties(renderNode);
18942                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18943                return;
18944            }
18945        }
18946
18947        final int scrollX = mScrollX;
18948        final int scrollY = mScrollY;
18949        if ((scrollX | scrollY) == 0) {
18950            background.draw(canvas);
18951        } else {
18952            canvas.translate(scrollX, scrollY);
18953            background.draw(canvas);
18954            canvas.translate(-scrollX, -scrollY);
18955        }
18956    }
18957
18958    /**
18959     * Sets the correct background bounds and rebuilds the outline, if needed.
18960     * <p/>
18961     * This is called by LayoutLib.
18962     */
18963    void setBackgroundBounds() {
18964        if (mBackgroundSizeChanged && mBackground != null) {
18965            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18966            mBackgroundSizeChanged = false;
18967            rebuildOutline();
18968        }
18969    }
18970
18971    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18972        renderNode.setTranslationX(mScrollX);
18973        renderNode.setTranslationY(mScrollY);
18974    }
18975
18976    /**
18977     * Creates a new display list or updates the existing display list for the
18978     * specified Drawable.
18979     *
18980     * @param drawable Drawable for which to create a display list
18981     * @param renderNode Existing RenderNode, or {@code null}
18982     * @return A valid display list for the specified drawable
18983     */
18984    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18985        if (renderNode == null) {
18986            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18987        }
18988
18989        final Rect bounds = drawable.getBounds();
18990        final int width = bounds.width();
18991        final int height = bounds.height();
18992        final DisplayListCanvas canvas = renderNode.start(width, height);
18993
18994        // Reverse left/top translation done by drawable canvas, which will
18995        // instead be applied by rendernode's LTRB bounds below. This way, the
18996        // drawable's bounds match with its rendernode bounds and its content
18997        // will lie within those bounds in the rendernode tree.
18998        canvas.translate(-bounds.left, -bounds.top);
18999
19000        try {
19001            drawable.draw(canvas);
19002        } finally {
19003            renderNode.end(canvas);
19004        }
19005
19006        // Set up drawable properties that are view-independent.
19007        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19008        renderNode.setProjectBackwards(drawable.isProjected());
19009        renderNode.setProjectionReceiver(true);
19010        renderNode.setClipToBounds(false);
19011        return renderNode;
19012    }
19013
19014    /**
19015     * Returns the overlay for this view, creating it if it does not yet exist.
19016     * Adding drawables to the overlay will cause them to be displayed whenever
19017     * the view itself is redrawn. Objects in the overlay should be actively
19018     * managed: remove them when they should not be displayed anymore. The
19019     * overlay will always have the same size as its host view.
19020     *
19021     * <p>Note: Overlays do not currently work correctly with {@link
19022     * SurfaceView} or {@link TextureView}; contents in overlays for these
19023     * types of views may not display correctly.</p>
19024     *
19025     * @return The ViewOverlay object for this view.
19026     * @see ViewOverlay
19027     */
19028    public ViewOverlay getOverlay() {
19029        if (mOverlay == null) {
19030            mOverlay = new ViewOverlay(mContext, this);
19031        }
19032        return mOverlay;
19033    }
19034
19035    /**
19036     * Override this if your view is known to always be drawn on top of a solid color background,
19037     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19038     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19039     * should be set to 0xFF.
19040     *
19041     * @see #setVerticalFadingEdgeEnabled(boolean)
19042     * @see #setHorizontalFadingEdgeEnabled(boolean)
19043     *
19044     * @return The known solid color background for this view, or 0 if the color may vary
19045     */
19046    @ViewDebug.ExportedProperty(category = "drawing")
19047    @ColorInt
19048    public int getSolidColor() {
19049        return 0;
19050    }
19051
19052    /**
19053     * Build a human readable string representation of the specified view flags.
19054     *
19055     * @param flags the view flags to convert to a string
19056     * @return a String representing the supplied flags
19057     */
19058    private static String printFlags(int flags) {
19059        String output = "";
19060        int numFlags = 0;
19061        if ((flags & FOCUSABLE) == FOCUSABLE) {
19062            output += "TAKES_FOCUS";
19063            numFlags++;
19064        }
19065
19066        switch (flags & VISIBILITY_MASK) {
19067        case INVISIBLE:
19068            if (numFlags > 0) {
19069                output += " ";
19070            }
19071            output += "INVISIBLE";
19072            // USELESS HERE numFlags++;
19073            break;
19074        case GONE:
19075            if (numFlags > 0) {
19076                output += " ";
19077            }
19078            output += "GONE";
19079            // USELESS HERE numFlags++;
19080            break;
19081        default:
19082            break;
19083        }
19084        return output;
19085    }
19086
19087    /**
19088     * Build a human readable string representation of the specified private
19089     * view flags.
19090     *
19091     * @param privateFlags the private view flags to convert to a string
19092     * @return a String representing the supplied flags
19093     */
19094    private static String printPrivateFlags(int privateFlags) {
19095        String output = "";
19096        int numFlags = 0;
19097
19098        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19099            output += "WANTS_FOCUS";
19100            numFlags++;
19101        }
19102
19103        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19104            if (numFlags > 0) {
19105                output += " ";
19106            }
19107            output += "FOCUSED";
19108            numFlags++;
19109        }
19110
19111        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19112            if (numFlags > 0) {
19113                output += " ";
19114            }
19115            output += "SELECTED";
19116            numFlags++;
19117        }
19118
19119        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19120            if (numFlags > 0) {
19121                output += " ";
19122            }
19123            output += "IS_ROOT_NAMESPACE";
19124            numFlags++;
19125        }
19126
19127        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19128            if (numFlags > 0) {
19129                output += " ";
19130            }
19131            output += "HAS_BOUNDS";
19132            numFlags++;
19133        }
19134
19135        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19136            if (numFlags > 0) {
19137                output += " ";
19138            }
19139            output += "DRAWN";
19140            // USELESS HERE numFlags++;
19141        }
19142        return output;
19143    }
19144
19145    /**
19146     * <p>Indicates whether or not this view's layout will be requested during
19147     * the next hierarchy layout pass.</p>
19148     *
19149     * @return true if the layout will be forced during next layout pass
19150     */
19151    public boolean isLayoutRequested() {
19152        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19153    }
19154
19155    /**
19156     * Return true if o is a ViewGroup that is laying out using optical bounds.
19157     * @hide
19158     */
19159    public static boolean isLayoutModeOptical(Object o) {
19160        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19161    }
19162
19163    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19164        Insets parentInsets = mParent instanceof View ?
19165                ((View) mParent).getOpticalInsets() : Insets.NONE;
19166        Insets childInsets = getOpticalInsets();
19167        return setFrame(
19168                left   + parentInsets.left - childInsets.left,
19169                top    + parentInsets.top  - childInsets.top,
19170                right  + parentInsets.left + childInsets.right,
19171                bottom + parentInsets.top  + childInsets.bottom);
19172    }
19173
19174    /**
19175     * Assign a size and position to a view and all of its
19176     * descendants
19177     *
19178     * <p>This is the second phase of the layout mechanism.
19179     * (The first is measuring). In this phase, each parent calls
19180     * layout on all of its children to position them.
19181     * This is typically done using the child measurements
19182     * that were stored in the measure pass().</p>
19183     *
19184     * <p>Derived classes should not override this method.
19185     * Derived classes with children should override
19186     * onLayout. In that method, they should
19187     * call layout on each of their children.</p>
19188     *
19189     * @param l Left position, relative to parent
19190     * @param t Top position, relative to parent
19191     * @param r Right position, relative to parent
19192     * @param b Bottom position, relative to parent
19193     */
19194    @SuppressWarnings({"unchecked"})
19195    public void layout(int l, int t, int r, int b) {
19196        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19197            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19198            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19199        }
19200
19201        int oldL = mLeft;
19202        int oldT = mTop;
19203        int oldB = mBottom;
19204        int oldR = mRight;
19205
19206        boolean changed = isLayoutModeOptical(mParent) ?
19207                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19208
19209        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19210            onLayout(changed, l, t, r, b);
19211
19212            if (shouldDrawRoundScrollbar()) {
19213                if(mRoundScrollbarRenderer == null) {
19214                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19215                }
19216            } else {
19217                mRoundScrollbarRenderer = null;
19218            }
19219
19220            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19221
19222            ListenerInfo li = mListenerInfo;
19223            if (li != null && li.mOnLayoutChangeListeners != null) {
19224                ArrayList<OnLayoutChangeListener> listenersCopy =
19225                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19226                int numListeners = listenersCopy.size();
19227                for (int i = 0; i < numListeners; ++i) {
19228                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19229                }
19230            }
19231        }
19232
19233        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19234        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19235    }
19236
19237    /**
19238     * Called from layout when this view should
19239     * assign a size and position to each of its children.
19240     *
19241     * Derived classes with children should override
19242     * this method and call layout on each of
19243     * their children.
19244     * @param changed This is a new size or position for this view
19245     * @param left Left position, relative to parent
19246     * @param top Top position, relative to parent
19247     * @param right Right position, relative to parent
19248     * @param bottom Bottom position, relative to parent
19249     */
19250    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19251    }
19252
19253    /**
19254     * Assign a size and position to this view.
19255     *
19256     * This is called from layout.
19257     *
19258     * @param left Left position, relative to parent
19259     * @param top Top position, relative to parent
19260     * @param right Right position, relative to parent
19261     * @param bottom Bottom position, relative to parent
19262     * @return true if the new size and position are different than the
19263     *         previous ones
19264     * {@hide}
19265     */
19266    protected boolean setFrame(int left, int top, int right, int bottom) {
19267        boolean changed = false;
19268
19269        if (DBG) {
19270            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19271                    + right + "," + bottom + ")");
19272        }
19273
19274        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19275            changed = true;
19276
19277            // Remember our drawn bit
19278            int drawn = mPrivateFlags & PFLAG_DRAWN;
19279
19280            int oldWidth = mRight - mLeft;
19281            int oldHeight = mBottom - mTop;
19282            int newWidth = right - left;
19283            int newHeight = bottom - top;
19284            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19285
19286            // Invalidate our old position
19287            invalidate(sizeChanged);
19288
19289            mLeft = left;
19290            mTop = top;
19291            mRight = right;
19292            mBottom = bottom;
19293            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19294
19295            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19296
19297
19298            if (sizeChanged) {
19299                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19300            }
19301
19302            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19303                // If we are visible, force the DRAWN bit to on so that
19304                // this invalidate will go through (at least to our parent).
19305                // This is because someone may have invalidated this view
19306                // before this call to setFrame came in, thereby clearing
19307                // the DRAWN bit.
19308                mPrivateFlags |= PFLAG_DRAWN;
19309                invalidate(sizeChanged);
19310                // parent display list may need to be recreated based on a change in the bounds
19311                // of any child
19312                invalidateParentCaches();
19313            }
19314
19315            // Reset drawn bit to original value (invalidate turns it off)
19316            mPrivateFlags |= drawn;
19317
19318            mBackgroundSizeChanged = true;
19319            if (mForegroundInfo != null) {
19320                mForegroundInfo.mBoundsChanged = true;
19321            }
19322
19323            notifySubtreeAccessibilityStateChangedIfNeeded();
19324        }
19325        return changed;
19326    }
19327
19328    /**
19329     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19330     * @hide
19331     */
19332    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19333        setFrame(left, top, right, bottom);
19334    }
19335
19336    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19337        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19338        if (mOverlay != null) {
19339            mOverlay.getOverlayView().setRight(newWidth);
19340            mOverlay.getOverlayView().setBottom(newHeight);
19341        }
19342        rebuildOutline();
19343    }
19344
19345    /**
19346     * Finalize inflating a view from XML.  This is called as the last phase
19347     * of inflation, after all child views have been added.
19348     *
19349     * <p>Even if the subclass overrides onFinishInflate, they should always be
19350     * sure to call the super method, so that we get called.
19351     */
19352    @CallSuper
19353    protected void onFinishInflate() {
19354    }
19355
19356    /**
19357     * Returns the resources associated with this view.
19358     *
19359     * @return Resources object.
19360     */
19361    public Resources getResources() {
19362        return mResources;
19363    }
19364
19365    /**
19366     * Invalidates the specified Drawable.
19367     *
19368     * @param drawable the drawable to invalidate
19369     */
19370    @Override
19371    public void invalidateDrawable(@NonNull Drawable drawable) {
19372        if (verifyDrawable(drawable)) {
19373            final Rect dirty = drawable.getDirtyBounds();
19374            final int scrollX = mScrollX;
19375            final int scrollY = mScrollY;
19376
19377            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19378                    dirty.right + scrollX, dirty.bottom + scrollY);
19379            rebuildOutline();
19380        }
19381    }
19382
19383    /**
19384     * Schedules an action on a drawable to occur at a specified time.
19385     *
19386     * @param who the recipient of the action
19387     * @param what the action to run on the drawable
19388     * @param when the time at which the action must occur. Uses the
19389     *        {@link SystemClock#uptimeMillis} timebase.
19390     */
19391    @Override
19392    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19393        if (verifyDrawable(who) && what != null) {
19394            final long delay = when - SystemClock.uptimeMillis();
19395            if (mAttachInfo != null) {
19396                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19397                        Choreographer.CALLBACK_ANIMATION, what, who,
19398                        Choreographer.subtractFrameDelay(delay));
19399            } else {
19400                // Postpone the runnable until we know
19401                // on which thread it needs to run.
19402                getRunQueue().postDelayed(what, delay);
19403            }
19404        }
19405    }
19406
19407    /**
19408     * Cancels a scheduled action on a drawable.
19409     *
19410     * @param who the recipient of the action
19411     * @param what the action to cancel
19412     */
19413    @Override
19414    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19415        if (verifyDrawable(who) && what != null) {
19416            if (mAttachInfo != null) {
19417                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19418                        Choreographer.CALLBACK_ANIMATION, what, who);
19419            }
19420            getRunQueue().removeCallbacks(what);
19421        }
19422    }
19423
19424    /**
19425     * Unschedule any events associated with the given Drawable.  This can be
19426     * used when selecting a new Drawable into a view, so that the previous
19427     * one is completely unscheduled.
19428     *
19429     * @param who The Drawable to unschedule.
19430     *
19431     * @see #drawableStateChanged
19432     */
19433    public void unscheduleDrawable(Drawable who) {
19434        if (mAttachInfo != null && who != null) {
19435            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19436                    Choreographer.CALLBACK_ANIMATION, null, who);
19437        }
19438    }
19439
19440    /**
19441     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19442     * that the View directionality can and will be resolved before its Drawables.
19443     *
19444     * Will call {@link View#onResolveDrawables} when resolution is done.
19445     *
19446     * @hide
19447     */
19448    protected void resolveDrawables() {
19449        // Drawables resolution may need to happen before resolving the layout direction (which is
19450        // done only during the measure() call).
19451        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19452        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19453        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19454        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19455        // direction to be resolved as its resolved value will be the same as its raw value.
19456        if (!isLayoutDirectionResolved() &&
19457                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19458            return;
19459        }
19460
19461        final int layoutDirection = isLayoutDirectionResolved() ?
19462                getLayoutDirection() : getRawLayoutDirection();
19463
19464        if (mBackground != null) {
19465            mBackground.setLayoutDirection(layoutDirection);
19466        }
19467        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19468            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19469        }
19470        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19471        onResolveDrawables(layoutDirection);
19472    }
19473
19474    boolean areDrawablesResolved() {
19475        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19476    }
19477
19478    /**
19479     * Called when layout direction has been resolved.
19480     *
19481     * The default implementation does nothing.
19482     *
19483     * @param layoutDirection The resolved layout direction.
19484     *
19485     * @see #LAYOUT_DIRECTION_LTR
19486     * @see #LAYOUT_DIRECTION_RTL
19487     *
19488     * @hide
19489     */
19490    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19491    }
19492
19493    /**
19494     * @hide
19495     */
19496    protected void resetResolvedDrawables() {
19497        resetResolvedDrawablesInternal();
19498    }
19499
19500    void resetResolvedDrawablesInternal() {
19501        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19502    }
19503
19504    /**
19505     * If your view subclass is displaying its own Drawable objects, it should
19506     * override this function and return true for any Drawable it is
19507     * displaying.  This allows animations for those drawables to be
19508     * scheduled.
19509     *
19510     * <p>Be sure to call through to the super class when overriding this
19511     * function.
19512     *
19513     * @param who The Drawable to verify.  Return true if it is one you are
19514     *            displaying, else return the result of calling through to the
19515     *            super class.
19516     *
19517     * @return boolean If true than the Drawable is being displayed in the
19518     *         view; else false and it is not allowed to animate.
19519     *
19520     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19521     * @see #drawableStateChanged()
19522     */
19523    @CallSuper
19524    protected boolean verifyDrawable(@NonNull Drawable who) {
19525        // Avoid verifying the scroll bar drawable so that we don't end up in
19526        // an invalidation loop. This effectively prevents the scroll bar
19527        // drawable from triggering invalidations and scheduling runnables.
19528        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
19529    }
19530
19531    /**
19532     * This function is called whenever the state of the view changes in such
19533     * a way that it impacts the state of drawables being shown.
19534     * <p>
19535     * If the View has a StateListAnimator, it will also be called to run necessary state
19536     * change animations.
19537     * <p>
19538     * Be sure to call through to the superclass when overriding this function.
19539     *
19540     * @see Drawable#setState(int[])
19541     */
19542    @CallSuper
19543    protected void drawableStateChanged() {
19544        final int[] state = getDrawableState();
19545        boolean changed = false;
19546
19547        final Drawable bg = mBackground;
19548        if (bg != null && bg.isStateful()) {
19549            changed |= bg.setState(state);
19550        }
19551
19552        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19553        if (fg != null && fg.isStateful()) {
19554            changed |= fg.setState(state);
19555        }
19556
19557        if (mScrollCache != null) {
19558            final Drawable scrollBar = mScrollCache.scrollBar;
19559            if (scrollBar != null && scrollBar.isStateful()) {
19560                changed |= scrollBar.setState(state)
19561                        && mScrollCache.state != ScrollabilityCache.OFF;
19562            }
19563        }
19564
19565        if (mStateListAnimator != null) {
19566            mStateListAnimator.setState(state);
19567        }
19568
19569        if (changed) {
19570            invalidate();
19571        }
19572    }
19573
19574    /**
19575     * This function is called whenever the view hotspot changes and needs to
19576     * be propagated to drawables or child views managed by the view.
19577     * <p>
19578     * Dispatching to child views is handled by
19579     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19580     * <p>
19581     * Be sure to call through to the superclass when overriding this function.
19582     *
19583     * @param x hotspot x coordinate
19584     * @param y hotspot y coordinate
19585     */
19586    @CallSuper
19587    public void drawableHotspotChanged(float x, float y) {
19588        if (mBackground != null) {
19589            mBackground.setHotspot(x, y);
19590        }
19591        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19592            mForegroundInfo.mDrawable.setHotspot(x, y);
19593        }
19594
19595        dispatchDrawableHotspotChanged(x, y);
19596    }
19597
19598    /**
19599     * Dispatches drawableHotspotChanged to all of this View's children.
19600     *
19601     * @param x hotspot x coordinate
19602     * @param y hotspot y coordinate
19603     * @see #drawableHotspotChanged(float, float)
19604     */
19605    public void dispatchDrawableHotspotChanged(float x, float y) {
19606    }
19607
19608    /**
19609     * Call this to force a view to update its drawable state. This will cause
19610     * drawableStateChanged to be called on this view. Views that are interested
19611     * in the new state should call getDrawableState.
19612     *
19613     * @see #drawableStateChanged
19614     * @see #getDrawableState
19615     */
19616    public void refreshDrawableState() {
19617        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19618        drawableStateChanged();
19619
19620        ViewParent parent = mParent;
19621        if (parent != null) {
19622            parent.childDrawableStateChanged(this);
19623        }
19624    }
19625
19626    /**
19627     * Return an array of resource IDs of the drawable states representing the
19628     * current state of the view.
19629     *
19630     * @return The current drawable state
19631     *
19632     * @see Drawable#setState(int[])
19633     * @see #drawableStateChanged()
19634     * @see #onCreateDrawableState(int)
19635     */
19636    public final int[] getDrawableState() {
19637        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19638            return mDrawableState;
19639        } else {
19640            mDrawableState = onCreateDrawableState(0);
19641            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19642            return mDrawableState;
19643        }
19644    }
19645
19646    /**
19647     * Generate the new {@link android.graphics.drawable.Drawable} state for
19648     * this view. This is called by the view
19649     * system when the cached Drawable state is determined to be invalid.  To
19650     * retrieve the current state, you should use {@link #getDrawableState}.
19651     *
19652     * @param extraSpace if non-zero, this is the number of extra entries you
19653     * would like in the returned array in which you can place your own
19654     * states.
19655     *
19656     * @return Returns an array holding the current {@link Drawable} state of
19657     * the view.
19658     *
19659     * @see #mergeDrawableStates(int[], int[])
19660     */
19661    protected int[] onCreateDrawableState(int extraSpace) {
19662        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19663                mParent instanceof View) {
19664            return ((View) mParent).onCreateDrawableState(extraSpace);
19665        }
19666
19667        int[] drawableState;
19668
19669        int privateFlags = mPrivateFlags;
19670
19671        int viewStateIndex = 0;
19672        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19673        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19674        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19675        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19676        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19677        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19678        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19679                ThreadedRenderer.isAvailable()) {
19680            // This is set if HW acceleration is requested, even if the current
19681            // process doesn't allow it.  This is just to allow app preview
19682            // windows to better match their app.
19683            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19684        }
19685        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19686
19687        final int privateFlags2 = mPrivateFlags2;
19688        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19689            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19690        }
19691        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19692            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19693        }
19694
19695        drawableState = StateSet.get(viewStateIndex);
19696
19697        //noinspection ConstantIfStatement
19698        if (false) {
19699            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19700            Log.i("View", toString()
19701                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19702                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19703                    + " fo=" + hasFocus()
19704                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19705                    + " wf=" + hasWindowFocus()
19706                    + ": " + Arrays.toString(drawableState));
19707        }
19708
19709        if (extraSpace == 0) {
19710            return drawableState;
19711        }
19712
19713        final int[] fullState;
19714        if (drawableState != null) {
19715            fullState = new int[drawableState.length + extraSpace];
19716            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19717        } else {
19718            fullState = new int[extraSpace];
19719        }
19720
19721        return fullState;
19722    }
19723
19724    /**
19725     * Merge your own state values in <var>additionalState</var> into the base
19726     * state values <var>baseState</var> that were returned by
19727     * {@link #onCreateDrawableState(int)}.
19728     *
19729     * @param baseState The base state values returned by
19730     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19731     * own additional state values.
19732     *
19733     * @param additionalState The additional state values you would like
19734     * added to <var>baseState</var>; this array is not modified.
19735     *
19736     * @return As a convenience, the <var>baseState</var> array you originally
19737     * passed into the function is returned.
19738     *
19739     * @see #onCreateDrawableState(int)
19740     */
19741    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19742        final int N = baseState.length;
19743        int i = N - 1;
19744        while (i >= 0 && baseState[i] == 0) {
19745            i--;
19746        }
19747        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19748        return baseState;
19749    }
19750
19751    /**
19752     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19753     * on all Drawable objects associated with this view.
19754     * <p>
19755     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19756     * attached to this view.
19757     */
19758    @CallSuper
19759    public void jumpDrawablesToCurrentState() {
19760        if (mBackground != null) {
19761            mBackground.jumpToCurrentState();
19762        }
19763        if (mStateListAnimator != null) {
19764            mStateListAnimator.jumpToCurrentState();
19765        }
19766        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19767            mForegroundInfo.mDrawable.jumpToCurrentState();
19768        }
19769    }
19770
19771    /**
19772     * Sets the background color for this view.
19773     * @param color the color of the background
19774     */
19775    @RemotableViewMethod
19776    public void setBackgroundColor(@ColorInt int color) {
19777        if (mBackground instanceof ColorDrawable) {
19778            ((ColorDrawable) mBackground.mutate()).setColor(color);
19779            computeOpaqueFlags();
19780            mBackgroundResource = 0;
19781        } else {
19782            setBackground(new ColorDrawable(color));
19783        }
19784    }
19785
19786    /**
19787     * Set the background to a given resource. The resource should refer to
19788     * a Drawable object or 0 to remove the background.
19789     * @param resid The identifier of the resource.
19790     *
19791     * @attr ref android.R.styleable#View_background
19792     */
19793    @RemotableViewMethod
19794    public void setBackgroundResource(@DrawableRes int resid) {
19795        if (resid != 0 && resid == mBackgroundResource) {
19796            return;
19797        }
19798
19799        Drawable d = null;
19800        if (resid != 0) {
19801            d = mContext.getDrawable(resid);
19802        }
19803        setBackground(d);
19804
19805        mBackgroundResource = resid;
19806    }
19807
19808    /**
19809     * Set the background to a given Drawable, or remove the background. If the
19810     * background has padding, this View's padding is set to the background's
19811     * padding. However, when a background is removed, this View's padding isn't
19812     * touched. If setting the padding is desired, please use
19813     * {@link #setPadding(int, int, int, int)}.
19814     *
19815     * @param background The Drawable to use as the background, or null to remove the
19816     *        background
19817     */
19818    public void setBackground(Drawable background) {
19819        //noinspection deprecation
19820        setBackgroundDrawable(background);
19821    }
19822
19823    /**
19824     * @deprecated use {@link #setBackground(Drawable)} instead
19825     */
19826    @Deprecated
19827    public void setBackgroundDrawable(Drawable background) {
19828        computeOpaqueFlags();
19829
19830        if (background == mBackground) {
19831            return;
19832        }
19833
19834        boolean requestLayout = false;
19835
19836        mBackgroundResource = 0;
19837
19838        /*
19839         * Regardless of whether we're setting a new background or not, we want
19840         * to clear the previous drawable. setVisible first while we still have the callback set.
19841         */
19842        if (mBackground != null) {
19843            if (isAttachedToWindow()) {
19844                mBackground.setVisible(false, false);
19845            }
19846            mBackground.setCallback(null);
19847            unscheduleDrawable(mBackground);
19848        }
19849
19850        if (background != null) {
19851            Rect padding = sThreadLocal.get();
19852            if (padding == null) {
19853                padding = new Rect();
19854                sThreadLocal.set(padding);
19855            }
19856            resetResolvedDrawablesInternal();
19857            background.setLayoutDirection(getLayoutDirection());
19858            if (background.getPadding(padding)) {
19859                resetResolvedPaddingInternal();
19860                switch (background.getLayoutDirection()) {
19861                    case LAYOUT_DIRECTION_RTL:
19862                        mUserPaddingLeftInitial = padding.right;
19863                        mUserPaddingRightInitial = padding.left;
19864                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19865                        break;
19866                    case LAYOUT_DIRECTION_LTR:
19867                    default:
19868                        mUserPaddingLeftInitial = padding.left;
19869                        mUserPaddingRightInitial = padding.right;
19870                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19871                }
19872                mLeftPaddingDefined = false;
19873                mRightPaddingDefined = false;
19874            }
19875
19876            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19877            // if it has a different minimum size, we should layout again
19878            if (mBackground == null
19879                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19880                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19881                requestLayout = true;
19882            }
19883
19884            // Set mBackground before we set this as the callback and start making other
19885            // background drawable state change calls. In particular, the setVisible call below
19886            // can result in drawables attempting to start animations or otherwise invalidate,
19887            // which requires the view set as the callback (us) to recognize the drawable as
19888            // belonging to it as per verifyDrawable.
19889            mBackground = background;
19890            if (background.isStateful()) {
19891                background.setState(getDrawableState());
19892            }
19893            if (isAttachedToWindow()) {
19894                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19895            }
19896
19897            applyBackgroundTint();
19898
19899            // Set callback last, since the view may still be initializing.
19900            background.setCallback(this);
19901
19902            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19903                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19904                requestLayout = true;
19905            }
19906        } else {
19907            /* Remove the background */
19908            mBackground = null;
19909            if ((mViewFlags & WILL_NOT_DRAW) != 0
19910                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19911                mPrivateFlags |= PFLAG_SKIP_DRAW;
19912            }
19913
19914            /*
19915             * When the background is set, we try to apply its padding to this
19916             * View. When the background is removed, we don't touch this View's
19917             * padding. This is noted in the Javadocs. Hence, we don't need to
19918             * requestLayout(), the invalidate() below is sufficient.
19919             */
19920
19921            // The old background's minimum size could have affected this
19922            // View's layout, so let's requestLayout
19923            requestLayout = true;
19924        }
19925
19926        computeOpaqueFlags();
19927
19928        if (requestLayout) {
19929            requestLayout();
19930        }
19931
19932        mBackgroundSizeChanged = true;
19933        invalidate(true);
19934        invalidateOutline();
19935    }
19936
19937    /**
19938     * Gets the background drawable
19939     *
19940     * @return The drawable used as the background for this view, if any.
19941     *
19942     * @see #setBackground(Drawable)
19943     *
19944     * @attr ref android.R.styleable#View_background
19945     */
19946    public Drawable getBackground() {
19947        return mBackground;
19948    }
19949
19950    /**
19951     * Applies a tint to the background drawable. Does not modify the current tint
19952     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19953     * <p>
19954     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
19955     * mutate the drawable and apply the specified tint and tint mode using
19956     * {@link Drawable#setTintList(ColorStateList)}.
19957     *
19958     * @param tint the tint to apply, may be {@code null} to clear tint
19959     *
19960     * @attr ref android.R.styleable#View_backgroundTint
19961     * @see #getBackgroundTintList()
19962     * @see Drawable#setTintList(ColorStateList)
19963     */
19964    public void setBackgroundTintList(@Nullable ColorStateList tint) {
19965        if (mBackgroundTint == null) {
19966            mBackgroundTint = new TintInfo();
19967        }
19968        mBackgroundTint.mTintList = tint;
19969        mBackgroundTint.mHasTintList = true;
19970
19971        applyBackgroundTint();
19972    }
19973
19974    /**
19975     * Return the tint applied to the background drawable, if specified.
19976     *
19977     * @return the tint applied to the background drawable
19978     * @attr ref android.R.styleable#View_backgroundTint
19979     * @see #setBackgroundTintList(ColorStateList)
19980     */
19981    @Nullable
19982    public ColorStateList getBackgroundTintList() {
19983        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
19984    }
19985
19986    /**
19987     * Specifies the blending mode used to apply the tint specified by
19988     * {@link #setBackgroundTintList(ColorStateList)}} to the background
19989     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19990     *
19991     * @param tintMode the blending mode used to apply the tint, may be
19992     *                 {@code null} to clear tint
19993     * @attr ref android.R.styleable#View_backgroundTintMode
19994     * @see #getBackgroundTintMode()
19995     * @see Drawable#setTintMode(PorterDuff.Mode)
19996     */
19997    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19998        if (mBackgroundTint == null) {
19999            mBackgroundTint = new TintInfo();
20000        }
20001        mBackgroundTint.mTintMode = tintMode;
20002        mBackgroundTint.mHasTintMode = true;
20003
20004        applyBackgroundTint();
20005    }
20006
20007    /**
20008     * Return the blending mode used to apply the tint to the background
20009     * drawable, if specified.
20010     *
20011     * @return the blending mode used to apply the tint to the background
20012     *         drawable
20013     * @attr ref android.R.styleable#View_backgroundTintMode
20014     * @see #setBackgroundTintMode(PorterDuff.Mode)
20015     */
20016    @Nullable
20017    public PorterDuff.Mode getBackgroundTintMode() {
20018        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20019    }
20020
20021    private void applyBackgroundTint() {
20022        if (mBackground != null && mBackgroundTint != null) {
20023            final TintInfo tintInfo = mBackgroundTint;
20024            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20025                mBackground = mBackground.mutate();
20026
20027                if (tintInfo.mHasTintList) {
20028                    mBackground.setTintList(tintInfo.mTintList);
20029                }
20030
20031                if (tintInfo.mHasTintMode) {
20032                    mBackground.setTintMode(tintInfo.mTintMode);
20033                }
20034
20035                // The drawable (or one of its children) may not have been
20036                // stateful before applying the tint, so let's try again.
20037                if (mBackground.isStateful()) {
20038                    mBackground.setState(getDrawableState());
20039                }
20040            }
20041        }
20042    }
20043
20044    /**
20045     * Returns the drawable used as the foreground of this View. The
20046     * foreground drawable, if non-null, is always drawn on top of the view's content.
20047     *
20048     * @return a Drawable or null if no foreground was set
20049     *
20050     * @see #onDrawForeground(Canvas)
20051     */
20052    public Drawable getForeground() {
20053        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20054    }
20055
20056    /**
20057     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20058     *
20059     * @param foreground the Drawable to be drawn on top of the children
20060     *
20061     * @attr ref android.R.styleable#View_foreground
20062     */
20063    public void setForeground(Drawable foreground) {
20064        if (mForegroundInfo == null) {
20065            if (foreground == null) {
20066                // Nothing to do.
20067                return;
20068            }
20069            mForegroundInfo = new ForegroundInfo();
20070        }
20071
20072        if (foreground == mForegroundInfo.mDrawable) {
20073            // Nothing to do
20074            return;
20075        }
20076
20077        if (mForegroundInfo.mDrawable != null) {
20078            if (isAttachedToWindow()) {
20079                mForegroundInfo.mDrawable.setVisible(false, false);
20080            }
20081            mForegroundInfo.mDrawable.setCallback(null);
20082            unscheduleDrawable(mForegroundInfo.mDrawable);
20083        }
20084
20085        mForegroundInfo.mDrawable = foreground;
20086        mForegroundInfo.mBoundsChanged = true;
20087        if (foreground != null) {
20088            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20089                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20090            }
20091            foreground.setLayoutDirection(getLayoutDirection());
20092            if (foreground.isStateful()) {
20093                foreground.setState(getDrawableState());
20094            }
20095            applyForegroundTint();
20096            if (isAttachedToWindow()) {
20097                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20098            }
20099            // Set callback last, since the view may still be initializing.
20100            foreground.setCallback(this);
20101        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
20102            mPrivateFlags |= PFLAG_SKIP_DRAW;
20103        }
20104        requestLayout();
20105        invalidate();
20106    }
20107
20108    /**
20109     * Magic bit used to support features of framework-internal window decor implementation details.
20110     * This used to live exclusively in FrameLayout.
20111     *
20112     * @return true if the foreground should draw inside the padding region or false
20113     *         if it should draw inset by the view's padding
20114     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20115     */
20116    public boolean isForegroundInsidePadding() {
20117        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20118    }
20119
20120    /**
20121     * Describes how the foreground is positioned.
20122     *
20123     * @return foreground gravity.
20124     *
20125     * @see #setForegroundGravity(int)
20126     *
20127     * @attr ref android.R.styleable#View_foregroundGravity
20128     */
20129    public int getForegroundGravity() {
20130        return mForegroundInfo != null ? mForegroundInfo.mGravity
20131                : Gravity.START | Gravity.TOP;
20132    }
20133
20134    /**
20135     * Describes how the foreground is positioned. Defaults to START and TOP.
20136     *
20137     * @param gravity see {@link android.view.Gravity}
20138     *
20139     * @see #getForegroundGravity()
20140     *
20141     * @attr ref android.R.styleable#View_foregroundGravity
20142     */
20143    public void setForegroundGravity(int gravity) {
20144        if (mForegroundInfo == null) {
20145            mForegroundInfo = new ForegroundInfo();
20146        }
20147
20148        if (mForegroundInfo.mGravity != gravity) {
20149            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20150                gravity |= Gravity.START;
20151            }
20152
20153            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20154                gravity |= Gravity.TOP;
20155            }
20156
20157            mForegroundInfo.mGravity = gravity;
20158            requestLayout();
20159        }
20160    }
20161
20162    /**
20163     * Applies a tint to the foreground drawable. Does not modify the current tint
20164     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20165     * <p>
20166     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20167     * mutate the drawable and apply the specified tint and tint mode using
20168     * {@link Drawable#setTintList(ColorStateList)}.
20169     *
20170     * @param tint the tint to apply, may be {@code null} to clear tint
20171     *
20172     * @attr ref android.R.styleable#View_foregroundTint
20173     * @see #getForegroundTintList()
20174     * @see Drawable#setTintList(ColorStateList)
20175     */
20176    public void setForegroundTintList(@Nullable ColorStateList tint) {
20177        if (mForegroundInfo == null) {
20178            mForegroundInfo = new ForegroundInfo();
20179        }
20180        if (mForegroundInfo.mTintInfo == null) {
20181            mForegroundInfo.mTintInfo = new TintInfo();
20182        }
20183        mForegroundInfo.mTintInfo.mTintList = tint;
20184        mForegroundInfo.mTintInfo.mHasTintList = true;
20185
20186        applyForegroundTint();
20187    }
20188
20189    /**
20190     * Return the tint applied to the foreground drawable, if specified.
20191     *
20192     * @return the tint applied to the foreground drawable
20193     * @attr ref android.R.styleable#View_foregroundTint
20194     * @see #setForegroundTintList(ColorStateList)
20195     */
20196    @Nullable
20197    public ColorStateList getForegroundTintList() {
20198        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20199                ? mForegroundInfo.mTintInfo.mTintList : null;
20200    }
20201
20202    /**
20203     * Specifies the blending mode used to apply the tint specified by
20204     * {@link #setForegroundTintList(ColorStateList)}} to the background
20205     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20206     *
20207     * @param tintMode the blending mode used to apply the tint, may be
20208     *                 {@code null} to clear tint
20209     * @attr ref android.R.styleable#View_foregroundTintMode
20210     * @see #getForegroundTintMode()
20211     * @see Drawable#setTintMode(PorterDuff.Mode)
20212     */
20213    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20214        if (mForegroundInfo == null) {
20215            mForegroundInfo = new ForegroundInfo();
20216        }
20217        if (mForegroundInfo.mTintInfo == null) {
20218            mForegroundInfo.mTintInfo = new TintInfo();
20219        }
20220        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20221        mForegroundInfo.mTintInfo.mHasTintMode = true;
20222
20223        applyForegroundTint();
20224    }
20225
20226    /**
20227     * Return the blending mode used to apply the tint to the foreground
20228     * drawable, if specified.
20229     *
20230     * @return the blending mode used to apply the tint to the foreground
20231     *         drawable
20232     * @attr ref android.R.styleable#View_foregroundTintMode
20233     * @see #setForegroundTintMode(PorterDuff.Mode)
20234     */
20235    @Nullable
20236    public PorterDuff.Mode getForegroundTintMode() {
20237        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20238                ? mForegroundInfo.mTintInfo.mTintMode : null;
20239    }
20240
20241    private void applyForegroundTint() {
20242        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20243                && mForegroundInfo.mTintInfo != null) {
20244            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20245            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20246                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20247
20248                if (tintInfo.mHasTintList) {
20249                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20250                }
20251
20252                if (tintInfo.mHasTintMode) {
20253                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20254                }
20255
20256                // The drawable (or one of its children) may not have been
20257                // stateful before applying the tint, so let's try again.
20258                if (mForegroundInfo.mDrawable.isStateful()) {
20259                    mForegroundInfo.mDrawable.setState(getDrawableState());
20260                }
20261            }
20262        }
20263    }
20264
20265    /**
20266     * Get the drawable to be overlayed when a view is autofilled
20267     *
20268     * @return The drawable
20269     *
20270     * @throws IllegalStateException if the drawable could not be found.
20271     */
20272    @NonNull private Drawable getAutofilledDrawable() {
20273        // Lazily load the isAutofilled drawable.
20274        if (mAttachInfo.mAutofilledDrawable == null) {
20275            mAttachInfo.mAutofilledDrawable = mContext.getDrawable(R.drawable.autofilled_highlight);
20276
20277            if (mAttachInfo.mAutofilledDrawable == null) {
20278                throw new IllegalStateException(
20279                        "Could not find android:drawable/autofilled_highlight");
20280            }
20281        }
20282
20283        return mAttachInfo.mAutofilledDrawable;
20284    }
20285
20286    /**
20287     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20288     *
20289     * @param canvas The canvas to draw on
20290     */
20291    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20292        if (isAutofilled()) {
20293            Drawable autofilledHighlight = getAutofilledDrawable();
20294
20295            autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20296            autofilledHighlight.draw(canvas);
20297        }
20298    }
20299
20300    /**
20301     * Draw any foreground content for this view.
20302     *
20303     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20304     * drawable or other view-specific decorations. The foreground is drawn on top of the
20305     * primary view content.</p>
20306     *
20307     * @param canvas canvas to draw into
20308     */
20309    public void onDrawForeground(Canvas canvas) {
20310        onDrawScrollIndicators(canvas);
20311        onDrawScrollBars(canvas);
20312
20313        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20314        if (foreground != null) {
20315            if (mForegroundInfo.mBoundsChanged) {
20316                mForegroundInfo.mBoundsChanged = false;
20317                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20318                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20319
20320                if (mForegroundInfo.mInsidePadding) {
20321                    selfBounds.set(0, 0, getWidth(), getHeight());
20322                } else {
20323                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20324                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20325                }
20326
20327                final int ld = getLayoutDirection();
20328                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20329                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20330                foreground.setBounds(overlayBounds);
20331            }
20332
20333            foreground.draw(canvas);
20334        }
20335    }
20336
20337    /**
20338     * Sets the padding. The view may add on the space required to display
20339     * the scrollbars, depending on the style and visibility of the scrollbars.
20340     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20341     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20342     * from the values set in this call.
20343     *
20344     * @attr ref android.R.styleable#View_padding
20345     * @attr ref android.R.styleable#View_paddingBottom
20346     * @attr ref android.R.styleable#View_paddingLeft
20347     * @attr ref android.R.styleable#View_paddingRight
20348     * @attr ref android.R.styleable#View_paddingTop
20349     * @param left the left padding in pixels
20350     * @param top the top padding in pixels
20351     * @param right the right padding in pixels
20352     * @param bottom the bottom padding in pixels
20353     */
20354    public void setPadding(int left, int top, int right, int bottom) {
20355        resetResolvedPaddingInternal();
20356
20357        mUserPaddingStart = UNDEFINED_PADDING;
20358        mUserPaddingEnd = UNDEFINED_PADDING;
20359
20360        mUserPaddingLeftInitial = left;
20361        mUserPaddingRightInitial = right;
20362
20363        mLeftPaddingDefined = true;
20364        mRightPaddingDefined = true;
20365
20366        internalSetPadding(left, top, right, bottom);
20367    }
20368
20369    /**
20370     * @hide
20371     */
20372    protected void internalSetPadding(int left, int top, int right, int bottom) {
20373        mUserPaddingLeft = left;
20374        mUserPaddingRight = right;
20375        mUserPaddingBottom = bottom;
20376
20377        final int viewFlags = mViewFlags;
20378        boolean changed = false;
20379
20380        // Common case is there are no scroll bars.
20381        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20382            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20383                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20384                        ? 0 : getVerticalScrollbarWidth();
20385                switch (mVerticalScrollbarPosition) {
20386                    case SCROLLBAR_POSITION_DEFAULT:
20387                        if (isLayoutRtl()) {
20388                            left += offset;
20389                        } else {
20390                            right += offset;
20391                        }
20392                        break;
20393                    case SCROLLBAR_POSITION_RIGHT:
20394                        right += offset;
20395                        break;
20396                    case SCROLLBAR_POSITION_LEFT:
20397                        left += offset;
20398                        break;
20399                }
20400            }
20401            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20402                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20403                        ? 0 : getHorizontalScrollbarHeight();
20404            }
20405        }
20406
20407        if (mPaddingLeft != left) {
20408            changed = true;
20409            mPaddingLeft = left;
20410        }
20411        if (mPaddingTop != top) {
20412            changed = true;
20413            mPaddingTop = top;
20414        }
20415        if (mPaddingRight != right) {
20416            changed = true;
20417            mPaddingRight = right;
20418        }
20419        if (mPaddingBottom != bottom) {
20420            changed = true;
20421            mPaddingBottom = bottom;
20422        }
20423
20424        if (changed) {
20425            requestLayout();
20426            invalidateOutline();
20427        }
20428    }
20429
20430    /**
20431     * Sets the relative padding. The view may add on the space required to display
20432     * the scrollbars, depending on the style and visibility of the scrollbars.
20433     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20434     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20435     * from the values set in this call.
20436     *
20437     * @attr ref android.R.styleable#View_padding
20438     * @attr ref android.R.styleable#View_paddingBottom
20439     * @attr ref android.R.styleable#View_paddingStart
20440     * @attr ref android.R.styleable#View_paddingEnd
20441     * @attr ref android.R.styleable#View_paddingTop
20442     * @param start the start padding in pixels
20443     * @param top the top padding in pixels
20444     * @param end the end padding in pixels
20445     * @param bottom the bottom padding in pixels
20446     */
20447    public void setPaddingRelative(int start, int top, int end, int bottom) {
20448        resetResolvedPaddingInternal();
20449
20450        mUserPaddingStart = start;
20451        mUserPaddingEnd = end;
20452        mLeftPaddingDefined = true;
20453        mRightPaddingDefined = true;
20454
20455        switch(getLayoutDirection()) {
20456            case LAYOUT_DIRECTION_RTL:
20457                mUserPaddingLeftInitial = end;
20458                mUserPaddingRightInitial = start;
20459                internalSetPadding(end, top, start, bottom);
20460                break;
20461            case LAYOUT_DIRECTION_LTR:
20462            default:
20463                mUserPaddingLeftInitial = start;
20464                mUserPaddingRightInitial = end;
20465                internalSetPadding(start, top, end, bottom);
20466        }
20467    }
20468
20469    /**
20470     * Returns the top padding of this view.
20471     *
20472     * @return the top padding in pixels
20473     */
20474    public int getPaddingTop() {
20475        return mPaddingTop;
20476    }
20477
20478    /**
20479     * Returns the bottom padding of this view. If there are inset and enabled
20480     * scrollbars, this value may include the space required to display the
20481     * scrollbars as well.
20482     *
20483     * @return the bottom padding in pixels
20484     */
20485    public int getPaddingBottom() {
20486        return mPaddingBottom;
20487    }
20488
20489    /**
20490     * Returns the left padding of this view. If there are inset and enabled
20491     * scrollbars, this value may include the space required to display the
20492     * scrollbars as well.
20493     *
20494     * @return the left padding in pixels
20495     */
20496    public int getPaddingLeft() {
20497        if (!isPaddingResolved()) {
20498            resolvePadding();
20499        }
20500        return mPaddingLeft;
20501    }
20502
20503    /**
20504     * Returns the start padding of this view depending on its resolved layout direction.
20505     * If there are inset and enabled scrollbars, this value may include the space
20506     * required to display the scrollbars as well.
20507     *
20508     * @return the start padding in pixels
20509     */
20510    public int getPaddingStart() {
20511        if (!isPaddingResolved()) {
20512            resolvePadding();
20513        }
20514        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20515                mPaddingRight : mPaddingLeft;
20516    }
20517
20518    /**
20519     * Returns the right padding of this view. If there are inset and enabled
20520     * scrollbars, this value may include the space required to display the
20521     * scrollbars as well.
20522     *
20523     * @return the right padding in pixels
20524     */
20525    public int getPaddingRight() {
20526        if (!isPaddingResolved()) {
20527            resolvePadding();
20528        }
20529        return mPaddingRight;
20530    }
20531
20532    /**
20533     * Returns the end padding of this view depending on its resolved layout direction.
20534     * If there are inset and enabled scrollbars, this value may include the space
20535     * required to display the scrollbars as well.
20536     *
20537     * @return the end padding in pixels
20538     */
20539    public int getPaddingEnd() {
20540        if (!isPaddingResolved()) {
20541            resolvePadding();
20542        }
20543        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20544                mPaddingLeft : mPaddingRight;
20545    }
20546
20547    /**
20548     * Return if the padding has been set through relative values
20549     * {@link #setPaddingRelative(int, int, int, int)} or through
20550     * @attr ref android.R.styleable#View_paddingStart or
20551     * @attr ref android.R.styleable#View_paddingEnd
20552     *
20553     * @return true if the padding is relative or false if it is not.
20554     */
20555    public boolean isPaddingRelative() {
20556        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20557    }
20558
20559    Insets computeOpticalInsets() {
20560        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20561    }
20562
20563    /**
20564     * @hide
20565     */
20566    public void resetPaddingToInitialValues() {
20567        if (isRtlCompatibilityMode()) {
20568            mPaddingLeft = mUserPaddingLeftInitial;
20569            mPaddingRight = mUserPaddingRightInitial;
20570            return;
20571        }
20572        if (isLayoutRtl()) {
20573            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20574            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20575        } else {
20576            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20577            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20578        }
20579    }
20580
20581    /**
20582     * @hide
20583     */
20584    public Insets getOpticalInsets() {
20585        if (mLayoutInsets == null) {
20586            mLayoutInsets = computeOpticalInsets();
20587        }
20588        return mLayoutInsets;
20589    }
20590
20591    /**
20592     * Set this view's optical insets.
20593     *
20594     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20595     * property. Views that compute their own optical insets should call it as part of measurement.
20596     * This method does not request layout. If you are setting optical insets outside of
20597     * measure/layout itself you will want to call requestLayout() yourself.
20598     * </p>
20599     * @hide
20600     */
20601    public void setOpticalInsets(Insets insets) {
20602        mLayoutInsets = insets;
20603    }
20604
20605    /**
20606     * Changes the selection state of this view. A view can be selected or not.
20607     * Note that selection is not the same as focus. Views are typically
20608     * selected in the context of an AdapterView like ListView or GridView;
20609     * the selected view is the view that is highlighted.
20610     *
20611     * @param selected true if the view must be selected, false otherwise
20612     */
20613    public void setSelected(boolean selected) {
20614        //noinspection DoubleNegation
20615        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20616            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20617            if (!selected) resetPressedState();
20618            invalidate(true);
20619            refreshDrawableState();
20620            dispatchSetSelected(selected);
20621            if (selected) {
20622                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20623            } else {
20624                notifyViewAccessibilityStateChangedIfNeeded(
20625                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20626            }
20627        }
20628    }
20629
20630    /**
20631     * Dispatch setSelected to all of this View's children.
20632     *
20633     * @see #setSelected(boolean)
20634     *
20635     * @param selected The new selected state
20636     */
20637    protected void dispatchSetSelected(boolean selected) {
20638    }
20639
20640    /**
20641     * Indicates the selection state of this view.
20642     *
20643     * @return true if the view is selected, false otherwise
20644     */
20645    @ViewDebug.ExportedProperty
20646    public boolean isSelected() {
20647        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20648    }
20649
20650    /**
20651     * Changes the activated state of this view. A view can be activated or not.
20652     * Note that activation is not the same as selection.  Selection is
20653     * a transient property, representing the view (hierarchy) the user is
20654     * currently interacting with.  Activation is a longer-term state that the
20655     * user can move views in and out of.  For example, in a list view with
20656     * single or multiple selection enabled, the views in the current selection
20657     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20658     * here.)  The activated state is propagated down to children of the view it
20659     * is set on.
20660     *
20661     * @param activated true if the view must be activated, false otherwise
20662     */
20663    public void setActivated(boolean activated) {
20664        //noinspection DoubleNegation
20665        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20666            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20667            invalidate(true);
20668            refreshDrawableState();
20669            dispatchSetActivated(activated);
20670        }
20671    }
20672
20673    /**
20674     * Dispatch setActivated to all of this View's children.
20675     *
20676     * @see #setActivated(boolean)
20677     *
20678     * @param activated The new activated state
20679     */
20680    protected void dispatchSetActivated(boolean activated) {
20681    }
20682
20683    /**
20684     * Indicates the activation state of this view.
20685     *
20686     * @return true if the view is activated, false otherwise
20687     */
20688    @ViewDebug.ExportedProperty
20689    public boolean isActivated() {
20690        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20691    }
20692
20693    /**
20694     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20695     * observer can be used to get notifications when global events, like
20696     * layout, happen.
20697     *
20698     * The returned ViewTreeObserver observer is not guaranteed to remain
20699     * valid for the lifetime of this View. If the caller of this method keeps
20700     * a long-lived reference to ViewTreeObserver, it should always check for
20701     * the return value of {@link ViewTreeObserver#isAlive()}.
20702     *
20703     * @return The ViewTreeObserver for this view's hierarchy.
20704     */
20705    public ViewTreeObserver getViewTreeObserver() {
20706        if (mAttachInfo != null) {
20707            return mAttachInfo.mTreeObserver;
20708        }
20709        if (mFloatingTreeObserver == null) {
20710            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20711        }
20712        return mFloatingTreeObserver;
20713    }
20714
20715    /**
20716     * <p>Finds the topmost view in the current view hierarchy.</p>
20717     *
20718     * @return the topmost view containing this view
20719     */
20720    public View getRootView() {
20721        if (mAttachInfo != null) {
20722            final View v = mAttachInfo.mRootView;
20723            if (v != null) {
20724                return v;
20725            }
20726        }
20727
20728        View parent = this;
20729
20730        while (parent.mParent != null && parent.mParent instanceof View) {
20731            parent = (View) parent.mParent;
20732        }
20733
20734        return parent;
20735    }
20736
20737    /**
20738     * Transforms a motion event from view-local coordinates to on-screen
20739     * coordinates.
20740     *
20741     * @param ev the view-local motion event
20742     * @return false if the transformation could not be applied
20743     * @hide
20744     */
20745    public boolean toGlobalMotionEvent(MotionEvent ev) {
20746        final AttachInfo info = mAttachInfo;
20747        if (info == null) {
20748            return false;
20749        }
20750
20751        final Matrix m = info.mTmpMatrix;
20752        m.set(Matrix.IDENTITY_MATRIX);
20753        transformMatrixToGlobal(m);
20754        ev.transform(m);
20755        return true;
20756    }
20757
20758    /**
20759     * Transforms a motion event from on-screen coordinates to view-local
20760     * coordinates.
20761     *
20762     * @param ev the on-screen motion event
20763     * @return false if the transformation could not be applied
20764     * @hide
20765     */
20766    public boolean toLocalMotionEvent(MotionEvent ev) {
20767        final AttachInfo info = mAttachInfo;
20768        if (info == null) {
20769            return false;
20770        }
20771
20772        final Matrix m = info.mTmpMatrix;
20773        m.set(Matrix.IDENTITY_MATRIX);
20774        transformMatrixToLocal(m);
20775        ev.transform(m);
20776        return true;
20777    }
20778
20779    /**
20780     * Modifies the input matrix such that it maps view-local coordinates to
20781     * on-screen coordinates.
20782     *
20783     * @param m input matrix to modify
20784     * @hide
20785     */
20786    public void transformMatrixToGlobal(Matrix m) {
20787        final ViewParent parent = mParent;
20788        if (parent instanceof View) {
20789            final View vp = (View) parent;
20790            vp.transformMatrixToGlobal(m);
20791            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20792        } else if (parent instanceof ViewRootImpl) {
20793            final ViewRootImpl vr = (ViewRootImpl) parent;
20794            vr.transformMatrixToGlobal(m);
20795            m.preTranslate(0, -vr.mCurScrollY);
20796        }
20797
20798        m.preTranslate(mLeft, mTop);
20799
20800        if (!hasIdentityMatrix()) {
20801            m.preConcat(getMatrix());
20802        }
20803    }
20804
20805    /**
20806     * Modifies the input matrix such that it maps on-screen coordinates to
20807     * view-local coordinates.
20808     *
20809     * @param m input matrix to modify
20810     * @hide
20811     */
20812    public void transformMatrixToLocal(Matrix m) {
20813        final ViewParent parent = mParent;
20814        if (parent instanceof View) {
20815            final View vp = (View) parent;
20816            vp.transformMatrixToLocal(m);
20817            m.postTranslate(vp.mScrollX, vp.mScrollY);
20818        } else if (parent instanceof ViewRootImpl) {
20819            final ViewRootImpl vr = (ViewRootImpl) parent;
20820            vr.transformMatrixToLocal(m);
20821            m.postTranslate(0, vr.mCurScrollY);
20822        }
20823
20824        m.postTranslate(-mLeft, -mTop);
20825
20826        if (!hasIdentityMatrix()) {
20827            m.postConcat(getInverseMatrix());
20828        }
20829    }
20830
20831    /**
20832     * @hide
20833     */
20834    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20835            @ViewDebug.IntToString(from = 0, to = "x"),
20836            @ViewDebug.IntToString(from = 1, to = "y")
20837    })
20838    public int[] getLocationOnScreen() {
20839        int[] location = new int[2];
20840        getLocationOnScreen(location);
20841        return location;
20842    }
20843
20844    /**
20845     * <p>Computes the coordinates of this view on the screen. The argument
20846     * must be an array of two integers. After the method returns, the array
20847     * contains the x and y location in that order.</p>
20848     *
20849     * @param outLocation an array of two integers in which to hold the coordinates
20850     */
20851    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20852        getLocationInWindow(outLocation);
20853
20854        final AttachInfo info = mAttachInfo;
20855        if (info != null) {
20856            outLocation[0] += info.mWindowLeft;
20857            outLocation[1] += info.mWindowTop;
20858        }
20859    }
20860
20861    /**
20862     * <p>Computes the coordinates of this view in its window. The argument
20863     * must be an array of two integers. After the method returns, the array
20864     * contains the x and y location in that order.</p>
20865     *
20866     * @param outLocation an array of two integers in which to hold the coordinates
20867     */
20868    public void getLocationInWindow(@Size(2) int[] outLocation) {
20869        if (outLocation == null || outLocation.length < 2) {
20870            throw new IllegalArgumentException("outLocation must be an array of two integers");
20871        }
20872
20873        outLocation[0] = 0;
20874        outLocation[1] = 0;
20875
20876        transformFromViewToWindowSpace(outLocation);
20877    }
20878
20879    /** @hide */
20880    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20881        if (inOutLocation == null || inOutLocation.length < 2) {
20882            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20883        }
20884
20885        if (mAttachInfo == null) {
20886            // When the view is not attached to a window, this method does not make sense
20887            inOutLocation[0] = inOutLocation[1] = 0;
20888            return;
20889        }
20890
20891        float position[] = mAttachInfo.mTmpTransformLocation;
20892        position[0] = inOutLocation[0];
20893        position[1] = inOutLocation[1];
20894
20895        if (!hasIdentityMatrix()) {
20896            getMatrix().mapPoints(position);
20897        }
20898
20899        position[0] += mLeft;
20900        position[1] += mTop;
20901
20902        ViewParent viewParent = mParent;
20903        while (viewParent instanceof View) {
20904            final View view = (View) viewParent;
20905
20906            position[0] -= view.mScrollX;
20907            position[1] -= view.mScrollY;
20908
20909            if (!view.hasIdentityMatrix()) {
20910                view.getMatrix().mapPoints(position);
20911            }
20912
20913            position[0] += view.mLeft;
20914            position[1] += view.mTop;
20915
20916            viewParent = view.mParent;
20917         }
20918
20919        if (viewParent instanceof ViewRootImpl) {
20920            // *cough*
20921            final ViewRootImpl vr = (ViewRootImpl) viewParent;
20922            position[1] -= vr.mCurScrollY;
20923        }
20924
20925        inOutLocation[0] = Math.round(position[0]);
20926        inOutLocation[1] = Math.round(position[1]);
20927    }
20928
20929    /**
20930     * @param id the id of the view to be found
20931     * @return the view of the specified id, null if cannot be found
20932     * @hide
20933     */
20934    protected <T extends View> T findViewTraversal(@IdRes int id) {
20935        if (id == mID) {
20936            return (T) this;
20937        }
20938        return null;
20939    }
20940
20941    /**
20942     * @param tag the tag of the view to be found
20943     * @return the view of specified tag, null if cannot be found
20944     * @hide
20945     */
20946    protected <T extends View> T findViewWithTagTraversal(Object tag) {
20947        if (tag != null && tag.equals(mTag)) {
20948            return (T) this;
20949        }
20950        return null;
20951    }
20952
20953    /**
20954     * @param predicate The predicate to evaluate.
20955     * @param childToSkip If not null, ignores this child during the recursive traversal.
20956     * @return The first view that matches the predicate or null.
20957     * @hide
20958     */
20959    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
20960            View childToSkip) {
20961        if (predicate.test(this)) {
20962            return (T) this;
20963        }
20964        return null;
20965    }
20966
20967    /**
20968     * Finds the first descendant view with the given ID, the view itself if
20969     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
20970     * (< 0) or there is no matching view in the hierarchy.
20971     * <p>
20972     * <strong>Note:</strong> In most cases -- depending on compiler support --
20973     * the resulting view is automatically cast to the target class type. If
20974     * the target class type is unconstrained, an explicit cast may be
20975     * necessary.
20976     *
20977     * @param id the ID to search for
20978     * @return a view with given ID if found, or {@code null} otherwise
20979     * @see View#findViewById(int)
20980     */
20981    @Nullable
20982    public final <T extends View> T findViewById(@IdRes int id) {
20983        if (id < 0) {
20984            return null;
20985        }
20986        return findViewTraversal(id);
20987    }
20988
20989    /**
20990     * Finds a view by its unuque and stable accessibility id.
20991     *
20992     * @param accessibilityId The searched accessibility id.
20993     * @return The found view.
20994     */
20995    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
20996        if (accessibilityId < 0) {
20997            return null;
20998        }
20999        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21000        if (view != null) {
21001            return view.includeForAccessibility() ? view : null;
21002        }
21003        return null;
21004    }
21005
21006    /**
21007     * Performs the traversal to find a view by its unuque and stable accessibility id.
21008     *
21009     * <strong>Note:</strong>This method does not stop at the root namespace
21010     * boundary since the user can touch the screen at an arbitrary location
21011     * potentially crossing the root namespace bounday which will send an
21012     * accessibility event to accessibility services and they should be able
21013     * to obtain the event source. Also accessibility ids are guaranteed to be
21014     * unique in the window.
21015     *
21016     * @param accessibilityId The accessibility id.
21017     * @return The found view.
21018     * @hide
21019     */
21020    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21021        if (getAccessibilityViewId() == accessibilityId) {
21022            return (T) this;
21023        }
21024        return null;
21025    }
21026
21027    /**
21028     * Look for a child view with the given tag.  If this view has the given
21029     * tag, return this view.
21030     *
21031     * @param tag The tag to search for, using "tag.equals(getTag())".
21032     * @return The View that has the given tag in the hierarchy or null
21033     */
21034    public final <T extends View> T findViewWithTag(Object tag) {
21035        if (tag == null) {
21036            return null;
21037        }
21038        return findViewWithTagTraversal(tag);
21039    }
21040
21041    /**
21042     * Look for a child view that matches the specified predicate.
21043     * If this view matches the predicate, return this view.
21044     *
21045     * @param predicate The predicate to evaluate.
21046     * @return The first view that matches the predicate or null.
21047     * @hide
21048     */
21049    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21050        return findViewByPredicateTraversal(predicate, null);
21051    }
21052
21053    /**
21054     * Look for a child view that matches the specified predicate,
21055     * starting with the specified view and its descendents and then
21056     * recusively searching the ancestors and siblings of that view
21057     * until this view is reached.
21058     *
21059     * This method is useful in cases where the predicate does not match
21060     * a single unique view (perhaps multiple views use the same id)
21061     * and we are trying to find the view that is "closest" in scope to the
21062     * starting view.
21063     *
21064     * @param start The view to start from.
21065     * @param predicate The predicate to evaluate.
21066     * @return The first view that matches the predicate or null.
21067     * @hide
21068     */
21069    public final <T extends View> T findViewByPredicateInsideOut(
21070            View start, Predicate<View> predicate) {
21071        View childToSkip = null;
21072        for (;;) {
21073            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21074            if (view != null || start == this) {
21075                return view;
21076            }
21077
21078            ViewParent parent = start.getParent();
21079            if (parent == null || !(parent instanceof View)) {
21080                return null;
21081            }
21082
21083            childToSkip = start;
21084            start = (View) parent;
21085        }
21086    }
21087
21088    /**
21089     * Sets the identifier for this view. The identifier does not have to be
21090     * unique in this view's hierarchy. The identifier should be a positive
21091     * number.
21092     *
21093     * @see #NO_ID
21094     * @see #getId()
21095     * @see #findViewById(int)
21096     *
21097     * @param id a number used to identify the view
21098     *
21099     * @attr ref android.R.styleable#View_id
21100     */
21101    public void setId(@IdRes int id) {
21102        mID = id;
21103        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21104            mID = generateViewId();
21105        }
21106    }
21107
21108    /**
21109     * {@hide}
21110     *
21111     * @param isRoot true if the view belongs to the root namespace, false
21112     *        otherwise
21113     */
21114    public void setIsRootNamespace(boolean isRoot) {
21115        if (isRoot) {
21116            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21117        } else {
21118            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21119        }
21120    }
21121
21122    /**
21123     * {@hide}
21124     *
21125     * @return true if the view belongs to the root namespace, false otherwise
21126     */
21127    public boolean isRootNamespace() {
21128        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21129    }
21130
21131    /**
21132     * Returns this view's identifier.
21133     *
21134     * @return a positive integer used to identify the view or {@link #NO_ID}
21135     *         if the view has no ID
21136     *
21137     * @see #setId(int)
21138     * @see #findViewById(int)
21139     * @attr ref android.R.styleable#View_id
21140     */
21141    @IdRes
21142    @ViewDebug.CapturedViewProperty
21143    public int getId() {
21144        return mID;
21145    }
21146
21147    /**
21148     * Returns this view's tag.
21149     *
21150     * @return the Object stored in this view as a tag, or {@code null} if not
21151     *         set
21152     *
21153     * @see #setTag(Object)
21154     * @see #getTag(int)
21155     */
21156    @ViewDebug.ExportedProperty
21157    public Object getTag() {
21158        return mTag;
21159    }
21160
21161    /**
21162     * Sets the tag associated with this view. A tag can be used to mark
21163     * a view in its hierarchy and does not have to be unique within the
21164     * hierarchy. Tags can also be used to store data within a view without
21165     * resorting to another data structure.
21166     *
21167     * @param tag an Object to tag the view with
21168     *
21169     * @see #getTag()
21170     * @see #setTag(int, Object)
21171     */
21172    public void setTag(final Object tag) {
21173        mTag = tag;
21174    }
21175
21176    /**
21177     * Returns the tag associated with this view and the specified key.
21178     *
21179     * @param key The key identifying the tag
21180     *
21181     * @return the Object stored in this view as a tag, or {@code null} if not
21182     *         set
21183     *
21184     * @see #setTag(int, Object)
21185     * @see #getTag()
21186     */
21187    public Object getTag(int key) {
21188        if (mKeyedTags != null) return mKeyedTags.get(key);
21189        return null;
21190    }
21191
21192    /**
21193     * Sets a tag associated with this view and a key. A tag can be used
21194     * to mark a view in its hierarchy and does not have to be unique within
21195     * the hierarchy. Tags can also be used to store data within a view
21196     * without resorting to another data structure.
21197     *
21198     * The specified key should be an id declared in the resources of the
21199     * application to ensure it is unique (see the <a
21200     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21201     * Keys identified as belonging to
21202     * the Android framework or not associated with any package will cause
21203     * an {@link IllegalArgumentException} to be thrown.
21204     *
21205     * @param key The key identifying the tag
21206     * @param tag An Object to tag the view with
21207     *
21208     * @throws IllegalArgumentException If they specified key is not valid
21209     *
21210     * @see #setTag(Object)
21211     * @see #getTag(int)
21212     */
21213    public void setTag(int key, final Object tag) {
21214        // If the package id is 0x00 or 0x01, it's either an undefined package
21215        // or a framework id
21216        if ((key >>> 24) < 2) {
21217            throw new IllegalArgumentException("The key must be an application-specific "
21218                    + "resource id.");
21219        }
21220
21221        setKeyedTag(key, tag);
21222    }
21223
21224    /**
21225     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21226     * framework id.
21227     *
21228     * @hide
21229     */
21230    public void setTagInternal(int key, Object tag) {
21231        if ((key >>> 24) != 0x1) {
21232            throw new IllegalArgumentException("The key must be a framework-specific "
21233                    + "resource id.");
21234        }
21235
21236        setKeyedTag(key, tag);
21237    }
21238
21239    private void setKeyedTag(int key, Object tag) {
21240        if (mKeyedTags == null) {
21241            mKeyedTags = new SparseArray<Object>(2);
21242        }
21243
21244        mKeyedTags.put(key, tag);
21245    }
21246
21247    /**
21248     * Prints information about this view in the log output, with the tag
21249     * {@link #VIEW_LOG_TAG}.
21250     *
21251     * @hide
21252     */
21253    public void debug() {
21254        debug(0);
21255    }
21256
21257    /**
21258     * Prints information about this view in the log output, with the tag
21259     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21260     * indentation defined by the <code>depth</code>.
21261     *
21262     * @param depth the indentation level
21263     *
21264     * @hide
21265     */
21266    protected void debug(int depth) {
21267        String output = debugIndent(depth - 1);
21268
21269        output += "+ " + this;
21270        int id = getId();
21271        if (id != -1) {
21272            output += " (id=" + id + ")";
21273        }
21274        Object tag = getTag();
21275        if (tag != null) {
21276            output += " (tag=" + tag + ")";
21277        }
21278        Log.d(VIEW_LOG_TAG, output);
21279
21280        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21281            output = debugIndent(depth) + " FOCUSED";
21282            Log.d(VIEW_LOG_TAG, output);
21283        }
21284
21285        output = debugIndent(depth);
21286        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21287                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21288                + "} ";
21289        Log.d(VIEW_LOG_TAG, output);
21290
21291        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21292                || mPaddingBottom != 0) {
21293            output = debugIndent(depth);
21294            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21295                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21296            Log.d(VIEW_LOG_TAG, output);
21297        }
21298
21299        output = debugIndent(depth);
21300        output += "mMeasureWidth=" + mMeasuredWidth +
21301                " mMeasureHeight=" + mMeasuredHeight;
21302        Log.d(VIEW_LOG_TAG, output);
21303
21304        output = debugIndent(depth);
21305        if (mLayoutParams == null) {
21306            output += "BAD! no layout params";
21307        } else {
21308            output = mLayoutParams.debug(output);
21309        }
21310        Log.d(VIEW_LOG_TAG, output);
21311
21312        output = debugIndent(depth);
21313        output += "flags={";
21314        output += View.printFlags(mViewFlags);
21315        output += "}";
21316        Log.d(VIEW_LOG_TAG, output);
21317
21318        output = debugIndent(depth);
21319        output += "privateFlags={";
21320        output += View.printPrivateFlags(mPrivateFlags);
21321        output += "}";
21322        Log.d(VIEW_LOG_TAG, output);
21323    }
21324
21325    /**
21326     * Creates a string of whitespaces used for indentation.
21327     *
21328     * @param depth the indentation level
21329     * @return a String containing (depth * 2 + 3) * 2 white spaces
21330     *
21331     * @hide
21332     */
21333    protected static String debugIndent(int depth) {
21334        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21335        for (int i = 0; i < (depth * 2) + 3; i++) {
21336            spaces.append(' ').append(' ');
21337        }
21338        return spaces.toString();
21339    }
21340
21341    /**
21342     * <p>Return the offset of the widget's text baseline from the widget's top
21343     * boundary. If this widget does not support baseline alignment, this
21344     * method returns -1. </p>
21345     *
21346     * @return the offset of the baseline within the widget's bounds or -1
21347     *         if baseline alignment is not supported
21348     */
21349    @ViewDebug.ExportedProperty(category = "layout")
21350    public int getBaseline() {
21351        return -1;
21352    }
21353
21354    /**
21355     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21356     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21357     * a layout pass.
21358     *
21359     * @return whether the view hierarchy is currently undergoing a layout pass
21360     */
21361    public boolean isInLayout() {
21362        ViewRootImpl viewRoot = getViewRootImpl();
21363        return (viewRoot != null && viewRoot.isInLayout());
21364    }
21365
21366    /**
21367     * Call this when something has changed which has invalidated the
21368     * layout of this view. This will schedule a layout pass of the view
21369     * tree. This should not be called while the view hierarchy is currently in a layout
21370     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21371     * end of the current layout pass (and then layout will run again) or after the current
21372     * frame is drawn and the next layout occurs.
21373     *
21374     * <p>Subclasses which override this method should call the superclass method to
21375     * handle possible request-during-layout errors correctly.</p>
21376     */
21377    @CallSuper
21378    public void requestLayout() {
21379        if (mMeasureCache != null) mMeasureCache.clear();
21380
21381        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21382            // Only trigger request-during-layout logic if this is the view requesting it,
21383            // not the views in its parent hierarchy
21384            ViewRootImpl viewRoot = getViewRootImpl();
21385            if (viewRoot != null && viewRoot.isInLayout()) {
21386                if (!viewRoot.requestLayoutDuringLayout(this)) {
21387                    return;
21388                }
21389            }
21390            mAttachInfo.mViewRequestingLayout = this;
21391        }
21392
21393        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21394        mPrivateFlags |= PFLAG_INVALIDATED;
21395
21396        if (mParent != null && !mParent.isLayoutRequested()) {
21397            mParent.requestLayout();
21398        }
21399        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21400            mAttachInfo.mViewRequestingLayout = null;
21401        }
21402    }
21403
21404    /**
21405     * Forces this view to be laid out during the next layout pass.
21406     * This method does not call requestLayout() or forceLayout()
21407     * on the parent.
21408     */
21409    public void forceLayout() {
21410        if (mMeasureCache != null) mMeasureCache.clear();
21411
21412        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21413        mPrivateFlags |= PFLAG_INVALIDATED;
21414    }
21415
21416    /**
21417     * <p>
21418     * This is called to find out how big a view should be. The parent
21419     * supplies constraint information in the width and height parameters.
21420     * </p>
21421     *
21422     * <p>
21423     * The actual measurement work of a view is performed in
21424     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21425     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21426     * </p>
21427     *
21428     *
21429     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21430     *        parent
21431     * @param heightMeasureSpec Vertical space requirements as imposed by the
21432     *        parent
21433     *
21434     * @see #onMeasure(int, int)
21435     */
21436    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21437        boolean optical = isLayoutModeOptical(this);
21438        if (optical != isLayoutModeOptical(mParent)) {
21439            Insets insets = getOpticalInsets();
21440            int oWidth  = insets.left + insets.right;
21441            int oHeight = insets.top  + insets.bottom;
21442            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21443            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21444        }
21445
21446        // Suppress sign extension for the low bytes
21447        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21448        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21449
21450        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21451
21452        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21453        // already measured as the correct size. In API 23 and below, this
21454        // extra pass is required to make LinearLayout re-distribute weight.
21455        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21456                || heightMeasureSpec != mOldHeightMeasureSpec;
21457        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21458                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21459        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21460                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21461        final boolean needsLayout = specChanged
21462                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21463
21464        if (forceLayout || needsLayout) {
21465            // first clears the measured dimension flag
21466            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21467
21468            resolveRtlPropertiesIfNeeded();
21469
21470            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21471            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21472                // measure ourselves, this should set the measured dimension flag back
21473                onMeasure(widthMeasureSpec, heightMeasureSpec);
21474                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21475            } else {
21476                long value = mMeasureCache.valueAt(cacheIndex);
21477                // Casting a long to int drops the high 32 bits, no mask needed
21478                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21479                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21480            }
21481
21482            // flag not set, setMeasuredDimension() was not invoked, we raise
21483            // an exception to warn the developer
21484            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21485                throw new IllegalStateException("View with id " + getId() + ": "
21486                        + getClass().getName() + "#onMeasure() did not set the"
21487                        + " measured dimension by calling"
21488                        + " setMeasuredDimension()");
21489            }
21490
21491            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21492        }
21493
21494        mOldWidthMeasureSpec = widthMeasureSpec;
21495        mOldHeightMeasureSpec = heightMeasureSpec;
21496
21497        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21498                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21499    }
21500
21501    /**
21502     * <p>
21503     * Measure the view and its content to determine the measured width and the
21504     * measured height. This method is invoked by {@link #measure(int, int)} and
21505     * should be overridden by subclasses to provide accurate and efficient
21506     * measurement of their contents.
21507     * </p>
21508     *
21509     * <p>
21510     * <strong>CONTRACT:</strong> When overriding this method, you
21511     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21512     * measured width and height of this view. Failure to do so will trigger an
21513     * <code>IllegalStateException</code>, thrown by
21514     * {@link #measure(int, int)}. Calling the superclass'
21515     * {@link #onMeasure(int, int)} is a valid use.
21516     * </p>
21517     *
21518     * <p>
21519     * The base class implementation of measure defaults to the background size,
21520     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21521     * override {@link #onMeasure(int, int)} to provide better measurements of
21522     * their content.
21523     * </p>
21524     *
21525     * <p>
21526     * If this method is overridden, it is the subclass's responsibility to make
21527     * sure the measured height and width are at least the view's minimum height
21528     * and width ({@link #getSuggestedMinimumHeight()} and
21529     * {@link #getSuggestedMinimumWidth()}).
21530     * </p>
21531     *
21532     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21533     *                         The requirements are encoded with
21534     *                         {@link android.view.View.MeasureSpec}.
21535     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21536     *                         The requirements are encoded with
21537     *                         {@link android.view.View.MeasureSpec}.
21538     *
21539     * @see #getMeasuredWidth()
21540     * @see #getMeasuredHeight()
21541     * @see #setMeasuredDimension(int, int)
21542     * @see #getSuggestedMinimumHeight()
21543     * @see #getSuggestedMinimumWidth()
21544     * @see android.view.View.MeasureSpec#getMode(int)
21545     * @see android.view.View.MeasureSpec#getSize(int)
21546     */
21547    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21548        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21549                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21550    }
21551
21552    /**
21553     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21554     * measured width and measured height. Failing to do so will trigger an
21555     * exception at measurement time.</p>
21556     *
21557     * @param measuredWidth The measured width of this view.  May be a complex
21558     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21559     * {@link #MEASURED_STATE_TOO_SMALL}.
21560     * @param measuredHeight The measured height of this view.  May be a complex
21561     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21562     * {@link #MEASURED_STATE_TOO_SMALL}.
21563     */
21564    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21565        boolean optical = isLayoutModeOptical(this);
21566        if (optical != isLayoutModeOptical(mParent)) {
21567            Insets insets = getOpticalInsets();
21568            int opticalWidth  = insets.left + insets.right;
21569            int opticalHeight = insets.top  + insets.bottom;
21570
21571            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21572            measuredHeight += optical ? opticalHeight : -opticalHeight;
21573        }
21574        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21575    }
21576
21577    /**
21578     * Sets the measured dimension without extra processing for things like optical bounds.
21579     * Useful for reapplying consistent values that have already been cooked with adjustments
21580     * for optical bounds, etc. such as those from the measurement cache.
21581     *
21582     * @param measuredWidth The measured width of this view.  May be a complex
21583     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21584     * {@link #MEASURED_STATE_TOO_SMALL}.
21585     * @param measuredHeight The measured height of this view.  May be a complex
21586     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21587     * {@link #MEASURED_STATE_TOO_SMALL}.
21588     */
21589    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21590        mMeasuredWidth = measuredWidth;
21591        mMeasuredHeight = measuredHeight;
21592
21593        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21594    }
21595
21596    /**
21597     * Merge two states as returned by {@link #getMeasuredState()}.
21598     * @param curState The current state as returned from a view or the result
21599     * of combining multiple views.
21600     * @param newState The new view state to combine.
21601     * @return Returns a new integer reflecting the combination of the two
21602     * states.
21603     */
21604    public static int combineMeasuredStates(int curState, int newState) {
21605        return curState | newState;
21606    }
21607
21608    /**
21609     * Version of {@link #resolveSizeAndState(int, int, int)}
21610     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21611     */
21612    public static int resolveSize(int size, int measureSpec) {
21613        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21614    }
21615
21616    /**
21617     * Utility to reconcile a desired size and state, with constraints imposed
21618     * by a MeasureSpec. Will take the desired size, unless a different size
21619     * is imposed by the constraints. The returned value is a compound integer,
21620     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21621     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21622     * resulting size is smaller than the size the view wants to be.
21623     *
21624     * @param size How big the view wants to be.
21625     * @param measureSpec Constraints imposed by the parent.
21626     * @param childMeasuredState Size information bit mask for the view's
21627     *                           children.
21628     * @return Size information bit mask as defined by
21629     *         {@link #MEASURED_SIZE_MASK} and
21630     *         {@link #MEASURED_STATE_TOO_SMALL}.
21631     */
21632    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21633        final int specMode = MeasureSpec.getMode(measureSpec);
21634        final int specSize = MeasureSpec.getSize(measureSpec);
21635        final int result;
21636        switch (specMode) {
21637            case MeasureSpec.AT_MOST:
21638                if (specSize < size) {
21639                    result = specSize | MEASURED_STATE_TOO_SMALL;
21640                } else {
21641                    result = size;
21642                }
21643                break;
21644            case MeasureSpec.EXACTLY:
21645                result = specSize;
21646                break;
21647            case MeasureSpec.UNSPECIFIED:
21648            default:
21649                result = size;
21650        }
21651        return result | (childMeasuredState & MEASURED_STATE_MASK);
21652    }
21653
21654    /**
21655     * Utility to return a default size. Uses the supplied size if the
21656     * MeasureSpec imposed no constraints. Will get larger if allowed
21657     * by the MeasureSpec.
21658     *
21659     * @param size Default size for this view
21660     * @param measureSpec Constraints imposed by the parent
21661     * @return The size this view should be.
21662     */
21663    public static int getDefaultSize(int size, int measureSpec) {
21664        int result = size;
21665        int specMode = MeasureSpec.getMode(measureSpec);
21666        int specSize = MeasureSpec.getSize(measureSpec);
21667
21668        switch (specMode) {
21669        case MeasureSpec.UNSPECIFIED:
21670            result = size;
21671            break;
21672        case MeasureSpec.AT_MOST:
21673        case MeasureSpec.EXACTLY:
21674            result = specSize;
21675            break;
21676        }
21677        return result;
21678    }
21679
21680    /**
21681     * Returns the suggested minimum height that the view should use. This
21682     * returns the maximum of the view's minimum height
21683     * and the background's minimum height
21684     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21685     * <p>
21686     * When being used in {@link #onMeasure(int, int)}, the caller should still
21687     * ensure the returned height is within the requirements of the parent.
21688     *
21689     * @return The suggested minimum height of the view.
21690     */
21691    protected int getSuggestedMinimumHeight() {
21692        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21693
21694    }
21695
21696    /**
21697     * Returns the suggested minimum width that the view should use. This
21698     * returns the maximum of the view's minimum width
21699     * and the background's minimum width
21700     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21701     * <p>
21702     * When being used in {@link #onMeasure(int, int)}, the caller should still
21703     * ensure the returned width is within the requirements of the parent.
21704     *
21705     * @return The suggested minimum width of the view.
21706     */
21707    protected int getSuggestedMinimumWidth() {
21708        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21709    }
21710
21711    /**
21712     * Returns the minimum height of the view.
21713     *
21714     * @return the minimum height the view will try to be, in pixels
21715     *
21716     * @see #setMinimumHeight(int)
21717     *
21718     * @attr ref android.R.styleable#View_minHeight
21719     */
21720    public int getMinimumHeight() {
21721        return mMinHeight;
21722    }
21723
21724    /**
21725     * Sets the minimum height of the view. It is not guaranteed the view will
21726     * be able to achieve this minimum height (for example, if its parent layout
21727     * constrains it with less available height).
21728     *
21729     * @param minHeight The minimum height the view will try to be, in pixels
21730     *
21731     * @see #getMinimumHeight()
21732     *
21733     * @attr ref android.R.styleable#View_minHeight
21734     */
21735    @RemotableViewMethod
21736    public void setMinimumHeight(int minHeight) {
21737        mMinHeight = minHeight;
21738        requestLayout();
21739    }
21740
21741    /**
21742     * Returns the minimum width of the view.
21743     *
21744     * @return the minimum width the view will try to be, in pixels
21745     *
21746     * @see #setMinimumWidth(int)
21747     *
21748     * @attr ref android.R.styleable#View_minWidth
21749     */
21750    public int getMinimumWidth() {
21751        return mMinWidth;
21752    }
21753
21754    /**
21755     * Sets the minimum width of the view. It is not guaranteed the view will
21756     * be able to achieve this minimum width (for example, if its parent layout
21757     * constrains it with less available width).
21758     *
21759     * @param minWidth The minimum width the view will try to be, in pixels
21760     *
21761     * @see #getMinimumWidth()
21762     *
21763     * @attr ref android.R.styleable#View_minWidth
21764     */
21765    public void setMinimumWidth(int minWidth) {
21766        mMinWidth = minWidth;
21767        requestLayout();
21768
21769    }
21770
21771    /**
21772     * Get the animation currently associated with this view.
21773     *
21774     * @return The animation that is currently playing or
21775     *         scheduled to play for this view.
21776     */
21777    public Animation getAnimation() {
21778        return mCurrentAnimation;
21779    }
21780
21781    /**
21782     * Start the specified animation now.
21783     *
21784     * @param animation the animation to start now
21785     */
21786    public void startAnimation(Animation animation) {
21787        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21788        setAnimation(animation);
21789        invalidateParentCaches();
21790        invalidate(true);
21791    }
21792
21793    /**
21794     * Cancels any animations for this view.
21795     */
21796    public void clearAnimation() {
21797        if (mCurrentAnimation != null) {
21798            mCurrentAnimation.detach();
21799        }
21800        mCurrentAnimation = null;
21801        invalidateParentIfNeeded();
21802    }
21803
21804    /**
21805     * Sets the next animation to play for this view.
21806     * If you want the animation to play immediately, use
21807     * {@link #startAnimation(android.view.animation.Animation)} instead.
21808     * This method provides allows fine-grained
21809     * control over the start time and invalidation, but you
21810     * must make sure that 1) the animation has a start time set, and
21811     * 2) the view's parent (which controls animations on its children)
21812     * will be invalidated when the animation is supposed to
21813     * start.
21814     *
21815     * @param animation The next animation, or null.
21816     */
21817    public void setAnimation(Animation animation) {
21818        mCurrentAnimation = animation;
21819
21820        if (animation != null) {
21821            // If the screen is off assume the animation start time is now instead of
21822            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21823            // would cause the animation to start when the screen turns back on
21824            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21825                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21826                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21827            }
21828            animation.reset();
21829        }
21830    }
21831
21832    /**
21833     * Invoked by a parent ViewGroup to notify the start of the animation
21834     * currently associated with this view. If you override this method,
21835     * always call super.onAnimationStart();
21836     *
21837     * @see #setAnimation(android.view.animation.Animation)
21838     * @see #getAnimation()
21839     */
21840    @CallSuper
21841    protected void onAnimationStart() {
21842        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21843    }
21844
21845    /**
21846     * Invoked by a parent ViewGroup to notify the end of the animation
21847     * currently associated with this view. If you override this method,
21848     * always call super.onAnimationEnd();
21849     *
21850     * @see #setAnimation(android.view.animation.Animation)
21851     * @see #getAnimation()
21852     */
21853    @CallSuper
21854    protected void onAnimationEnd() {
21855        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21856    }
21857
21858    /**
21859     * Invoked if there is a Transform that involves alpha. Subclass that can
21860     * draw themselves with the specified alpha should return true, and then
21861     * respect that alpha when their onDraw() is called. If this returns false
21862     * then the view may be redirected to draw into an offscreen buffer to
21863     * fulfill the request, which will look fine, but may be slower than if the
21864     * subclass handles it internally. The default implementation returns false.
21865     *
21866     * @param alpha The alpha (0..255) to apply to the view's drawing
21867     * @return true if the view can draw with the specified alpha.
21868     */
21869    protected boolean onSetAlpha(int alpha) {
21870        return false;
21871    }
21872
21873    /**
21874     * This is used by the RootView to perform an optimization when
21875     * the view hierarchy contains one or several SurfaceView.
21876     * SurfaceView is always considered transparent, but its children are not,
21877     * therefore all View objects remove themselves from the global transparent
21878     * region (passed as a parameter to this function).
21879     *
21880     * @param region The transparent region for this ViewAncestor (window).
21881     *
21882     * @return Returns true if the effective visibility of the view at this
21883     * point is opaque, regardless of the transparent region; returns false
21884     * if it is possible for underlying windows to be seen behind the view.
21885     *
21886     * {@hide}
21887     */
21888    public boolean gatherTransparentRegion(Region region) {
21889        final AttachInfo attachInfo = mAttachInfo;
21890        if (region != null && attachInfo != null) {
21891            final int pflags = mPrivateFlags;
21892            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
21893                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
21894                // remove it from the transparent region.
21895                final int[] location = attachInfo.mTransparentLocation;
21896                getLocationInWindow(location);
21897                // When a view has Z value, then it will be better to leave some area below the view
21898                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
21899                // the bottom part needs more offset than the left, top and right parts due to the
21900                // spot light effects.
21901                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
21902                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
21903                        location[0] + mRight - mLeft + shadowOffset,
21904                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
21905            } else {
21906                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
21907                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
21908                    // the background drawable's non-transparent parts from this transparent region.
21909                    applyDrawableToTransparentRegion(mBackground, region);
21910                }
21911                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
21912                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
21913                    // Similarly, we remove the foreground drawable's non-transparent parts.
21914                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
21915                }
21916            }
21917        }
21918        return true;
21919    }
21920
21921    /**
21922     * Play a sound effect for this view.
21923     *
21924     * <p>The framework will play sound effects for some built in actions, such as
21925     * clicking, but you may wish to play these effects in your widget,
21926     * for instance, for internal navigation.
21927     *
21928     * <p>The sound effect will only be played if sound effects are enabled by the user, and
21929     * {@link #isSoundEffectsEnabled()} is true.
21930     *
21931     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
21932     */
21933    public void playSoundEffect(int soundConstant) {
21934        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
21935            return;
21936        }
21937        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
21938    }
21939
21940    /**
21941     * BZZZTT!!1!
21942     *
21943     * <p>Provide haptic feedback to the user for this view.
21944     *
21945     * <p>The framework will provide haptic feedback for some built in actions,
21946     * such as long presses, but you may wish to provide feedback for your
21947     * own widget.
21948     *
21949     * <p>The feedback will only be performed if
21950     * {@link #isHapticFeedbackEnabled()} is true.
21951     *
21952     * @param feedbackConstant One of the constants defined in
21953     * {@link HapticFeedbackConstants}
21954     */
21955    public boolean performHapticFeedback(int feedbackConstant) {
21956        return performHapticFeedback(feedbackConstant, 0);
21957    }
21958
21959    /**
21960     * BZZZTT!!1!
21961     *
21962     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
21963     *
21964     * @param feedbackConstant One of the constants defined in
21965     * {@link HapticFeedbackConstants}
21966     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
21967     */
21968    public boolean performHapticFeedback(int feedbackConstant, int flags) {
21969        if (mAttachInfo == null) {
21970            return false;
21971        }
21972        //noinspection SimplifiableIfStatement
21973        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
21974                && !isHapticFeedbackEnabled()) {
21975            return false;
21976        }
21977        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
21978                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
21979    }
21980
21981    /**
21982     * Request that the visibility of the status bar or other screen/window
21983     * decorations be changed.
21984     *
21985     * <p>This method is used to put the over device UI into temporary modes
21986     * where the user's attention is focused more on the application content,
21987     * by dimming or hiding surrounding system affordances.  This is typically
21988     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
21989     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
21990     * to be placed behind the action bar (and with these flags other system
21991     * affordances) so that smooth transitions between hiding and showing them
21992     * can be done.
21993     *
21994     * <p>Two representative examples of the use of system UI visibility is
21995     * implementing a content browsing application (like a magazine reader)
21996     * and a video playing application.
21997     *
21998     * <p>The first code shows a typical implementation of a View in a content
21999     * browsing application.  In this implementation, the application goes
22000     * into a content-oriented mode by hiding the status bar and action bar,
22001     * and putting the navigation elements into lights out mode.  The user can
22002     * then interact with content while in this mode.  Such an application should
22003     * provide an easy way for the user to toggle out of the mode (such as to
22004     * check information in the status bar or access notifications).  In the
22005     * implementation here, this is done simply by tapping on the content.
22006     *
22007     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22008     *      content}
22009     *
22010     * <p>This second code sample shows a typical implementation of a View
22011     * in a video playing application.  In this situation, while the video is
22012     * playing the application would like to go into a complete full-screen mode,
22013     * to use as much of the display as possible for the video.  When in this state
22014     * the user can not interact with the application; the system intercepts
22015     * touching on the screen to pop the UI out of full screen mode.  See
22016     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22017     *
22018     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22019     *      content}
22020     *
22021     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22022     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22023     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22024     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22025     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22026     */
22027    public void setSystemUiVisibility(int visibility) {
22028        if (visibility != mSystemUiVisibility) {
22029            mSystemUiVisibility = visibility;
22030            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22031                mParent.recomputeViewAttributes(this);
22032            }
22033        }
22034    }
22035
22036    /**
22037     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22038     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22039     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22040     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22041     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22042     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22043     */
22044    public int getSystemUiVisibility() {
22045        return mSystemUiVisibility;
22046    }
22047
22048    /**
22049     * Returns the current system UI visibility that is currently set for
22050     * the entire window.  This is the combination of the
22051     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22052     * views in the window.
22053     */
22054    public int getWindowSystemUiVisibility() {
22055        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22056    }
22057
22058    /**
22059     * Override to find out when the window's requested system UI visibility
22060     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22061     * This is different from the callbacks received through
22062     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22063     * in that this is only telling you about the local request of the window,
22064     * not the actual values applied by the system.
22065     */
22066    public void onWindowSystemUiVisibilityChanged(int visible) {
22067    }
22068
22069    /**
22070     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22071     * the view hierarchy.
22072     */
22073    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22074        onWindowSystemUiVisibilityChanged(visible);
22075    }
22076
22077    /**
22078     * Set a listener to receive callbacks when the visibility of the system bar changes.
22079     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22080     */
22081    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22082        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22083        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22084            mParent.recomputeViewAttributes(this);
22085        }
22086    }
22087
22088    /**
22089     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22090     * the view hierarchy.
22091     */
22092    public void dispatchSystemUiVisibilityChanged(int visibility) {
22093        ListenerInfo li = mListenerInfo;
22094        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22095            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22096                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22097        }
22098    }
22099
22100    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22101        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22102        if (val != mSystemUiVisibility) {
22103            setSystemUiVisibility(val);
22104            return true;
22105        }
22106        return false;
22107    }
22108
22109    /** @hide */
22110    public void setDisabledSystemUiVisibility(int flags) {
22111        if (mAttachInfo != null) {
22112            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22113                mAttachInfo.mDisabledSystemUiVisibility = flags;
22114                if (mParent != null) {
22115                    mParent.recomputeViewAttributes(this);
22116                }
22117            }
22118        }
22119    }
22120
22121    /**
22122     * Creates an image that the system displays during the drag and drop
22123     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22124     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22125     * appearance as the given View. The default also positions the center of the drag shadow
22126     * directly under the touch point. If no View is provided (the constructor with no parameters
22127     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22128     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22129     * default is an invisible drag shadow.
22130     * <p>
22131     * You are not required to use the View you provide to the constructor as the basis of the
22132     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22133     * anything you want as the drag shadow.
22134     * </p>
22135     * <p>
22136     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22137     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22138     *  size and position of the drag shadow. It uses this data to construct a
22139     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22140     *  so that your application can draw the shadow image in the Canvas.
22141     * </p>
22142     *
22143     * <div class="special reference">
22144     * <h3>Developer Guides</h3>
22145     * <p>For a guide to implementing drag and drop features, read the
22146     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22147     * </div>
22148     */
22149    public static class DragShadowBuilder {
22150        private final WeakReference<View> mView;
22151
22152        /**
22153         * Constructs a shadow image builder based on a View. By default, the resulting drag
22154         * shadow will have the same appearance and dimensions as the View, with the touch point
22155         * over the center of the View.
22156         * @param view A View. Any View in scope can be used.
22157         */
22158        public DragShadowBuilder(View view) {
22159            mView = new WeakReference<View>(view);
22160        }
22161
22162        /**
22163         * Construct a shadow builder object with no associated View.  This
22164         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22165         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22166         * to supply the drag shadow's dimensions and appearance without
22167         * reference to any View object. If they are not overridden, then the result is an
22168         * invisible drag shadow.
22169         */
22170        public DragShadowBuilder() {
22171            mView = new WeakReference<View>(null);
22172        }
22173
22174        /**
22175         * Returns the View object that had been passed to the
22176         * {@link #View.DragShadowBuilder(View)}
22177         * constructor.  If that View parameter was {@code null} or if the
22178         * {@link #View.DragShadowBuilder()}
22179         * constructor was used to instantiate the builder object, this method will return
22180         * null.
22181         *
22182         * @return The View object associate with this builder object.
22183         */
22184        @SuppressWarnings({"JavadocReference"})
22185        final public View getView() {
22186            return mView.get();
22187        }
22188
22189        /**
22190         * Provides the metrics for the shadow image. These include the dimensions of
22191         * the shadow image, and the point within that shadow that should
22192         * be centered under the touch location while dragging.
22193         * <p>
22194         * The default implementation sets the dimensions of the shadow to be the
22195         * same as the dimensions of the View itself and centers the shadow under
22196         * the touch point.
22197         * </p>
22198         *
22199         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22200         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22201         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22202         * image.
22203         *
22204         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22205         * shadow image that should be underneath the touch point during the drag and drop
22206         * operation. Your application must set {@link android.graphics.Point#x} to the
22207         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22208         */
22209        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22210            final View view = mView.get();
22211            if (view != null) {
22212                outShadowSize.set(view.getWidth(), view.getHeight());
22213                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22214            } else {
22215                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22216            }
22217        }
22218
22219        /**
22220         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22221         * based on the dimensions it received from the
22222         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22223         *
22224         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22225         */
22226        public void onDrawShadow(Canvas canvas) {
22227            final View view = mView.get();
22228            if (view != null) {
22229                view.draw(canvas);
22230            } else {
22231                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22232            }
22233        }
22234    }
22235
22236    /**
22237     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22238     * startDragAndDrop()} for newer platform versions.
22239     */
22240    @Deprecated
22241    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22242                                   Object myLocalState, int flags) {
22243        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22244    }
22245
22246    /**
22247     * Starts a drag and drop operation. When your application calls this method, it passes a
22248     * {@link android.view.View.DragShadowBuilder} object to the system. The
22249     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22250     * to get metrics for the drag shadow, and then calls the object's
22251     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22252     * <p>
22253     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22254     *  drag events to all the View objects in your application that are currently visible. It does
22255     *  this either by calling the View object's drag listener (an implementation of
22256     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22257     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22258     *  Both are passed a {@link android.view.DragEvent} object that has a
22259     *  {@link android.view.DragEvent#getAction()} value of
22260     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22261     * </p>
22262     * <p>
22263     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22264     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22265     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22266     * to the View the user selected for dragging.
22267     * </p>
22268     * @param data A {@link android.content.ClipData} object pointing to the data to be
22269     * transferred by the drag and drop operation.
22270     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22271     * drag shadow.
22272     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22273     * drop operation. When dispatching drag events to views in the same activity this object
22274     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22275     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22276     * will return null).
22277     * <p>
22278     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22279     * to the target Views. For example, it can contain flags that differentiate between a
22280     * a copy operation and a move operation.
22281     * </p>
22282     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22283     * flags, or any combination of the following:
22284     *     <ul>
22285     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22286     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22287     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22288     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22289     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22290     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22291     *     </ul>
22292     * @return {@code true} if the method completes successfully, or
22293     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22294     * do a drag, and so no drag operation is in progress.
22295     */
22296    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22297            Object myLocalState, int flags) {
22298        if (ViewDebug.DEBUG_DRAG) {
22299            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22300        }
22301        if (mAttachInfo == null) {
22302            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22303            return false;
22304        }
22305
22306        if (data != null) {
22307            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22308        }
22309
22310        boolean okay = false;
22311
22312        Point shadowSize = new Point();
22313        Point shadowTouchPoint = new Point();
22314        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22315
22316        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22317                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22318            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22319        }
22320
22321        if (ViewDebug.DEBUG_DRAG) {
22322            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22323                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22324        }
22325        if (mAttachInfo.mDragSurface != null) {
22326            mAttachInfo.mDragSurface.release();
22327        }
22328        mAttachInfo.mDragSurface = new Surface();
22329        try {
22330            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22331                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22332            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22333                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22334            if (mAttachInfo.mDragToken != null) {
22335                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22336                try {
22337                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22338                    shadowBuilder.onDrawShadow(canvas);
22339                } finally {
22340                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22341                }
22342
22343                final ViewRootImpl root = getViewRootImpl();
22344
22345                // Cache the local state object for delivery with DragEvents
22346                root.setLocalDragState(myLocalState);
22347
22348                // repurpose 'shadowSize' for the last touch point
22349                root.getLastTouchPoint(shadowSize);
22350
22351                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22352                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22353                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22354                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22355            }
22356        } catch (Exception e) {
22357            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22358            mAttachInfo.mDragSurface.destroy();
22359            mAttachInfo.mDragSurface = null;
22360        }
22361
22362        return okay;
22363    }
22364
22365    /**
22366     * Cancels an ongoing drag and drop operation.
22367     * <p>
22368     * A {@link android.view.DragEvent} object with
22369     * {@link android.view.DragEvent#getAction()} value of
22370     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22371     * {@link android.view.DragEvent#getResult()} value of {@code false}
22372     * will be sent to every
22373     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22374     * even if they are not currently visible.
22375     * </p>
22376     * <p>
22377     * This method can be called on any View in the same window as the View on which
22378     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22379     * was called.
22380     * </p>
22381     */
22382    public final void cancelDragAndDrop() {
22383        if (ViewDebug.DEBUG_DRAG) {
22384            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22385        }
22386        if (mAttachInfo == null) {
22387            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22388            return;
22389        }
22390        if (mAttachInfo.mDragToken != null) {
22391            try {
22392                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22393            } catch (Exception e) {
22394                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22395            }
22396            mAttachInfo.mDragToken = null;
22397        } else {
22398            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22399        }
22400    }
22401
22402    /**
22403     * Updates the drag shadow for the ongoing drag and drop operation.
22404     *
22405     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22406     * new drag shadow.
22407     */
22408    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22409        if (ViewDebug.DEBUG_DRAG) {
22410            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22411        }
22412        if (mAttachInfo == null) {
22413            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22414            return;
22415        }
22416        if (mAttachInfo.mDragToken != null) {
22417            try {
22418                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22419                try {
22420                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22421                    shadowBuilder.onDrawShadow(canvas);
22422                } finally {
22423                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22424                }
22425            } catch (Exception e) {
22426                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22427            }
22428        } else {
22429            Log.e(VIEW_LOG_TAG, "No active drag");
22430        }
22431    }
22432
22433    /**
22434     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22435     * between {startX, startY} and the new cursor positon.
22436     * @param startX horizontal coordinate where the move started.
22437     * @param startY vertical coordinate where the move started.
22438     * @return whether moving was started successfully.
22439     * @hide
22440     */
22441    public final boolean startMovingTask(float startX, float startY) {
22442        if (ViewDebug.DEBUG_POSITIONING) {
22443            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22444        }
22445        try {
22446            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22447        } catch (RemoteException e) {
22448            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22449        }
22450        return false;
22451    }
22452
22453    /**
22454     * Handles drag events sent by the system following a call to
22455     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22456     * startDragAndDrop()}.
22457     *<p>
22458     * When the system calls this method, it passes a
22459     * {@link android.view.DragEvent} object. A call to
22460     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22461     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22462     * operation.
22463     * @param event The {@link android.view.DragEvent} sent by the system.
22464     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22465     * in DragEvent, indicating the type of drag event represented by this object.
22466     * @return {@code true} if the method was successful, otherwise {@code false}.
22467     * <p>
22468     *  The method should return {@code true} in response to an action type of
22469     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22470     *  operation.
22471     * </p>
22472     * <p>
22473     *  The method should also return {@code true} in response to an action type of
22474     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22475     *  {@code false} if it didn't.
22476     * </p>
22477     * <p>
22478     *  For all other events, the return value is ignored.
22479     * </p>
22480     */
22481    public boolean onDragEvent(DragEvent event) {
22482        return false;
22483    }
22484
22485    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22486    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22487        return callDragEventHandler(event);
22488    }
22489
22490    /**
22491     * Detects if this View is enabled and has a drag event listener.
22492     * If both are true, then it calls the drag event listener with the
22493     * {@link android.view.DragEvent} it received. If the drag event listener returns
22494     * {@code true}, then dispatchDragEvent() returns {@code true}.
22495     * <p>
22496     * For all other cases, the method calls the
22497     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22498     * method and returns its result.
22499     * </p>
22500     * <p>
22501     * This ensures that a drag event is always consumed, even if the View does not have a drag
22502     * event listener. However, if the View has a listener and the listener returns true, then
22503     * onDragEvent() is not called.
22504     * </p>
22505     */
22506    public boolean dispatchDragEvent(DragEvent event) {
22507        event.mEventHandlerWasCalled = true;
22508        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22509            event.mAction == DragEvent.ACTION_DROP) {
22510            // About to deliver an event with coordinates to this view. Notify that now this view
22511            // has drag focus. This will send exit/enter events as needed.
22512            getViewRootImpl().setDragFocus(this, event);
22513        }
22514        return callDragEventHandler(event);
22515    }
22516
22517    final boolean callDragEventHandler(DragEvent event) {
22518        final boolean result;
22519
22520        ListenerInfo li = mListenerInfo;
22521        //noinspection SimplifiableIfStatement
22522        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22523                && li.mOnDragListener.onDrag(this, event)) {
22524            result = true;
22525        } else {
22526            result = onDragEvent(event);
22527        }
22528
22529        switch (event.mAction) {
22530            case DragEvent.ACTION_DRAG_ENTERED: {
22531                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22532                refreshDrawableState();
22533            } break;
22534            case DragEvent.ACTION_DRAG_EXITED: {
22535                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22536                refreshDrawableState();
22537            } break;
22538            case DragEvent.ACTION_DRAG_ENDED: {
22539                mPrivateFlags2 &= ~View.DRAG_MASK;
22540                refreshDrawableState();
22541            } break;
22542        }
22543
22544        return result;
22545    }
22546
22547    boolean canAcceptDrag() {
22548        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22549    }
22550
22551    /**
22552     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22553     * it is ever exposed at all.
22554     * @hide
22555     */
22556    public void onCloseSystemDialogs(String reason) {
22557    }
22558
22559    /**
22560     * Given a Drawable whose bounds have been set to draw into this view,
22561     * update a Region being computed for
22562     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22563     * that any non-transparent parts of the Drawable are removed from the
22564     * given transparent region.
22565     *
22566     * @param dr The Drawable whose transparency is to be applied to the region.
22567     * @param region A Region holding the current transparency information,
22568     * where any parts of the region that are set are considered to be
22569     * transparent.  On return, this region will be modified to have the
22570     * transparency information reduced by the corresponding parts of the
22571     * Drawable that are not transparent.
22572     * {@hide}
22573     */
22574    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22575        if (DBG) {
22576            Log.i("View", "Getting transparent region for: " + this);
22577        }
22578        final Region r = dr.getTransparentRegion();
22579        final Rect db = dr.getBounds();
22580        final AttachInfo attachInfo = mAttachInfo;
22581        if (r != null && attachInfo != null) {
22582            final int w = getRight()-getLeft();
22583            final int h = getBottom()-getTop();
22584            if (db.left > 0) {
22585                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22586                r.op(0, 0, db.left, h, Region.Op.UNION);
22587            }
22588            if (db.right < w) {
22589                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22590                r.op(db.right, 0, w, h, Region.Op.UNION);
22591            }
22592            if (db.top > 0) {
22593                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22594                r.op(0, 0, w, db.top, Region.Op.UNION);
22595            }
22596            if (db.bottom < h) {
22597                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22598                r.op(0, db.bottom, w, h, Region.Op.UNION);
22599            }
22600            final int[] location = attachInfo.mTransparentLocation;
22601            getLocationInWindow(location);
22602            r.translate(location[0], location[1]);
22603            region.op(r, Region.Op.INTERSECT);
22604        } else {
22605            region.op(db, Region.Op.DIFFERENCE);
22606        }
22607    }
22608
22609    private void checkForLongClick(int delayOffset, float x, float y) {
22610        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22611            mHasPerformedLongPress = false;
22612
22613            if (mPendingCheckForLongPress == null) {
22614                mPendingCheckForLongPress = new CheckForLongPress();
22615            }
22616            mPendingCheckForLongPress.setAnchor(x, y);
22617            mPendingCheckForLongPress.rememberWindowAttachCount();
22618            mPendingCheckForLongPress.rememberPressedState();
22619            postDelayed(mPendingCheckForLongPress,
22620                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22621        }
22622    }
22623
22624    /**
22625     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22626     * LayoutInflater} class, which provides a full range of options for view inflation.
22627     *
22628     * @param context The Context object for your activity or application.
22629     * @param resource The resource ID to inflate
22630     * @param root A view group that will be the parent.  Used to properly inflate the
22631     * layout_* parameters.
22632     * @see LayoutInflater
22633     */
22634    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22635        LayoutInflater factory = LayoutInflater.from(context);
22636        return factory.inflate(resource, root);
22637    }
22638
22639    /**
22640     * Scroll the view with standard behavior for scrolling beyond the normal
22641     * content boundaries. Views that call this method should override
22642     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22643     * results of an over-scroll operation.
22644     *
22645     * Views can use this method to handle any touch or fling-based scrolling.
22646     *
22647     * @param deltaX Change in X in pixels
22648     * @param deltaY Change in Y in pixels
22649     * @param scrollX Current X scroll value in pixels before applying deltaX
22650     * @param scrollY Current Y scroll value in pixels before applying deltaY
22651     * @param scrollRangeX Maximum content scroll range along the X axis
22652     * @param scrollRangeY Maximum content scroll range along the Y axis
22653     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22654     *          along the X axis.
22655     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22656     *          along the Y axis.
22657     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22658     * @return true if scrolling was clamped to an over-scroll boundary along either
22659     *          axis, false otherwise.
22660     */
22661    @SuppressWarnings({"UnusedParameters"})
22662    protected boolean overScrollBy(int deltaX, int deltaY,
22663            int scrollX, int scrollY,
22664            int scrollRangeX, int scrollRangeY,
22665            int maxOverScrollX, int maxOverScrollY,
22666            boolean isTouchEvent) {
22667        final int overScrollMode = mOverScrollMode;
22668        final boolean canScrollHorizontal =
22669                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22670        final boolean canScrollVertical =
22671                computeVerticalScrollRange() > computeVerticalScrollExtent();
22672        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22673                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22674        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22675                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22676
22677        int newScrollX = scrollX + deltaX;
22678        if (!overScrollHorizontal) {
22679            maxOverScrollX = 0;
22680        }
22681
22682        int newScrollY = scrollY + deltaY;
22683        if (!overScrollVertical) {
22684            maxOverScrollY = 0;
22685        }
22686
22687        // Clamp values if at the limits and record
22688        final int left = -maxOverScrollX;
22689        final int right = maxOverScrollX + scrollRangeX;
22690        final int top = -maxOverScrollY;
22691        final int bottom = maxOverScrollY + scrollRangeY;
22692
22693        boolean clampedX = false;
22694        if (newScrollX > right) {
22695            newScrollX = right;
22696            clampedX = true;
22697        } else if (newScrollX < left) {
22698            newScrollX = left;
22699            clampedX = true;
22700        }
22701
22702        boolean clampedY = false;
22703        if (newScrollY > bottom) {
22704            newScrollY = bottom;
22705            clampedY = true;
22706        } else if (newScrollY < top) {
22707            newScrollY = top;
22708            clampedY = true;
22709        }
22710
22711        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22712
22713        return clampedX || clampedY;
22714    }
22715
22716    /**
22717     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22718     * respond to the results of an over-scroll operation.
22719     *
22720     * @param scrollX New X scroll value in pixels
22721     * @param scrollY New Y scroll value in pixels
22722     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22723     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22724     */
22725    protected void onOverScrolled(int scrollX, int scrollY,
22726            boolean clampedX, boolean clampedY) {
22727        // Intentionally empty.
22728    }
22729
22730    /**
22731     * Returns the over-scroll mode for this view. The result will be
22732     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22733     * (allow over-scrolling only if the view content is larger than the container),
22734     * or {@link #OVER_SCROLL_NEVER}.
22735     *
22736     * @return This view's over-scroll mode.
22737     */
22738    public int getOverScrollMode() {
22739        return mOverScrollMode;
22740    }
22741
22742    /**
22743     * Set the over-scroll mode for this view. Valid over-scroll modes are
22744     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22745     * (allow over-scrolling only if the view content is larger than the container),
22746     * or {@link #OVER_SCROLL_NEVER}.
22747     *
22748     * Setting the over-scroll mode of a view will have an effect only if the
22749     * view is capable of scrolling.
22750     *
22751     * @param overScrollMode The new over-scroll mode for this view.
22752     */
22753    public void setOverScrollMode(int overScrollMode) {
22754        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22755                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22756                overScrollMode != OVER_SCROLL_NEVER) {
22757            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22758        }
22759        mOverScrollMode = overScrollMode;
22760    }
22761
22762    /**
22763     * Enable or disable nested scrolling for this view.
22764     *
22765     * <p>If this property is set to true the view will be permitted to initiate nested
22766     * scrolling operations with a compatible parent view in the current hierarchy. If this
22767     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22768     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22769     * the nested scroll.</p>
22770     *
22771     * @param enabled true to enable nested scrolling, false to disable
22772     *
22773     * @see #isNestedScrollingEnabled()
22774     */
22775    public void setNestedScrollingEnabled(boolean enabled) {
22776        if (enabled) {
22777            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22778        } else {
22779            stopNestedScroll();
22780            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22781        }
22782    }
22783
22784    /**
22785     * Returns true if nested scrolling is enabled for this view.
22786     *
22787     * <p>If nested scrolling is enabled and this View class implementation supports it,
22788     * this view will act as a nested scrolling child view when applicable, forwarding data
22789     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22790     * parent.</p>
22791     *
22792     * @return true if nested scrolling is enabled
22793     *
22794     * @see #setNestedScrollingEnabled(boolean)
22795     */
22796    public boolean isNestedScrollingEnabled() {
22797        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22798                PFLAG3_NESTED_SCROLLING_ENABLED;
22799    }
22800
22801    /**
22802     * Begin a nestable scroll operation along the given axes.
22803     *
22804     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22805     *
22806     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22807     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22808     * In the case of touch scrolling the nested scroll will be terminated automatically in
22809     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22810     * In the event of programmatic scrolling the caller must explicitly call
22811     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22812     *
22813     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22814     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22815     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22816     *
22817     * <p>At each incremental step of the scroll the caller should invoke
22818     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22819     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22820     * parent at least partially consumed the scroll and the caller should adjust the amount it
22821     * scrolls by.</p>
22822     *
22823     * <p>After applying the remainder of the scroll delta the caller should invoke
22824     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22825     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22826     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22827     * </p>
22828     *
22829     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22830     *             {@link #SCROLL_AXIS_VERTICAL}.
22831     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22832     *         the current gesture.
22833     *
22834     * @see #stopNestedScroll()
22835     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22836     * @see #dispatchNestedScroll(int, int, int, int, int[])
22837     */
22838    public boolean startNestedScroll(int axes) {
22839        if (hasNestedScrollingParent()) {
22840            // Already in progress
22841            return true;
22842        }
22843        if (isNestedScrollingEnabled()) {
22844            ViewParent p = getParent();
22845            View child = this;
22846            while (p != null) {
22847                try {
22848                    if (p.onStartNestedScroll(child, this, axes)) {
22849                        mNestedScrollingParent = p;
22850                        p.onNestedScrollAccepted(child, this, axes);
22851                        return true;
22852                    }
22853                } catch (AbstractMethodError e) {
22854                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22855                            "method onStartNestedScroll", e);
22856                    // Allow the search upward to continue
22857                }
22858                if (p instanceof View) {
22859                    child = (View) p;
22860                }
22861                p = p.getParent();
22862            }
22863        }
22864        return false;
22865    }
22866
22867    /**
22868     * Stop a nested scroll in progress.
22869     *
22870     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22871     *
22872     * @see #startNestedScroll(int)
22873     */
22874    public void stopNestedScroll() {
22875        if (mNestedScrollingParent != null) {
22876            mNestedScrollingParent.onStopNestedScroll(this);
22877            mNestedScrollingParent = null;
22878        }
22879    }
22880
22881    /**
22882     * Returns true if this view has a nested scrolling parent.
22883     *
22884     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22885     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22886     *
22887     * @return whether this view has a nested scrolling parent
22888     */
22889    public boolean hasNestedScrollingParent() {
22890        return mNestedScrollingParent != null;
22891    }
22892
22893    /**
22894     * Dispatch one step of a nested scroll in progress.
22895     *
22896     * <p>Implementations of views that support nested scrolling should call this to report
22897     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
22898     * is not currently in progress or nested scrolling is not
22899     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
22900     *
22901     * <p>Compatible View implementations should also call
22902     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
22903     * consuming a component of the scroll event themselves.</p>
22904     *
22905     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
22906     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
22907     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
22908     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
22909     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22910     *                       in local view coordinates of this view from before this operation
22911     *                       to after it completes. View implementations may use this to adjust
22912     *                       expected input coordinate tracking.
22913     * @return true if the event was dispatched, false if it could not be dispatched.
22914     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22915     */
22916    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
22917            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
22918        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22919            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
22920                int startX = 0;
22921                int startY = 0;
22922                if (offsetInWindow != null) {
22923                    getLocationInWindow(offsetInWindow);
22924                    startX = offsetInWindow[0];
22925                    startY = offsetInWindow[1];
22926                }
22927
22928                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
22929                        dxUnconsumed, dyUnconsumed);
22930
22931                if (offsetInWindow != null) {
22932                    getLocationInWindow(offsetInWindow);
22933                    offsetInWindow[0] -= startX;
22934                    offsetInWindow[1] -= startY;
22935                }
22936                return true;
22937            } else if (offsetInWindow != null) {
22938                // No motion, no dispatch. Keep offsetInWindow up to date.
22939                offsetInWindow[0] = 0;
22940                offsetInWindow[1] = 0;
22941            }
22942        }
22943        return false;
22944    }
22945
22946    /**
22947     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
22948     *
22949     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
22950     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
22951     * scrolling operation to consume some or all of the scroll operation before the child view
22952     * consumes it.</p>
22953     *
22954     * @param dx Horizontal scroll distance in pixels
22955     * @param dy Vertical scroll distance in pixels
22956     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
22957     *                 and consumed[1] the consumed dy.
22958     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22959     *                       in local view coordinates of this view from before this operation
22960     *                       to after it completes. View implementations may use this to adjust
22961     *                       expected input coordinate tracking.
22962     * @return true if the parent consumed some or all of the scroll delta
22963     * @see #dispatchNestedScroll(int, int, int, int, int[])
22964     */
22965    public boolean dispatchNestedPreScroll(int dx, int dy,
22966            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
22967        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22968            if (dx != 0 || dy != 0) {
22969                int startX = 0;
22970                int startY = 0;
22971                if (offsetInWindow != null) {
22972                    getLocationInWindow(offsetInWindow);
22973                    startX = offsetInWindow[0];
22974                    startY = offsetInWindow[1];
22975                }
22976
22977                if (consumed == null) {
22978                    if (mTempNestedScrollConsumed == null) {
22979                        mTempNestedScrollConsumed = new int[2];
22980                    }
22981                    consumed = mTempNestedScrollConsumed;
22982                }
22983                consumed[0] = 0;
22984                consumed[1] = 0;
22985                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
22986
22987                if (offsetInWindow != null) {
22988                    getLocationInWindow(offsetInWindow);
22989                    offsetInWindow[0] -= startX;
22990                    offsetInWindow[1] -= startY;
22991                }
22992                return consumed[0] != 0 || consumed[1] != 0;
22993            } else if (offsetInWindow != null) {
22994                offsetInWindow[0] = 0;
22995                offsetInWindow[1] = 0;
22996            }
22997        }
22998        return false;
22999    }
23000
23001    /**
23002     * Dispatch a fling to a nested scrolling parent.
23003     *
23004     * <p>This method should be used to indicate that a nested scrolling child has detected
23005     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23006     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23007     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23008     * along a scrollable axis.</p>
23009     *
23010     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23011     * its own content, it can use this method to delegate the fling to its nested scrolling
23012     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23013     *
23014     * @param velocityX Horizontal fling velocity in pixels per second
23015     * @param velocityY Vertical fling velocity in pixels per second
23016     * @param consumed true if the child consumed the fling, false otherwise
23017     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23018     */
23019    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23020        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23021            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23022        }
23023        return false;
23024    }
23025
23026    /**
23027     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23028     *
23029     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23030     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23031     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23032     * before the child view consumes it. If this method returns <code>true</code>, a nested
23033     * parent view consumed the fling and this view should not scroll as a result.</p>
23034     *
23035     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23036     * the fling at a time. If a parent view consumed the fling this method will return false.
23037     * Custom view implementations should account for this in two ways:</p>
23038     *
23039     * <ul>
23040     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23041     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23042     *     position regardless.</li>
23043     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23044     *     even to settle back to a valid idle position.</li>
23045     * </ul>
23046     *
23047     * <p>Views should also not offer fling velocities to nested parent views along an axis
23048     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23049     * should not offer a horizontal fling velocity to its parents since scrolling along that
23050     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23051     *
23052     * @param velocityX Horizontal fling velocity in pixels per second
23053     * @param velocityY Vertical fling velocity in pixels per second
23054     * @return true if a nested scrolling parent consumed the fling
23055     */
23056    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23057        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23058            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23059        }
23060        return false;
23061    }
23062
23063    /**
23064     * Gets a scale factor that determines the distance the view should scroll
23065     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23066     * @return The vertical scroll scale factor.
23067     * @hide
23068     */
23069    protected float getVerticalScrollFactor() {
23070        if (mVerticalScrollFactor == 0) {
23071            TypedValue outValue = new TypedValue();
23072            if (!mContext.getTheme().resolveAttribute(
23073                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23074                throw new IllegalStateException(
23075                        "Expected theme to define listPreferredItemHeight.");
23076            }
23077            mVerticalScrollFactor = outValue.getDimension(
23078                    mContext.getResources().getDisplayMetrics());
23079        }
23080        return mVerticalScrollFactor;
23081    }
23082
23083    /**
23084     * Gets a scale factor that determines the distance the view should scroll
23085     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23086     * @return The horizontal scroll scale factor.
23087     * @hide
23088     */
23089    protected float getHorizontalScrollFactor() {
23090        // TODO: Should use something else.
23091        return getVerticalScrollFactor();
23092    }
23093
23094    /**
23095     * Return the value specifying the text direction or policy that was set with
23096     * {@link #setTextDirection(int)}.
23097     *
23098     * @return the defined text direction. It can be one of:
23099     *
23100     * {@link #TEXT_DIRECTION_INHERIT},
23101     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23102     * {@link #TEXT_DIRECTION_ANY_RTL},
23103     * {@link #TEXT_DIRECTION_LTR},
23104     * {@link #TEXT_DIRECTION_RTL},
23105     * {@link #TEXT_DIRECTION_LOCALE},
23106     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23107     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23108     *
23109     * @attr ref android.R.styleable#View_textDirection
23110     *
23111     * @hide
23112     */
23113    @ViewDebug.ExportedProperty(category = "text", mapping = {
23114            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23115            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23116            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23117            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23118            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23119            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23120            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23121            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23122    })
23123    public int getRawTextDirection() {
23124        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23125    }
23126
23127    /**
23128     * Set the text direction.
23129     *
23130     * @param textDirection the direction to set. Should be one of:
23131     *
23132     * {@link #TEXT_DIRECTION_INHERIT},
23133     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23134     * {@link #TEXT_DIRECTION_ANY_RTL},
23135     * {@link #TEXT_DIRECTION_LTR},
23136     * {@link #TEXT_DIRECTION_RTL},
23137     * {@link #TEXT_DIRECTION_LOCALE}
23138     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23139     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23140     *
23141     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23142     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23143     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23144     *
23145     * @attr ref android.R.styleable#View_textDirection
23146     */
23147    public void setTextDirection(int textDirection) {
23148        if (getRawTextDirection() != textDirection) {
23149            // Reset the current text direction and the resolved one
23150            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23151            resetResolvedTextDirection();
23152            // Set the new text direction
23153            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23154            // Do resolution
23155            resolveTextDirection();
23156            // Notify change
23157            onRtlPropertiesChanged(getLayoutDirection());
23158            // Refresh
23159            requestLayout();
23160            invalidate(true);
23161        }
23162    }
23163
23164    /**
23165     * Return the resolved text direction.
23166     *
23167     * @return the resolved text direction. Returns one of:
23168     *
23169     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23170     * {@link #TEXT_DIRECTION_ANY_RTL},
23171     * {@link #TEXT_DIRECTION_LTR},
23172     * {@link #TEXT_DIRECTION_RTL},
23173     * {@link #TEXT_DIRECTION_LOCALE},
23174     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23175     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23176     *
23177     * @attr ref android.R.styleable#View_textDirection
23178     */
23179    @ViewDebug.ExportedProperty(category = "text", mapping = {
23180            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23181            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23182            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23183            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23184            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23185            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23186            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23187            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23188    })
23189    public int getTextDirection() {
23190        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23191    }
23192
23193    /**
23194     * Resolve the text direction.
23195     *
23196     * @return true if resolution has been done, false otherwise.
23197     *
23198     * @hide
23199     */
23200    public boolean resolveTextDirection() {
23201        // Reset any previous text direction resolution
23202        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23203
23204        if (hasRtlSupport()) {
23205            // Set resolved text direction flag depending on text direction flag
23206            final int textDirection = getRawTextDirection();
23207            switch(textDirection) {
23208                case TEXT_DIRECTION_INHERIT:
23209                    if (!canResolveTextDirection()) {
23210                        // We cannot do the resolution if there is no parent, so use the default one
23211                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23212                        // Resolution will need to happen again later
23213                        return false;
23214                    }
23215
23216                    // Parent has not yet resolved, so we still return the default
23217                    try {
23218                        if (!mParent.isTextDirectionResolved()) {
23219                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23220                            // Resolution will need to happen again later
23221                            return false;
23222                        }
23223                    } catch (AbstractMethodError e) {
23224                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23225                                " does not fully implement ViewParent", e);
23226                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23227                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23228                        return true;
23229                    }
23230
23231                    // Set current resolved direction to the same value as the parent's one
23232                    int parentResolvedDirection;
23233                    try {
23234                        parentResolvedDirection = mParent.getTextDirection();
23235                    } catch (AbstractMethodError e) {
23236                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23237                                " does not fully implement ViewParent", e);
23238                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23239                    }
23240                    switch (parentResolvedDirection) {
23241                        case TEXT_DIRECTION_FIRST_STRONG:
23242                        case TEXT_DIRECTION_ANY_RTL:
23243                        case TEXT_DIRECTION_LTR:
23244                        case TEXT_DIRECTION_RTL:
23245                        case TEXT_DIRECTION_LOCALE:
23246                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23247                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23248                            mPrivateFlags2 |=
23249                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23250                            break;
23251                        default:
23252                            // Default resolved direction is "first strong" heuristic
23253                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23254                    }
23255                    break;
23256                case TEXT_DIRECTION_FIRST_STRONG:
23257                case TEXT_DIRECTION_ANY_RTL:
23258                case TEXT_DIRECTION_LTR:
23259                case TEXT_DIRECTION_RTL:
23260                case TEXT_DIRECTION_LOCALE:
23261                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23262                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23263                    // Resolved direction is the same as text direction
23264                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23265                    break;
23266                default:
23267                    // Default resolved direction is "first strong" heuristic
23268                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23269            }
23270        } else {
23271            // Default resolved direction is "first strong" heuristic
23272            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23273        }
23274
23275        // Set to resolved
23276        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23277        return true;
23278    }
23279
23280    /**
23281     * Check if text direction resolution can be done.
23282     *
23283     * @return true if text direction resolution can be done otherwise return false.
23284     */
23285    public boolean canResolveTextDirection() {
23286        switch (getRawTextDirection()) {
23287            case TEXT_DIRECTION_INHERIT:
23288                if (mParent != null) {
23289                    try {
23290                        return mParent.canResolveTextDirection();
23291                    } catch (AbstractMethodError e) {
23292                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23293                                " does not fully implement ViewParent", e);
23294                    }
23295                }
23296                return false;
23297
23298            default:
23299                return true;
23300        }
23301    }
23302
23303    /**
23304     * Reset resolved text direction. Text direction will be resolved during a call to
23305     * {@link #onMeasure(int, int)}.
23306     *
23307     * @hide
23308     */
23309    public void resetResolvedTextDirection() {
23310        // Reset any previous text direction resolution
23311        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23312        // Set to default value
23313        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23314    }
23315
23316    /**
23317     * @return true if text direction is inherited.
23318     *
23319     * @hide
23320     */
23321    public boolean isTextDirectionInherited() {
23322        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23323    }
23324
23325    /**
23326     * @return true if text direction is resolved.
23327     */
23328    public boolean isTextDirectionResolved() {
23329        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23330    }
23331
23332    /**
23333     * Return the value specifying the text alignment or policy that was set with
23334     * {@link #setTextAlignment(int)}.
23335     *
23336     * @return the defined text alignment. It can be one of:
23337     *
23338     * {@link #TEXT_ALIGNMENT_INHERIT},
23339     * {@link #TEXT_ALIGNMENT_GRAVITY},
23340     * {@link #TEXT_ALIGNMENT_CENTER},
23341     * {@link #TEXT_ALIGNMENT_TEXT_START},
23342     * {@link #TEXT_ALIGNMENT_TEXT_END},
23343     * {@link #TEXT_ALIGNMENT_VIEW_START},
23344     * {@link #TEXT_ALIGNMENT_VIEW_END}
23345     *
23346     * @attr ref android.R.styleable#View_textAlignment
23347     *
23348     * @hide
23349     */
23350    @ViewDebug.ExportedProperty(category = "text", mapping = {
23351            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23352            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23353            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23354            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23355            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23356            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23357            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23358    })
23359    @TextAlignment
23360    public int getRawTextAlignment() {
23361        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23362    }
23363
23364    /**
23365     * Set the text alignment.
23366     *
23367     * @param textAlignment The text alignment to set. Should be one of
23368     *
23369     * {@link #TEXT_ALIGNMENT_INHERIT},
23370     * {@link #TEXT_ALIGNMENT_GRAVITY},
23371     * {@link #TEXT_ALIGNMENT_CENTER},
23372     * {@link #TEXT_ALIGNMENT_TEXT_START},
23373     * {@link #TEXT_ALIGNMENT_TEXT_END},
23374     * {@link #TEXT_ALIGNMENT_VIEW_START},
23375     * {@link #TEXT_ALIGNMENT_VIEW_END}
23376     *
23377     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23378     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23379     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23380     *
23381     * @attr ref android.R.styleable#View_textAlignment
23382     */
23383    public void setTextAlignment(@TextAlignment int textAlignment) {
23384        if (textAlignment != getRawTextAlignment()) {
23385            // Reset the current and resolved text alignment
23386            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23387            resetResolvedTextAlignment();
23388            // Set the new text alignment
23389            mPrivateFlags2 |=
23390                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23391            // Do resolution
23392            resolveTextAlignment();
23393            // Notify change
23394            onRtlPropertiesChanged(getLayoutDirection());
23395            // Refresh
23396            requestLayout();
23397            invalidate(true);
23398        }
23399    }
23400
23401    /**
23402     * Return the resolved text alignment.
23403     *
23404     * @return the resolved text alignment. Returns one of:
23405     *
23406     * {@link #TEXT_ALIGNMENT_GRAVITY},
23407     * {@link #TEXT_ALIGNMENT_CENTER},
23408     * {@link #TEXT_ALIGNMENT_TEXT_START},
23409     * {@link #TEXT_ALIGNMENT_TEXT_END},
23410     * {@link #TEXT_ALIGNMENT_VIEW_START},
23411     * {@link #TEXT_ALIGNMENT_VIEW_END}
23412     *
23413     * @attr ref android.R.styleable#View_textAlignment
23414     */
23415    @ViewDebug.ExportedProperty(category = "text", mapping = {
23416            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23417            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23418            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23419            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23420            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23421            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23422            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23423    })
23424    @TextAlignment
23425    public int getTextAlignment() {
23426        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23427                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23428    }
23429
23430    /**
23431     * Resolve the text alignment.
23432     *
23433     * @return true if resolution has been done, false otherwise.
23434     *
23435     * @hide
23436     */
23437    public boolean resolveTextAlignment() {
23438        // Reset any previous text alignment resolution
23439        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23440
23441        if (hasRtlSupport()) {
23442            // Set resolved text alignment flag depending on text alignment flag
23443            final int textAlignment = getRawTextAlignment();
23444            switch (textAlignment) {
23445                case TEXT_ALIGNMENT_INHERIT:
23446                    // Check if we can resolve the text alignment
23447                    if (!canResolveTextAlignment()) {
23448                        // We cannot do the resolution if there is no parent so use the default
23449                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23450                        // Resolution will need to happen again later
23451                        return false;
23452                    }
23453
23454                    // Parent has not yet resolved, so we still return the default
23455                    try {
23456                        if (!mParent.isTextAlignmentResolved()) {
23457                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23458                            // Resolution will need to happen again later
23459                            return false;
23460                        }
23461                    } catch (AbstractMethodError e) {
23462                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23463                                " does not fully implement ViewParent", e);
23464                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23465                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23466                        return true;
23467                    }
23468
23469                    int parentResolvedTextAlignment;
23470                    try {
23471                        parentResolvedTextAlignment = mParent.getTextAlignment();
23472                    } catch (AbstractMethodError e) {
23473                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23474                                " does not fully implement ViewParent", e);
23475                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23476                    }
23477                    switch (parentResolvedTextAlignment) {
23478                        case TEXT_ALIGNMENT_GRAVITY:
23479                        case TEXT_ALIGNMENT_TEXT_START:
23480                        case TEXT_ALIGNMENT_TEXT_END:
23481                        case TEXT_ALIGNMENT_CENTER:
23482                        case TEXT_ALIGNMENT_VIEW_START:
23483                        case TEXT_ALIGNMENT_VIEW_END:
23484                            // Resolved text alignment is the same as the parent resolved
23485                            // text alignment
23486                            mPrivateFlags2 |=
23487                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23488                            break;
23489                        default:
23490                            // Use default resolved text alignment
23491                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23492                    }
23493                    break;
23494                case TEXT_ALIGNMENT_GRAVITY:
23495                case TEXT_ALIGNMENT_TEXT_START:
23496                case TEXT_ALIGNMENT_TEXT_END:
23497                case TEXT_ALIGNMENT_CENTER:
23498                case TEXT_ALIGNMENT_VIEW_START:
23499                case TEXT_ALIGNMENT_VIEW_END:
23500                    // Resolved text alignment is the same as text alignment
23501                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23502                    break;
23503                default:
23504                    // Use default resolved text alignment
23505                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23506            }
23507        } else {
23508            // Use default resolved text alignment
23509            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23510        }
23511
23512        // Set the resolved
23513        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23514        return true;
23515    }
23516
23517    /**
23518     * Check if text alignment resolution can be done.
23519     *
23520     * @return true if text alignment resolution can be done otherwise return false.
23521     */
23522    public boolean canResolveTextAlignment() {
23523        switch (getRawTextAlignment()) {
23524            case TEXT_DIRECTION_INHERIT:
23525                if (mParent != null) {
23526                    try {
23527                        return mParent.canResolveTextAlignment();
23528                    } catch (AbstractMethodError e) {
23529                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23530                                " does not fully implement ViewParent", e);
23531                    }
23532                }
23533                return false;
23534
23535            default:
23536                return true;
23537        }
23538    }
23539
23540    /**
23541     * Reset resolved text alignment. Text alignment will be resolved during a call to
23542     * {@link #onMeasure(int, int)}.
23543     *
23544     * @hide
23545     */
23546    public void resetResolvedTextAlignment() {
23547        // Reset any previous text alignment resolution
23548        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23549        // Set to default
23550        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23551    }
23552
23553    /**
23554     * @return true if text alignment is inherited.
23555     *
23556     * @hide
23557     */
23558    public boolean isTextAlignmentInherited() {
23559        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23560    }
23561
23562    /**
23563     * @return true if text alignment is resolved.
23564     */
23565    public boolean isTextAlignmentResolved() {
23566        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23567    }
23568
23569    /**
23570     * Generate a value suitable for use in {@link #setId(int)}.
23571     * This value will not collide with ID values generated at build time by aapt for R.id.
23572     *
23573     * @return a generated ID value
23574     */
23575    public static int generateViewId() {
23576        for (;;) {
23577            final int result = sNextGeneratedId.get();
23578            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23579            int newValue = result + 1;
23580            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23581            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23582                return result;
23583            }
23584        }
23585    }
23586
23587    private static boolean isViewIdGenerated(int id) {
23588        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23589    }
23590
23591    /**
23592     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23593     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23594     *                           a normal View or a ViewGroup with
23595     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23596     * @hide
23597     */
23598    public void captureTransitioningViews(List<View> transitioningViews) {
23599        if (getVisibility() == View.VISIBLE) {
23600            transitioningViews.add(this);
23601        }
23602    }
23603
23604    /**
23605     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23606     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23607     * @hide
23608     */
23609    public void findNamedViews(Map<String, View> namedElements) {
23610        if (getVisibility() == VISIBLE || mGhostView != null) {
23611            String transitionName = getTransitionName();
23612            if (transitionName != null) {
23613                namedElements.put(transitionName, this);
23614            }
23615        }
23616    }
23617
23618    /**
23619     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23620     * The default implementation does not care the location or event types, but some subclasses
23621     * may use it (such as WebViews).
23622     * @param event The MotionEvent from a mouse
23623     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23624     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23625     * @see PointerIcon
23626     */
23627    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23628        final float x = event.getX(pointerIndex);
23629        final float y = event.getY(pointerIndex);
23630        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23631            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23632        }
23633        return mPointerIcon;
23634    }
23635
23636    /**
23637     * Set the pointer icon for the current view.
23638     * Passing {@code null} will restore the pointer icon to its default value.
23639     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23640     */
23641    public void setPointerIcon(PointerIcon pointerIcon) {
23642        mPointerIcon = pointerIcon;
23643        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23644            return;
23645        }
23646        try {
23647            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23648        } catch (RemoteException e) {
23649        }
23650    }
23651
23652    /**
23653     * Gets the pointer icon for the current view.
23654     */
23655    public PointerIcon getPointerIcon() {
23656        return mPointerIcon;
23657    }
23658
23659    /**
23660     * Checks pointer capture status.
23661     *
23662     * @return true if the view has pointer capture.
23663     * @see #requestPointerCapture()
23664     * @see #hasPointerCapture()
23665     */
23666    public boolean hasPointerCapture() {
23667        final ViewRootImpl viewRootImpl = getViewRootImpl();
23668        if (viewRootImpl == null) {
23669            return false;
23670        }
23671        return viewRootImpl.hasPointerCapture();
23672    }
23673
23674    /**
23675     * Requests pointer capture mode.
23676     * <p>
23677     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23678     * change its position. Further mouse will be dispatched with the source
23679     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23680     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23681     * (touchscreens, or stylus) will not be affected.
23682     * <p>
23683     * If the window already has pointer capture, this call does nothing.
23684     * <p>
23685     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23686     * automatically when the window loses focus.
23687     *
23688     * @see #releasePointerCapture()
23689     * @see #hasPointerCapture()
23690     */
23691    public void requestPointerCapture() {
23692        final ViewRootImpl viewRootImpl = getViewRootImpl();
23693        if (viewRootImpl != null) {
23694            viewRootImpl.requestPointerCapture(true);
23695        }
23696    }
23697
23698
23699    /**
23700     * Releases the pointer capture.
23701     * <p>
23702     * If the window does not have pointer capture, this call will do nothing.
23703     * @see #requestPointerCapture()
23704     * @see #hasPointerCapture()
23705     */
23706    public void releasePointerCapture() {
23707        final ViewRootImpl viewRootImpl = getViewRootImpl();
23708        if (viewRootImpl != null) {
23709            viewRootImpl.requestPointerCapture(false);
23710        }
23711    }
23712
23713    /**
23714     * Called when the window has just acquired or lost pointer capture.
23715     *
23716     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23717     */
23718    @CallSuper
23719    public void onPointerCaptureChange(boolean hasCapture) {
23720    }
23721
23722    /**
23723     * @see #onPointerCaptureChange
23724     */
23725    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23726        onPointerCaptureChange(hasCapture);
23727    }
23728
23729    /**
23730     * Implement this method to handle captured pointer events
23731     *
23732     * @param event The captured pointer event.
23733     * @return True if the event was handled, false otherwise.
23734     * @see #requestPointerCapture()
23735     */
23736    public boolean onCapturedPointerEvent(MotionEvent event) {
23737        return false;
23738    }
23739
23740    /**
23741     * Interface definition for a callback to be invoked when a captured pointer event
23742     * is being dispatched this view. The callback will be invoked before the event is
23743     * given to the view.
23744     */
23745    public interface OnCapturedPointerListener {
23746        /**
23747         * Called when a captured pointer event is dispatched to a view.
23748         * @param view The view this event has been dispatched to.
23749         * @param event The captured event.
23750         * @return True if the listener has consumed the event, false otherwise.
23751         */
23752        boolean onCapturedPointer(View view, MotionEvent event);
23753    }
23754
23755    /**
23756     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23757     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23758     */
23759    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23760        getListenerInfo().mOnCapturedPointerListener = l;
23761    }
23762
23763    // Properties
23764    //
23765    /**
23766     * A Property wrapper around the <code>alpha</code> functionality handled by the
23767     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23768     */
23769    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23770        @Override
23771        public void setValue(View object, float value) {
23772            object.setAlpha(value);
23773        }
23774
23775        @Override
23776        public Float get(View object) {
23777            return object.getAlpha();
23778        }
23779    };
23780
23781    /**
23782     * A Property wrapper around the <code>translationX</code> functionality handled by the
23783     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23784     */
23785    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23786        @Override
23787        public void setValue(View object, float value) {
23788            object.setTranslationX(value);
23789        }
23790
23791                @Override
23792        public Float get(View object) {
23793            return object.getTranslationX();
23794        }
23795    };
23796
23797    /**
23798     * A Property wrapper around the <code>translationY</code> functionality handled by the
23799     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23800     */
23801    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23802        @Override
23803        public void setValue(View object, float value) {
23804            object.setTranslationY(value);
23805        }
23806
23807        @Override
23808        public Float get(View object) {
23809            return object.getTranslationY();
23810        }
23811    };
23812
23813    /**
23814     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23815     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23816     */
23817    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23818        @Override
23819        public void setValue(View object, float value) {
23820            object.setTranslationZ(value);
23821        }
23822
23823        @Override
23824        public Float get(View object) {
23825            return object.getTranslationZ();
23826        }
23827    };
23828
23829    /**
23830     * A Property wrapper around the <code>x</code> functionality handled by the
23831     * {@link View#setX(float)} and {@link View#getX()} methods.
23832     */
23833    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23834        @Override
23835        public void setValue(View object, float value) {
23836            object.setX(value);
23837        }
23838
23839        @Override
23840        public Float get(View object) {
23841            return object.getX();
23842        }
23843    };
23844
23845    /**
23846     * A Property wrapper around the <code>y</code> functionality handled by the
23847     * {@link View#setY(float)} and {@link View#getY()} methods.
23848     */
23849    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23850        @Override
23851        public void setValue(View object, float value) {
23852            object.setY(value);
23853        }
23854
23855        @Override
23856        public Float get(View object) {
23857            return object.getY();
23858        }
23859    };
23860
23861    /**
23862     * A Property wrapper around the <code>z</code> functionality handled by the
23863     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23864     */
23865    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23866        @Override
23867        public void setValue(View object, float value) {
23868            object.setZ(value);
23869        }
23870
23871        @Override
23872        public Float get(View object) {
23873            return object.getZ();
23874        }
23875    };
23876
23877    /**
23878     * A Property wrapper around the <code>rotation</code> functionality handled by the
23879     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23880     */
23881    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23882        @Override
23883        public void setValue(View object, float value) {
23884            object.setRotation(value);
23885        }
23886
23887        @Override
23888        public Float get(View object) {
23889            return object.getRotation();
23890        }
23891    };
23892
23893    /**
23894     * A Property wrapper around the <code>rotationX</code> functionality handled by the
23895     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
23896     */
23897    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
23898        @Override
23899        public void setValue(View object, float value) {
23900            object.setRotationX(value);
23901        }
23902
23903        @Override
23904        public Float get(View object) {
23905            return object.getRotationX();
23906        }
23907    };
23908
23909    /**
23910     * A Property wrapper around the <code>rotationY</code> functionality handled by the
23911     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
23912     */
23913    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
23914        @Override
23915        public void setValue(View object, float value) {
23916            object.setRotationY(value);
23917        }
23918
23919        @Override
23920        public Float get(View object) {
23921            return object.getRotationY();
23922        }
23923    };
23924
23925    /**
23926     * A Property wrapper around the <code>scaleX</code> functionality handled by the
23927     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
23928     */
23929    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
23930        @Override
23931        public void setValue(View object, float value) {
23932            object.setScaleX(value);
23933        }
23934
23935        @Override
23936        public Float get(View object) {
23937            return object.getScaleX();
23938        }
23939    };
23940
23941    /**
23942     * A Property wrapper around the <code>scaleY</code> functionality handled by the
23943     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
23944     */
23945    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
23946        @Override
23947        public void setValue(View object, float value) {
23948            object.setScaleY(value);
23949        }
23950
23951        @Override
23952        public Float get(View object) {
23953            return object.getScaleY();
23954        }
23955    };
23956
23957    /**
23958     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
23959     * Each MeasureSpec represents a requirement for either the width or the height.
23960     * A MeasureSpec is comprised of a size and a mode. There are three possible
23961     * modes:
23962     * <dl>
23963     * <dt>UNSPECIFIED</dt>
23964     * <dd>
23965     * The parent has not imposed any constraint on the child. It can be whatever size
23966     * it wants.
23967     * </dd>
23968     *
23969     * <dt>EXACTLY</dt>
23970     * <dd>
23971     * The parent has determined an exact size for the child. The child is going to be
23972     * given those bounds regardless of how big it wants to be.
23973     * </dd>
23974     *
23975     * <dt>AT_MOST</dt>
23976     * <dd>
23977     * The child can be as large as it wants up to the specified size.
23978     * </dd>
23979     * </dl>
23980     *
23981     * MeasureSpecs are implemented as ints to reduce object allocation. This class
23982     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
23983     */
23984    public static class MeasureSpec {
23985        private static final int MODE_SHIFT = 30;
23986        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
23987
23988        /** @hide */
23989        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
23990        @Retention(RetentionPolicy.SOURCE)
23991        public @interface MeasureSpecMode {}
23992
23993        /**
23994         * Measure specification mode: The parent has not imposed any constraint
23995         * on the child. It can be whatever size it wants.
23996         */
23997        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
23998
23999        /**
24000         * Measure specification mode: The parent has determined an exact size
24001         * for the child. The child is going to be given those bounds regardless
24002         * of how big it wants to be.
24003         */
24004        public static final int EXACTLY     = 1 << MODE_SHIFT;
24005
24006        /**
24007         * Measure specification mode: The child can be as large as it wants up
24008         * to the specified size.
24009         */
24010        public static final int AT_MOST     = 2 << MODE_SHIFT;
24011
24012        /**
24013         * Creates a measure specification based on the supplied size and mode.
24014         *
24015         * The mode must always be one of the following:
24016         * <ul>
24017         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24018         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24019         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24020         * </ul>
24021         *
24022         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24023         * implementation was such that the order of arguments did not matter
24024         * and overflow in either value could impact the resulting MeasureSpec.
24025         * {@link android.widget.RelativeLayout} was affected by this bug.
24026         * Apps targeting API levels greater than 17 will get the fixed, more strict
24027         * behavior.</p>
24028         *
24029         * @param size the size of the measure specification
24030         * @param mode the mode of the measure specification
24031         * @return the measure specification based on size and mode
24032         */
24033        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24034                                          @MeasureSpecMode int mode) {
24035            if (sUseBrokenMakeMeasureSpec) {
24036                return size + mode;
24037            } else {
24038                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24039            }
24040        }
24041
24042        /**
24043         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24044         * will automatically get a size of 0. Older apps expect this.
24045         *
24046         * @hide internal use only for compatibility with system widgets and older apps
24047         */
24048        public static int makeSafeMeasureSpec(int size, int mode) {
24049            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24050                return 0;
24051            }
24052            return makeMeasureSpec(size, mode);
24053        }
24054
24055        /**
24056         * Extracts the mode from the supplied measure specification.
24057         *
24058         * @param measureSpec the measure specification to extract the mode from
24059         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24060         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24061         *         {@link android.view.View.MeasureSpec#EXACTLY}
24062         */
24063        @MeasureSpecMode
24064        public static int getMode(int measureSpec) {
24065            //noinspection ResourceType
24066            return (measureSpec & MODE_MASK);
24067        }
24068
24069        /**
24070         * Extracts the size from the supplied measure specification.
24071         *
24072         * @param measureSpec the measure specification to extract the size from
24073         * @return the size in pixels defined in the supplied measure specification
24074         */
24075        public static int getSize(int measureSpec) {
24076            return (measureSpec & ~MODE_MASK);
24077        }
24078
24079        static int adjust(int measureSpec, int delta) {
24080            final int mode = getMode(measureSpec);
24081            int size = getSize(measureSpec);
24082            if (mode == UNSPECIFIED) {
24083                // No need to adjust size for UNSPECIFIED mode.
24084                return makeMeasureSpec(size, UNSPECIFIED);
24085            }
24086            size += delta;
24087            if (size < 0) {
24088                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24089                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24090                size = 0;
24091            }
24092            return makeMeasureSpec(size, mode);
24093        }
24094
24095        /**
24096         * Returns a String representation of the specified measure
24097         * specification.
24098         *
24099         * @param measureSpec the measure specification to convert to a String
24100         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24101         */
24102        public static String toString(int measureSpec) {
24103            int mode = getMode(measureSpec);
24104            int size = getSize(measureSpec);
24105
24106            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24107
24108            if (mode == UNSPECIFIED)
24109                sb.append("UNSPECIFIED ");
24110            else if (mode == EXACTLY)
24111                sb.append("EXACTLY ");
24112            else if (mode == AT_MOST)
24113                sb.append("AT_MOST ");
24114            else
24115                sb.append(mode).append(" ");
24116
24117            sb.append(size);
24118            return sb.toString();
24119        }
24120    }
24121
24122    private final class CheckForLongPress implements Runnable {
24123        private int mOriginalWindowAttachCount;
24124        private float mX;
24125        private float mY;
24126        private boolean mOriginalPressedState;
24127
24128        @Override
24129        public void run() {
24130            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24131                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24132                if (performLongClick(mX, mY)) {
24133                    mHasPerformedLongPress = true;
24134                }
24135            }
24136        }
24137
24138        public void setAnchor(float x, float y) {
24139            mX = x;
24140            mY = y;
24141        }
24142
24143        public void rememberWindowAttachCount() {
24144            mOriginalWindowAttachCount = mWindowAttachCount;
24145        }
24146
24147        public void rememberPressedState() {
24148            mOriginalPressedState = isPressed();
24149        }
24150    }
24151
24152    private final class CheckForTap implements Runnable {
24153        public float x;
24154        public float y;
24155
24156        @Override
24157        public void run() {
24158            mPrivateFlags &= ~PFLAG_PREPRESSED;
24159            setPressed(true, x, y);
24160            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24161        }
24162    }
24163
24164    private final class PerformClick implements Runnable {
24165        @Override
24166        public void run() {
24167            performClick();
24168        }
24169    }
24170
24171    /**
24172     * This method returns a ViewPropertyAnimator object, which can be used to animate
24173     * specific properties on this View.
24174     *
24175     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24176     */
24177    public ViewPropertyAnimator animate() {
24178        if (mAnimator == null) {
24179            mAnimator = new ViewPropertyAnimator(this);
24180        }
24181        return mAnimator;
24182    }
24183
24184    /**
24185     * Sets the name of the View to be used to identify Views in Transitions.
24186     * Names should be unique in the View hierarchy.
24187     *
24188     * @param transitionName The name of the View to uniquely identify it for Transitions.
24189     */
24190    public final void setTransitionName(String transitionName) {
24191        mTransitionName = transitionName;
24192    }
24193
24194    /**
24195     * Returns the name of the View to be used to identify Views in Transitions.
24196     * Names should be unique in the View hierarchy.
24197     *
24198     * <p>This returns null if the View has not been given a name.</p>
24199     *
24200     * @return The name used of the View to be used to identify Views in Transitions or null
24201     * if no name has been given.
24202     */
24203    @ViewDebug.ExportedProperty
24204    public String getTransitionName() {
24205        return mTransitionName;
24206    }
24207
24208    /**
24209     * @hide
24210     */
24211    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24212        // Do nothing.
24213    }
24214
24215    /**
24216     * Interface definition for a callback to be invoked when a hardware key event is
24217     * dispatched to this view. The callback will be invoked before the key event is
24218     * given to the view. This is only useful for hardware keyboards; a software input
24219     * method has no obligation to trigger this listener.
24220     */
24221    public interface OnKeyListener {
24222        /**
24223         * Called when a hardware key is dispatched to a view. This allows listeners to
24224         * get a chance to respond before the target view.
24225         * <p>Key presses in software keyboards will generally NOT trigger this method,
24226         * although some may elect to do so in some situations. Do not assume a
24227         * software input method has to be key-based; even if it is, it may use key presses
24228         * in a different way than you expect, so there is no way to reliably catch soft
24229         * input key presses.
24230         *
24231         * @param v The view the key has been dispatched to.
24232         * @param keyCode The code for the physical key that was pressed
24233         * @param event The KeyEvent object containing full information about
24234         *        the event.
24235         * @return True if the listener has consumed the event, false otherwise.
24236         */
24237        boolean onKey(View v, int keyCode, KeyEvent event);
24238    }
24239
24240    /**
24241     * Interface definition for a callback to be invoked when a touch event is
24242     * dispatched to this view. The callback will be invoked before the touch
24243     * event is given to the view.
24244     */
24245    public interface OnTouchListener {
24246        /**
24247         * Called when a touch event is dispatched to a view. This allows listeners to
24248         * get a chance to respond before the target view.
24249         *
24250         * @param v The view the touch event has been dispatched to.
24251         * @param event The MotionEvent object containing full information about
24252         *        the event.
24253         * @return True if the listener has consumed the event, false otherwise.
24254         */
24255        boolean onTouch(View v, MotionEvent event);
24256    }
24257
24258    /**
24259     * Interface definition for a callback to be invoked when a hover event is
24260     * dispatched to this view. The callback will be invoked before the hover
24261     * event is given to the view.
24262     */
24263    public interface OnHoverListener {
24264        /**
24265         * Called when a hover event is dispatched to a view. This allows listeners to
24266         * get a chance to respond before the target view.
24267         *
24268         * @param v The view the hover event has been dispatched to.
24269         * @param event The MotionEvent object containing full information about
24270         *        the event.
24271         * @return True if the listener has consumed the event, false otherwise.
24272         */
24273        boolean onHover(View v, MotionEvent event);
24274    }
24275
24276    /**
24277     * Interface definition for a callback to be invoked when a generic motion event is
24278     * dispatched to this view. The callback will be invoked before the generic motion
24279     * event is given to the view.
24280     */
24281    public interface OnGenericMotionListener {
24282        /**
24283         * Called when a generic motion event is dispatched to a view. This allows listeners to
24284         * get a chance to respond before the target view.
24285         *
24286         * @param v The view the generic motion event has been dispatched to.
24287         * @param event The MotionEvent object containing full information about
24288         *        the event.
24289         * @return True if the listener has consumed the event, false otherwise.
24290         */
24291        boolean onGenericMotion(View v, MotionEvent event);
24292    }
24293
24294    /**
24295     * Interface definition for a callback to be invoked when a view has been clicked and held.
24296     */
24297    public interface OnLongClickListener {
24298        /**
24299         * Called when a view has been clicked and held.
24300         *
24301         * @param v The view that was clicked and held.
24302         *
24303         * @return true if the callback consumed the long click, false otherwise.
24304         */
24305        boolean onLongClick(View v);
24306    }
24307
24308    /**
24309     * Interface definition for a callback to be invoked when a drag is being dispatched
24310     * to this view.  The callback will be invoked before the hosting view's own
24311     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24312     * onDrag(event) behavior, it should return 'false' from this callback.
24313     *
24314     * <div class="special reference">
24315     * <h3>Developer Guides</h3>
24316     * <p>For a guide to implementing drag and drop features, read the
24317     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24318     * </div>
24319     */
24320    public interface OnDragListener {
24321        /**
24322         * Called when a drag event is dispatched to a view. This allows listeners
24323         * to get a chance to override base View behavior.
24324         *
24325         * @param v The View that received the drag event.
24326         * @param event The {@link android.view.DragEvent} object for the drag event.
24327         * @return {@code true} if the drag event was handled successfully, or {@code false}
24328         * if the drag event was not handled. Note that {@code false} will trigger the View
24329         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24330         */
24331        boolean onDrag(View v, DragEvent event);
24332    }
24333
24334    /**
24335     * Interface definition for a callback to be invoked when the focus state of
24336     * a view changed.
24337     */
24338    public interface OnFocusChangeListener {
24339        /**
24340         * Called when the focus state of a view has changed.
24341         *
24342         * @param v The view whose state has changed.
24343         * @param hasFocus The new focus state of v.
24344         */
24345        void onFocusChange(View v, boolean hasFocus);
24346    }
24347
24348    /**
24349     * Interface definition for a callback to be invoked when a view is clicked.
24350     */
24351    public interface OnClickListener {
24352        /**
24353         * Called when a view has been clicked.
24354         *
24355         * @param v The view that was clicked.
24356         */
24357        void onClick(View v);
24358    }
24359
24360    /**
24361     * Interface definition for a callback to be invoked when a view is context clicked.
24362     */
24363    public interface OnContextClickListener {
24364        /**
24365         * Called when a view is context clicked.
24366         *
24367         * @param v The view that has been context clicked.
24368         * @return true if the callback consumed the context click, false otherwise.
24369         */
24370        boolean onContextClick(View v);
24371    }
24372
24373    /**
24374     * Interface definition for a callback to be invoked when the context menu
24375     * for this view is being built.
24376     */
24377    public interface OnCreateContextMenuListener {
24378        /**
24379         * Called when the context menu for this view is being built. It is not
24380         * safe to hold onto the menu after this method returns.
24381         *
24382         * @param menu The context menu that is being built
24383         * @param v The view for which the context menu is being built
24384         * @param menuInfo Extra information about the item for which the
24385         *            context menu should be shown. This information will vary
24386         *            depending on the class of v.
24387         */
24388        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24389    }
24390
24391    /**
24392     * Interface definition for a callback to be invoked when the status bar changes
24393     * visibility.  This reports <strong>global</strong> changes to the system UI
24394     * state, not what the application is requesting.
24395     *
24396     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24397     */
24398    public interface OnSystemUiVisibilityChangeListener {
24399        /**
24400         * Called when the status bar changes visibility because of a call to
24401         * {@link View#setSystemUiVisibility(int)}.
24402         *
24403         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24404         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24405         * This tells you the <strong>global</strong> state of these UI visibility
24406         * flags, not what your app is currently applying.
24407         */
24408        public void onSystemUiVisibilityChange(int visibility);
24409    }
24410
24411    /**
24412     * Interface definition for a callback to be invoked when this view is attached
24413     * or detached from its window.
24414     */
24415    public interface OnAttachStateChangeListener {
24416        /**
24417         * Called when the view is attached to a window.
24418         * @param v The view that was attached
24419         */
24420        public void onViewAttachedToWindow(View v);
24421        /**
24422         * Called when the view is detached from a window.
24423         * @param v The view that was detached
24424         */
24425        public void onViewDetachedFromWindow(View v);
24426    }
24427
24428    /**
24429     * Listener for applying window insets on a view in a custom way.
24430     *
24431     * <p>Apps may choose to implement this interface if they want to apply custom policy
24432     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24433     * is set, its
24434     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24435     * method will be called instead of the View's own
24436     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24437     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24438     * the View's normal behavior as part of its own.</p>
24439     */
24440    public interface OnApplyWindowInsetsListener {
24441        /**
24442         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24443         * on a View, this listener method will be called instead of the view's own
24444         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24445         *
24446         * @param v The view applying window insets
24447         * @param insets The insets to apply
24448         * @return The insets supplied, minus any insets that were consumed
24449         */
24450        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24451    }
24452
24453    private final class UnsetPressedState implements Runnable {
24454        @Override
24455        public void run() {
24456            setPressed(false);
24457        }
24458    }
24459
24460    /**
24461     * Base class for derived classes that want to save and restore their own
24462     * state in {@link android.view.View#onSaveInstanceState()}.
24463     */
24464    public static class BaseSavedState extends AbsSavedState {
24465        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24466        static final int IS_AUTOFILLED = 0b10;
24467        static final int ACCESSIBILITY_ID = 0b100;
24468
24469        // Flags that describe what data in this state is valid
24470        int mSavedData;
24471        String mStartActivityRequestWhoSaved;
24472        boolean mIsAutofilled;
24473        int mAccessibilityViewId;
24474
24475        /**
24476         * Constructor used when reading from a parcel. Reads the state of the superclass.
24477         *
24478         * @param source parcel to read from
24479         */
24480        public BaseSavedState(Parcel source) {
24481            this(source, null);
24482        }
24483
24484        /**
24485         * Constructor used when reading from a parcel using a given class loader.
24486         * Reads the state of the superclass.
24487         *
24488         * @param source parcel to read from
24489         * @param loader ClassLoader to use for reading
24490         */
24491        public BaseSavedState(Parcel source, ClassLoader loader) {
24492            super(source, loader);
24493            mSavedData = source.readInt();
24494            mStartActivityRequestWhoSaved = source.readString();
24495            mIsAutofilled = source.readBoolean();
24496            mAccessibilityViewId = source.readInt();
24497        }
24498
24499        /**
24500         * Constructor called by derived classes when creating their SavedState objects
24501         *
24502         * @param superState The state of the superclass of this view
24503         */
24504        public BaseSavedState(Parcelable superState) {
24505            super(superState);
24506        }
24507
24508        @Override
24509        public void writeToParcel(Parcel out, int flags) {
24510            super.writeToParcel(out, flags);
24511
24512            out.writeInt(mSavedData);
24513            out.writeString(mStartActivityRequestWhoSaved);
24514            out.writeBoolean(mIsAutofilled);
24515            out.writeInt(mAccessibilityViewId);
24516        }
24517
24518        public static final Parcelable.Creator<BaseSavedState> CREATOR
24519                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24520            @Override
24521            public BaseSavedState createFromParcel(Parcel in) {
24522                return new BaseSavedState(in);
24523            }
24524
24525            @Override
24526            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24527                return new BaseSavedState(in, loader);
24528            }
24529
24530            @Override
24531            public BaseSavedState[] newArray(int size) {
24532                return new BaseSavedState[size];
24533            }
24534        };
24535    }
24536
24537    /**
24538     * A set of information given to a view when it is attached to its parent
24539     * window.
24540     */
24541    final static class AttachInfo {
24542        interface Callbacks {
24543            void playSoundEffect(int effectId);
24544            boolean performHapticFeedback(int effectId, boolean always);
24545        }
24546
24547        /**
24548         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24549         * to a Handler. This class contains the target (View) to invalidate and
24550         * the coordinates of the dirty rectangle.
24551         *
24552         * For performance purposes, this class also implements a pool of up to
24553         * POOL_LIMIT objects that get reused. This reduces memory allocations
24554         * whenever possible.
24555         */
24556        static class InvalidateInfo {
24557            private static final int POOL_LIMIT = 10;
24558
24559            private static final SynchronizedPool<InvalidateInfo> sPool =
24560                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24561
24562            View target;
24563
24564            int left;
24565            int top;
24566            int right;
24567            int bottom;
24568
24569            public static InvalidateInfo obtain() {
24570                InvalidateInfo instance = sPool.acquire();
24571                return (instance != null) ? instance : new InvalidateInfo();
24572            }
24573
24574            public void recycle() {
24575                target = null;
24576                sPool.release(this);
24577            }
24578        }
24579
24580        final IWindowSession mSession;
24581
24582        final IWindow mWindow;
24583
24584        final IBinder mWindowToken;
24585
24586        Display mDisplay;
24587
24588        final Callbacks mRootCallbacks;
24589
24590        IWindowId mIWindowId;
24591        WindowId mWindowId;
24592
24593        /**
24594         * The top view of the hierarchy.
24595         */
24596        View mRootView;
24597
24598        IBinder mPanelParentWindowToken;
24599
24600        boolean mHardwareAccelerated;
24601        boolean mHardwareAccelerationRequested;
24602        ThreadedRenderer mThreadedRenderer;
24603        List<RenderNode> mPendingAnimatingRenderNodes;
24604
24605        /**
24606         * The state of the display to which the window is attached, as reported
24607         * by {@link Display#getState()}.  Note that the display state constants
24608         * declared by {@link Display} do not exactly line up with the screen state
24609         * constants declared by {@link View} (there are more display states than
24610         * screen states).
24611         */
24612        int mDisplayState = Display.STATE_UNKNOWN;
24613
24614        /**
24615         * Scale factor used by the compatibility mode
24616         */
24617        float mApplicationScale;
24618
24619        /**
24620         * Indicates whether the application is in compatibility mode
24621         */
24622        boolean mScalingRequired;
24623
24624        /**
24625         * Left position of this view's window
24626         */
24627        int mWindowLeft;
24628
24629        /**
24630         * Top position of this view's window
24631         */
24632        int mWindowTop;
24633
24634        /**
24635         * Indicates whether views need to use 32-bit drawing caches
24636         */
24637        boolean mUse32BitDrawingCache;
24638
24639        /**
24640         * For windows that are full-screen but using insets to layout inside
24641         * of the screen areas, these are the current insets to appear inside
24642         * the overscan area of the display.
24643         */
24644        final Rect mOverscanInsets = new Rect();
24645
24646        /**
24647         * For windows that are full-screen but using insets to layout inside
24648         * of the screen decorations, these are the current insets for the
24649         * content of the window.
24650         */
24651        final Rect mContentInsets = new Rect();
24652
24653        /**
24654         * For windows that are full-screen but using insets to layout inside
24655         * of the screen decorations, these are the current insets for the
24656         * actual visible parts of the window.
24657         */
24658        final Rect mVisibleInsets = new Rect();
24659
24660        /**
24661         * For windows that are full-screen but using insets to layout inside
24662         * of the screen decorations, these are the current insets for the
24663         * stable system windows.
24664         */
24665        final Rect mStableInsets = new Rect();
24666
24667        /**
24668         * For windows that include areas that are not covered by real surface these are the outsets
24669         * for real surface.
24670         */
24671        final Rect mOutsets = new Rect();
24672
24673        /**
24674         * In multi-window we force show the navigation bar. Because we don't want that the surface
24675         * size changes in this mode, we instead have a flag whether the navigation bar size should
24676         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24677         */
24678        boolean mAlwaysConsumeNavBar;
24679
24680        /**
24681         * The internal insets given by this window.  This value is
24682         * supplied by the client (through
24683         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24684         * be given to the window manager when changed to be used in laying
24685         * out windows behind it.
24686         */
24687        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24688                = new ViewTreeObserver.InternalInsetsInfo();
24689
24690        /**
24691         * Set to true when mGivenInternalInsets is non-empty.
24692         */
24693        boolean mHasNonEmptyGivenInternalInsets;
24694
24695        /**
24696         * All views in the window's hierarchy that serve as scroll containers,
24697         * used to determine if the window can be resized or must be panned
24698         * to adjust for a soft input area.
24699         */
24700        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24701
24702        final KeyEvent.DispatcherState mKeyDispatchState
24703                = new KeyEvent.DispatcherState();
24704
24705        /**
24706         * Indicates whether the view's window currently has the focus.
24707         */
24708        boolean mHasWindowFocus;
24709
24710        /**
24711         * The current visibility of the window.
24712         */
24713        int mWindowVisibility;
24714
24715        /**
24716         * Indicates the time at which drawing started to occur.
24717         */
24718        long mDrawingTime;
24719
24720        /**
24721         * Indicates whether or not ignoring the DIRTY_MASK flags.
24722         */
24723        boolean mIgnoreDirtyState;
24724
24725        /**
24726         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24727         * to avoid clearing that flag prematurely.
24728         */
24729        boolean mSetIgnoreDirtyState = false;
24730
24731        /**
24732         * Indicates whether the view's window is currently in touch mode.
24733         */
24734        boolean mInTouchMode;
24735
24736        /**
24737         * Indicates whether the view has requested unbuffered input dispatching for the current
24738         * event stream.
24739         */
24740        boolean mUnbufferedDispatchRequested;
24741
24742        /**
24743         * Indicates that ViewAncestor should trigger a global layout change
24744         * the next time it performs a traversal
24745         */
24746        boolean mRecomputeGlobalAttributes;
24747
24748        /**
24749         * Always report new attributes at next traversal.
24750         */
24751        boolean mForceReportNewAttributes;
24752
24753        /**
24754         * Set during a traveral if any views want to keep the screen on.
24755         */
24756        boolean mKeepScreenOn;
24757
24758        /**
24759         * Set during a traveral if the light center needs to be updated.
24760         */
24761        boolean mNeedsUpdateLightCenter;
24762
24763        /**
24764         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24765         */
24766        int mSystemUiVisibility;
24767
24768        /**
24769         * Hack to force certain system UI visibility flags to be cleared.
24770         */
24771        int mDisabledSystemUiVisibility;
24772
24773        /**
24774         * Last global system UI visibility reported by the window manager.
24775         */
24776        int mGlobalSystemUiVisibility = -1;
24777
24778        /**
24779         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24780         * attached.
24781         */
24782        boolean mHasSystemUiListeners;
24783
24784        /**
24785         * Set if the window has requested to extend into the overscan region
24786         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24787         */
24788        boolean mOverscanRequested;
24789
24790        /**
24791         * Set if the visibility of any views has changed.
24792         */
24793        boolean mViewVisibilityChanged;
24794
24795        /**
24796         * Set to true if a view has been scrolled.
24797         */
24798        boolean mViewScrollChanged;
24799
24800        /**
24801         * Set to true if high contrast mode enabled
24802         */
24803        boolean mHighContrastText;
24804
24805        /**
24806         * Set to true if a pointer event is currently being handled.
24807         */
24808        boolean mHandlingPointerEvent;
24809
24810        /**
24811         * Global to the view hierarchy used as a temporary for dealing with
24812         * x/y points in the transparent region computations.
24813         */
24814        final int[] mTransparentLocation = new int[2];
24815
24816        /**
24817         * Global to the view hierarchy used as a temporary for dealing with
24818         * x/y points in the ViewGroup.invalidateChild implementation.
24819         */
24820        final int[] mInvalidateChildLocation = new int[2];
24821
24822        /**
24823         * Global to the view hierarchy used as a temporary for dealing with
24824         * computing absolute on-screen location.
24825         */
24826        final int[] mTmpLocation = new int[2];
24827
24828        /**
24829         * Global to the view hierarchy used as a temporary for dealing with
24830         * x/y location when view is transformed.
24831         */
24832        final float[] mTmpTransformLocation = new float[2];
24833
24834        /**
24835         * The view tree observer used to dispatch global events like
24836         * layout, pre-draw, touch mode change, etc.
24837         */
24838        final ViewTreeObserver mTreeObserver;
24839
24840        /**
24841         * A Canvas used by the view hierarchy to perform bitmap caching.
24842         */
24843        Canvas mCanvas;
24844
24845        /**
24846         * The view root impl.
24847         */
24848        final ViewRootImpl mViewRootImpl;
24849
24850        /**
24851         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24852         * handler can be used to pump events in the UI events queue.
24853         */
24854        final Handler mHandler;
24855
24856        /**
24857         * Temporary for use in computing invalidate rectangles while
24858         * calling up the hierarchy.
24859         */
24860        final Rect mTmpInvalRect = new Rect();
24861
24862        /**
24863         * Temporary for use in computing hit areas with transformed views
24864         */
24865        final RectF mTmpTransformRect = new RectF();
24866
24867        /**
24868         * Temporary for use in computing hit areas with transformed views
24869         */
24870        final RectF mTmpTransformRect1 = new RectF();
24871
24872        /**
24873         * Temporary list of rectanges.
24874         */
24875        final List<RectF> mTmpRectList = new ArrayList<>();
24876
24877        /**
24878         * Temporary for use in transforming invalidation rect
24879         */
24880        final Matrix mTmpMatrix = new Matrix();
24881
24882        /**
24883         * Temporary for use in transforming invalidation rect
24884         */
24885        final Transformation mTmpTransformation = new Transformation();
24886
24887        /**
24888         * Temporary for use in querying outlines from OutlineProviders
24889         */
24890        final Outline mTmpOutline = new Outline();
24891
24892        /**
24893         * Temporary list for use in collecting focusable descendents of a view.
24894         */
24895        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
24896
24897        /**
24898         * The id of the window for accessibility purposes.
24899         */
24900        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
24901
24902        /**
24903         * Flags related to accessibility processing.
24904         *
24905         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
24906         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
24907         */
24908        int mAccessibilityFetchFlags;
24909
24910        /**
24911         * The drawable for highlighting accessibility focus.
24912         */
24913        Drawable mAccessibilityFocusDrawable;
24914
24915        /**
24916         * The drawable for highlighting autofilled views.
24917         *
24918         * @see #isAutofilled()
24919         */
24920        Drawable mAutofilledDrawable;
24921
24922        /**
24923         * Show where the margins, bounds and layout bounds are for each view.
24924         */
24925        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
24926
24927        /**
24928         * Point used to compute visible regions.
24929         */
24930        final Point mPoint = new Point();
24931
24932        /**
24933         * Used to track which View originated a requestLayout() call, used when
24934         * requestLayout() is called during layout.
24935         */
24936        View mViewRequestingLayout;
24937
24938        /**
24939         * Used to track views that need (at least) a partial relayout at their current size
24940         * during the next traversal.
24941         */
24942        List<View> mPartialLayoutViews = new ArrayList<>();
24943
24944        /**
24945         * Swapped with mPartialLayoutViews during layout to avoid concurrent
24946         * modification. Lazily assigned during ViewRootImpl layout.
24947         */
24948        List<View> mEmptyPartialLayoutViews;
24949
24950        /**
24951         * Used to track the identity of the current drag operation.
24952         */
24953        IBinder mDragToken;
24954
24955        /**
24956         * The drag shadow surface for the current drag operation.
24957         */
24958        public Surface mDragSurface;
24959
24960
24961        /**
24962         * The view that currently has a tooltip displayed.
24963         */
24964        View mTooltipHost;
24965
24966        /**
24967         * Creates a new set of attachment information with the specified
24968         * events handler and thread.
24969         *
24970         * @param handler the events handler the view must use
24971         */
24972        AttachInfo(IWindowSession session, IWindow window, Display display,
24973                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
24974                Context context) {
24975            mSession = session;
24976            mWindow = window;
24977            mWindowToken = window.asBinder();
24978            mDisplay = display;
24979            mViewRootImpl = viewRootImpl;
24980            mHandler = handler;
24981            mRootCallbacks = effectPlayer;
24982            mTreeObserver = new ViewTreeObserver(context);
24983        }
24984    }
24985
24986    /**
24987     * <p>ScrollabilityCache holds various fields used by a View when scrolling
24988     * is supported. This avoids keeping too many unused fields in most
24989     * instances of View.</p>
24990     */
24991    private static class ScrollabilityCache implements Runnable {
24992
24993        /**
24994         * Scrollbars are not visible
24995         */
24996        public static final int OFF = 0;
24997
24998        /**
24999         * Scrollbars are visible
25000         */
25001        public static final int ON = 1;
25002
25003        /**
25004         * Scrollbars are fading away
25005         */
25006        public static final int FADING = 2;
25007
25008        public boolean fadeScrollBars;
25009
25010        public int fadingEdgeLength;
25011        public int scrollBarDefaultDelayBeforeFade;
25012        public int scrollBarFadeDuration;
25013
25014        public int scrollBarSize;
25015        public int scrollBarMinTouchTarget;
25016        public ScrollBarDrawable scrollBar;
25017        public float[] interpolatorValues;
25018        public View host;
25019
25020        public final Paint paint;
25021        public final Matrix matrix;
25022        public Shader shader;
25023
25024        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25025
25026        private static final float[] OPAQUE = { 255 };
25027        private static final float[] TRANSPARENT = { 0.0f };
25028
25029        /**
25030         * When fading should start. This time moves into the future every time
25031         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25032         */
25033        public long fadeStartTime;
25034
25035
25036        /**
25037         * The current state of the scrollbars: ON, OFF, or FADING
25038         */
25039        public int state = OFF;
25040
25041        private int mLastColor;
25042
25043        public final Rect mScrollBarBounds = new Rect();
25044        public final Rect mScrollBarTouchBounds = new Rect();
25045
25046        public static final int NOT_DRAGGING = 0;
25047        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25048        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25049        public int mScrollBarDraggingState = NOT_DRAGGING;
25050
25051        public float mScrollBarDraggingPos = 0;
25052
25053        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25054            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25055            scrollBarSize = configuration.getScaledScrollBarSize();
25056            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25057            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25058            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25059
25060            paint = new Paint();
25061            matrix = new Matrix();
25062            // use use a height of 1, and then wack the matrix each time we
25063            // actually use it.
25064            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25065            paint.setShader(shader);
25066            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25067
25068            this.host = host;
25069        }
25070
25071        public void setFadeColor(int color) {
25072            if (color != mLastColor) {
25073                mLastColor = color;
25074
25075                if (color != 0) {
25076                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25077                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25078                    paint.setShader(shader);
25079                    // Restore the default transfer mode (src_over)
25080                    paint.setXfermode(null);
25081                } else {
25082                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25083                    paint.setShader(shader);
25084                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25085                }
25086            }
25087        }
25088
25089        public void run() {
25090            long now = AnimationUtils.currentAnimationTimeMillis();
25091            if (now >= fadeStartTime) {
25092
25093                // the animation fades the scrollbars out by changing
25094                // the opacity (alpha) from fully opaque to fully
25095                // transparent
25096                int nextFrame = (int) now;
25097                int framesCount = 0;
25098
25099                Interpolator interpolator = scrollBarInterpolator;
25100
25101                // Start opaque
25102                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25103
25104                // End transparent
25105                nextFrame += scrollBarFadeDuration;
25106                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25107
25108                state = FADING;
25109
25110                // Kick off the fade animation
25111                host.invalidate(true);
25112            }
25113        }
25114    }
25115
25116    /**
25117     * Resuable callback for sending
25118     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25119     */
25120    private class SendViewScrolledAccessibilityEvent implements Runnable {
25121        public volatile boolean mIsPending;
25122
25123        public void run() {
25124            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25125            mIsPending = false;
25126        }
25127    }
25128
25129    /**
25130     * <p>
25131     * This class represents a delegate that can be registered in a {@link View}
25132     * to enhance accessibility support via composition rather via inheritance.
25133     * It is specifically targeted to widget developers that extend basic View
25134     * classes i.e. classes in package android.view, that would like their
25135     * applications to be backwards compatible.
25136     * </p>
25137     * <div class="special reference">
25138     * <h3>Developer Guides</h3>
25139     * <p>For more information about making applications accessible, read the
25140     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25141     * developer guide.</p>
25142     * </div>
25143     * <p>
25144     * A scenario in which a developer would like to use an accessibility delegate
25145     * is overriding a method introduced in a later API version than the minimal API
25146     * version supported by the application. For example, the method
25147     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25148     * in API version 4 when the accessibility APIs were first introduced. If a
25149     * developer would like his application to run on API version 4 devices (assuming
25150     * all other APIs used by the application are version 4 or lower) and take advantage
25151     * of this method, instead of overriding the method which would break the application's
25152     * backwards compatibility, he can override the corresponding method in this
25153     * delegate and register the delegate in the target View if the API version of
25154     * the system is high enough, i.e. the API version is the same as or higher than the API
25155     * version that introduced
25156     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25157     * </p>
25158     * <p>
25159     * Here is an example implementation:
25160     * </p>
25161     * <code><pre><p>
25162     * if (Build.VERSION.SDK_INT >= 14) {
25163     *     // If the API version is equal of higher than the version in
25164     *     // which onInitializeAccessibilityNodeInfo was introduced we
25165     *     // register a delegate with a customized implementation.
25166     *     View view = findViewById(R.id.view_id);
25167     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25168     *         public void onInitializeAccessibilityNodeInfo(View host,
25169     *                 AccessibilityNodeInfo info) {
25170     *             // Let the default implementation populate the info.
25171     *             super.onInitializeAccessibilityNodeInfo(host, info);
25172     *             // Set some other information.
25173     *             info.setEnabled(host.isEnabled());
25174     *         }
25175     *     });
25176     * }
25177     * </code></pre></p>
25178     * <p>
25179     * This delegate contains methods that correspond to the accessibility methods
25180     * in View. If a delegate has been specified the implementation in View hands
25181     * off handling to the corresponding method in this delegate. The default
25182     * implementation the delegate methods behaves exactly as the corresponding
25183     * method in View for the case of no accessibility delegate been set. Hence,
25184     * to customize the behavior of a View method, clients can override only the
25185     * corresponding delegate method without altering the behavior of the rest
25186     * accessibility related methods of the host view.
25187     * </p>
25188     * <p>
25189     * <strong>Note:</strong> On platform versions prior to
25190     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25191     * views in the {@code android.widget.*} package are called <i>before</i>
25192     * host methods. This prevents certain properties such as class name from
25193     * being modified by overriding
25194     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25195     * as any changes will be overwritten by the host class.
25196     * <p>
25197     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25198     * methods are called <i>after</i> host methods, which all properties to be
25199     * modified without being overwritten by the host class.
25200     */
25201    public static class AccessibilityDelegate {
25202
25203        /**
25204         * Sends an accessibility event of the given type. If accessibility is not
25205         * enabled this method has no effect.
25206         * <p>
25207         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25208         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25209         * been set.
25210         * </p>
25211         *
25212         * @param host The View hosting the delegate.
25213         * @param eventType The type of the event to send.
25214         *
25215         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25216         */
25217        public void sendAccessibilityEvent(View host, int eventType) {
25218            host.sendAccessibilityEventInternal(eventType);
25219        }
25220
25221        /**
25222         * Performs the specified accessibility action on the view. For
25223         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25224         * <p>
25225         * The default implementation behaves as
25226         * {@link View#performAccessibilityAction(int, Bundle)
25227         *  View#performAccessibilityAction(int, Bundle)} for the case of
25228         *  no accessibility delegate been set.
25229         * </p>
25230         *
25231         * @param action The action to perform.
25232         * @return Whether the action was performed.
25233         *
25234         * @see View#performAccessibilityAction(int, Bundle)
25235         *      View#performAccessibilityAction(int, Bundle)
25236         */
25237        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25238            return host.performAccessibilityActionInternal(action, args);
25239        }
25240
25241        /**
25242         * Sends an accessibility event. This method behaves exactly as
25243         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25244         * empty {@link AccessibilityEvent} and does not perform a check whether
25245         * accessibility is enabled.
25246         * <p>
25247         * The default implementation behaves as
25248         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25249         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25250         * the case of no accessibility delegate been set.
25251         * </p>
25252         *
25253         * @param host The View hosting the delegate.
25254         * @param event The event to send.
25255         *
25256         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25257         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25258         */
25259        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25260            host.sendAccessibilityEventUncheckedInternal(event);
25261        }
25262
25263        /**
25264         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25265         * to its children for adding their text content to the event.
25266         * <p>
25267         * The default implementation behaves as
25268         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25269         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25270         * the case of no accessibility delegate been set.
25271         * </p>
25272         *
25273         * @param host The View hosting the delegate.
25274         * @param event The event.
25275         * @return True if the event population was completed.
25276         *
25277         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25278         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25279         */
25280        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25281            return host.dispatchPopulateAccessibilityEventInternal(event);
25282        }
25283
25284        /**
25285         * Gives a chance to the host View to populate the accessibility event with its
25286         * text content.
25287         * <p>
25288         * The default implementation behaves as
25289         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25290         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25291         * the case of no accessibility delegate been set.
25292         * </p>
25293         *
25294         * @param host The View hosting the delegate.
25295         * @param event The accessibility event which to populate.
25296         *
25297         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25298         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25299         */
25300        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25301            host.onPopulateAccessibilityEventInternal(event);
25302        }
25303
25304        /**
25305         * Initializes an {@link AccessibilityEvent} with information about the
25306         * the host View which is the event source.
25307         * <p>
25308         * The default implementation behaves as
25309         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25310         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25311         * the case of no accessibility delegate been set.
25312         * </p>
25313         *
25314         * @param host The View hosting the delegate.
25315         * @param event The event to initialize.
25316         *
25317         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25318         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25319         */
25320        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25321            host.onInitializeAccessibilityEventInternal(event);
25322        }
25323
25324        /**
25325         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25326         * <p>
25327         * The default implementation behaves as
25328         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25329         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25330         * the case of no accessibility delegate been set.
25331         * </p>
25332         *
25333         * @param host The View hosting the delegate.
25334         * @param info The instance to initialize.
25335         *
25336         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25337         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25338         */
25339        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25340            host.onInitializeAccessibilityNodeInfoInternal(info);
25341        }
25342
25343        /**
25344         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25345         * additional data.
25346         * <p>
25347         * This method only needs to be implemented if the View offers to provide additional data.
25348         * </p>
25349         * <p>
25350         * The default implementation behaves as
25351         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25352         * the case where no accessibility delegate is set.
25353         * </p>
25354         *
25355         * @param host The View hosting the delegate. Never {@code null}.
25356         * @param info The info to which to add the extra data. Never {@code null}.
25357         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25358         *                     extra data should be added to the {@link Bundle} returned by
25359         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25360         *                     {@code null}.
25361         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25362         *                  May be {@code null} if the if the service provided no arguments.
25363         *
25364         * @see AccessibilityNodeInfo#setExtraAvailableData
25365         */
25366        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25367                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25368                @Nullable Bundle arguments) {
25369            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25370        }
25371
25372        /**
25373         * Called when a child of the host View has requested sending an
25374         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25375         * to augment the event.
25376         * <p>
25377         * The default implementation behaves as
25378         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25379         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25380         * the case of no accessibility delegate been set.
25381         * </p>
25382         *
25383         * @param host The View hosting the delegate.
25384         * @param child The child which requests sending the event.
25385         * @param event The event to be sent.
25386         * @return True if the event should be sent
25387         *
25388         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25389         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25390         */
25391        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25392                AccessibilityEvent event) {
25393            return host.onRequestSendAccessibilityEventInternal(child, event);
25394        }
25395
25396        /**
25397         * Gets the provider for managing a virtual view hierarchy rooted at this View
25398         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25399         * that explore the window content.
25400         * <p>
25401         * The default implementation behaves as
25402         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25403         * the case of no accessibility delegate been set.
25404         * </p>
25405         *
25406         * @return The provider.
25407         *
25408         * @see AccessibilityNodeProvider
25409         */
25410        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25411            return null;
25412        }
25413
25414        /**
25415         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25416         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25417         * This method is responsible for obtaining an accessibility node info from a
25418         * pool of reusable instances and calling
25419         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25420         * view to initialize the former.
25421         * <p>
25422         * <strong>Note:</strong> The client is responsible for recycling the obtained
25423         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25424         * creation.
25425         * </p>
25426         * <p>
25427         * The default implementation behaves as
25428         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25429         * the case of no accessibility delegate been set.
25430         * </p>
25431         * @return A populated {@link AccessibilityNodeInfo}.
25432         *
25433         * @see AccessibilityNodeInfo
25434         *
25435         * @hide
25436         */
25437        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25438            return host.createAccessibilityNodeInfoInternal();
25439        }
25440    }
25441
25442    private static class MatchIdPredicate implements Predicate<View> {
25443        public int mId;
25444
25445        @Override
25446        public boolean test(View view) {
25447            return (view.mID == mId);
25448        }
25449    }
25450
25451    private static class MatchLabelForPredicate implements Predicate<View> {
25452        private int mLabeledId;
25453
25454        @Override
25455        public boolean test(View view) {
25456            return (view.mLabelForId == mLabeledId);
25457        }
25458    }
25459
25460    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25461        private int mChangeTypes = 0;
25462        private boolean mPosted;
25463        private boolean mPostedWithDelay;
25464        private long mLastEventTimeMillis;
25465
25466        @Override
25467        public void run() {
25468            mPosted = false;
25469            mPostedWithDelay = false;
25470            mLastEventTimeMillis = SystemClock.uptimeMillis();
25471            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25472                final AccessibilityEvent event = AccessibilityEvent.obtain();
25473                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25474                event.setContentChangeTypes(mChangeTypes);
25475                sendAccessibilityEventUnchecked(event);
25476            }
25477            mChangeTypes = 0;
25478        }
25479
25480        public void runOrPost(int changeType) {
25481            mChangeTypes |= changeType;
25482
25483            // If this is a live region or the child of a live region, collect
25484            // all events from this frame and send them on the next frame.
25485            if (inLiveRegion()) {
25486                // If we're already posted with a delay, remove that.
25487                if (mPostedWithDelay) {
25488                    removeCallbacks(this);
25489                    mPostedWithDelay = false;
25490                }
25491                // Only post if we're not already posted.
25492                if (!mPosted) {
25493                    post(this);
25494                    mPosted = true;
25495                }
25496                return;
25497            }
25498
25499            if (mPosted) {
25500                return;
25501            }
25502
25503            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25504            final long minEventIntevalMillis =
25505                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25506            if (timeSinceLastMillis >= minEventIntevalMillis) {
25507                removeCallbacks(this);
25508                run();
25509            } else {
25510                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25511                mPostedWithDelay = true;
25512            }
25513        }
25514    }
25515
25516    private boolean inLiveRegion() {
25517        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25518            return true;
25519        }
25520
25521        ViewParent parent = getParent();
25522        while (parent instanceof View) {
25523            if (((View) parent).getAccessibilityLiveRegion()
25524                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25525                return true;
25526            }
25527            parent = parent.getParent();
25528        }
25529
25530        return false;
25531    }
25532
25533    /**
25534     * Dump all private flags in readable format, useful for documentation and
25535     * sanity checking.
25536     */
25537    private static void dumpFlags() {
25538        final HashMap<String, String> found = Maps.newHashMap();
25539        try {
25540            for (Field field : View.class.getDeclaredFields()) {
25541                final int modifiers = field.getModifiers();
25542                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25543                    if (field.getType().equals(int.class)) {
25544                        final int value = field.getInt(null);
25545                        dumpFlag(found, field.getName(), value);
25546                    } else if (field.getType().equals(int[].class)) {
25547                        final int[] values = (int[]) field.get(null);
25548                        for (int i = 0; i < values.length; i++) {
25549                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25550                        }
25551                    }
25552                }
25553            }
25554        } catch (IllegalAccessException e) {
25555            throw new RuntimeException(e);
25556        }
25557
25558        final ArrayList<String> keys = Lists.newArrayList();
25559        keys.addAll(found.keySet());
25560        Collections.sort(keys);
25561        for (String key : keys) {
25562            Log.d(VIEW_LOG_TAG, found.get(key));
25563        }
25564    }
25565
25566    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25567        // Sort flags by prefix, then by bits, always keeping unique keys
25568        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25569        final int prefix = name.indexOf('_');
25570        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25571        final String output = bits + " " + name;
25572        found.put(key, output);
25573    }
25574
25575    /** {@hide} */
25576    public void encode(@NonNull ViewHierarchyEncoder stream) {
25577        stream.beginObject(this);
25578        encodeProperties(stream);
25579        stream.endObject();
25580    }
25581
25582    /** {@hide} */
25583    @CallSuper
25584    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25585        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25586        if (resolveId instanceof String) {
25587            stream.addProperty("id", (String) resolveId);
25588        } else {
25589            stream.addProperty("id", mID);
25590        }
25591
25592        stream.addProperty("misc:transformation.alpha",
25593                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25594        stream.addProperty("misc:transitionName", getTransitionName());
25595
25596        // layout
25597        stream.addProperty("layout:left", mLeft);
25598        stream.addProperty("layout:right", mRight);
25599        stream.addProperty("layout:top", mTop);
25600        stream.addProperty("layout:bottom", mBottom);
25601        stream.addProperty("layout:width", getWidth());
25602        stream.addProperty("layout:height", getHeight());
25603        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25604        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25605        stream.addProperty("layout:hasTransientState", hasTransientState());
25606        stream.addProperty("layout:baseline", getBaseline());
25607
25608        // layout params
25609        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25610        if (layoutParams != null) {
25611            stream.addPropertyKey("layoutParams");
25612            layoutParams.encode(stream);
25613        }
25614
25615        // scrolling
25616        stream.addProperty("scrolling:scrollX", mScrollX);
25617        stream.addProperty("scrolling:scrollY", mScrollY);
25618
25619        // padding
25620        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25621        stream.addProperty("padding:paddingRight", mPaddingRight);
25622        stream.addProperty("padding:paddingTop", mPaddingTop);
25623        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25624        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25625        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25626        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25627        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25628        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25629
25630        // measurement
25631        stream.addProperty("measurement:minHeight", mMinHeight);
25632        stream.addProperty("measurement:minWidth", mMinWidth);
25633        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25634        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25635
25636        // drawing
25637        stream.addProperty("drawing:elevation", getElevation());
25638        stream.addProperty("drawing:translationX", getTranslationX());
25639        stream.addProperty("drawing:translationY", getTranslationY());
25640        stream.addProperty("drawing:translationZ", getTranslationZ());
25641        stream.addProperty("drawing:rotation", getRotation());
25642        stream.addProperty("drawing:rotationX", getRotationX());
25643        stream.addProperty("drawing:rotationY", getRotationY());
25644        stream.addProperty("drawing:scaleX", getScaleX());
25645        stream.addProperty("drawing:scaleY", getScaleY());
25646        stream.addProperty("drawing:pivotX", getPivotX());
25647        stream.addProperty("drawing:pivotY", getPivotY());
25648        stream.addProperty("drawing:opaque", isOpaque());
25649        stream.addProperty("drawing:alpha", getAlpha());
25650        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25651        stream.addProperty("drawing:shadow", hasShadow());
25652        stream.addProperty("drawing:solidColor", getSolidColor());
25653        stream.addProperty("drawing:layerType", mLayerType);
25654        stream.addProperty("drawing:willNotDraw", willNotDraw());
25655        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25656        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25657        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25658        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25659
25660        // focus
25661        stream.addProperty("focus:hasFocus", hasFocus());
25662        stream.addProperty("focus:isFocused", isFocused());
25663        stream.addProperty("focus:isFocusable", isFocusable());
25664        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25665
25666        stream.addProperty("misc:clickable", isClickable());
25667        stream.addProperty("misc:pressed", isPressed());
25668        stream.addProperty("misc:selected", isSelected());
25669        stream.addProperty("misc:touchMode", isInTouchMode());
25670        stream.addProperty("misc:hovered", isHovered());
25671        stream.addProperty("misc:activated", isActivated());
25672
25673        stream.addProperty("misc:visibility", getVisibility());
25674        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25675        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25676
25677        stream.addProperty("misc:enabled", isEnabled());
25678        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25679        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25680
25681        // theme attributes
25682        Resources.Theme theme = getContext().getTheme();
25683        if (theme != null) {
25684            stream.addPropertyKey("theme");
25685            theme.encode(stream);
25686        }
25687
25688        // view attribute information
25689        int n = mAttributes != null ? mAttributes.length : 0;
25690        stream.addProperty("meta:__attrCount__", n/2);
25691        for (int i = 0; i < n; i += 2) {
25692            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25693        }
25694
25695        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25696
25697        // text
25698        stream.addProperty("text:textDirection", getTextDirection());
25699        stream.addProperty("text:textAlignment", getTextAlignment());
25700
25701        // accessibility
25702        CharSequence contentDescription = getContentDescription();
25703        stream.addProperty("accessibility:contentDescription",
25704                contentDescription == null ? "" : contentDescription.toString());
25705        stream.addProperty("accessibility:labelFor", getLabelFor());
25706        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25707    }
25708
25709    /**
25710     * Determine if this view is rendered on a round wearable device and is the main view
25711     * on the screen.
25712     */
25713    boolean shouldDrawRoundScrollbar() {
25714        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25715            return false;
25716        }
25717
25718        final View rootView = getRootView();
25719        final WindowInsets insets = getRootWindowInsets();
25720
25721        int height = getHeight();
25722        int width = getWidth();
25723        int displayHeight = rootView.getHeight();
25724        int displayWidth = rootView.getWidth();
25725
25726        if (height != displayHeight || width != displayWidth) {
25727            return false;
25728        }
25729
25730        getLocationInWindow(mAttachInfo.mTmpLocation);
25731        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25732                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25733    }
25734
25735    /**
25736     * Sets the tooltip text which will be displayed in a small popup next to the view.
25737     * <p>
25738     * The tooltip will be displayed:
25739     * <ul>
25740     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
25741     * menu). </li>
25742     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25743     * </ul>
25744     * <p>
25745     * <strong>Note:</strong> Do not override this method, as it will have no
25746     * effect on the text displayed in the tooltip.
25747     *
25748     * @param tooltipText the tooltip text, or null if no tooltip is required
25749     * @see #getTooltipText()
25750     * @attr ref android.R.styleable#View_tooltipText
25751     */
25752    public void setTooltipText(@Nullable CharSequence tooltipText) {
25753        if (TextUtils.isEmpty(tooltipText)) {
25754            setFlags(0, TOOLTIP);
25755            hideTooltip();
25756            mTooltipInfo = null;
25757        } else {
25758            setFlags(TOOLTIP, TOOLTIP);
25759            if (mTooltipInfo == null) {
25760                mTooltipInfo = new TooltipInfo();
25761                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25762                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25763            }
25764            mTooltipInfo.mTooltipText = tooltipText;
25765            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25766                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25767            }
25768        }
25769    }
25770
25771    /**
25772     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25773     */
25774    public void setTooltip(@Nullable CharSequence tooltipText) {
25775        setTooltipText(tooltipText);
25776    }
25777
25778    /**
25779     * Returns the view's tooltip text.
25780     *
25781     * <strong>Note:</strong> Do not override this method, as it will have no
25782     * effect on the text displayed in the tooltip. You must call
25783     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25784     *
25785     * @return the tooltip text
25786     * @see #setTooltipText(CharSequence)
25787     * @attr ref android.R.styleable#View_tooltipText
25788     */
25789    @Nullable
25790    public CharSequence getTooltipText() {
25791        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25792    }
25793
25794    /**
25795     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25796     */
25797    @Nullable
25798    public CharSequence getTooltip() {
25799        return getTooltipText();
25800    }
25801
25802    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25803        if (mAttachInfo == null || mTooltipInfo == null) {
25804            return false;
25805        }
25806        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25807            return false;
25808        }
25809        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25810            return false;
25811        }
25812        hideTooltip();
25813        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25814        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25815        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25816        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25817        mAttachInfo.mTooltipHost = this;
25818        return true;
25819    }
25820
25821    void hideTooltip() {
25822        if (mTooltipInfo == null) {
25823            return;
25824        }
25825        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25826        if (mTooltipInfo.mTooltipPopup == null) {
25827            return;
25828        }
25829        mTooltipInfo.mTooltipPopup.hide();
25830        mTooltipInfo.mTooltipPopup = null;
25831        mTooltipInfo.mTooltipFromLongClick = false;
25832        if (mAttachInfo != null) {
25833            mAttachInfo.mTooltipHost = null;
25834        }
25835    }
25836
25837    private boolean showLongClickTooltip(int x, int y) {
25838        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25839        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25840        return showTooltip(x, y, true);
25841    }
25842
25843    private void showHoverTooltip() {
25844        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25845    }
25846
25847    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25848        if (mTooltipInfo == null) {
25849            return false;
25850        }
25851        switch(event.getAction()) {
25852            case MotionEvent.ACTION_HOVER_MOVE:
25853                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25854                    break;
25855                }
25856                if (!mTooltipInfo.mTooltipFromLongClick) {
25857                    if (mTooltipInfo.mTooltipPopup == null) {
25858                        // Schedule showing the tooltip after a timeout.
25859                        mTooltipInfo.mAnchorX = (int) event.getX();
25860                        mTooltipInfo.mAnchorY = (int) event.getY();
25861                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25862                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25863                                ViewConfiguration.getHoverTooltipShowTimeout());
25864                    }
25865
25866                    // Hide hover-triggered tooltip after a period of inactivity.
25867                    // Match the timeout used by NativeInputManager to hide the mouse pointer
25868                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
25869                    final int timeout;
25870                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
25871                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
25872                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
25873                    } else {
25874                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
25875                    }
25876                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25877                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
25878                }
25879                return true;
25880
25881            case MotionEvent.ACTION_HOVER_EXIT:
25882                if (!mTooltipInfo.mTooltipFromLongClick) {
25883                    hideTooltip();
25884                }
25885                break;
25886        }
25887        return false;
25888    }
25889
25890    void handleTooltipKey(KeyEvent event) {
25891        switch (event.getAction()) {
25892            case KeyEvent.ACTION_DOWN:
25893                if (event.getRepeatCount() == 0) {
25894                    hideTooltip();
25895                }
25896                break;
25897
25898            case KeyEvent.ACTION_UP:
25899                handleTooltipUp();
25900                break;
25901        }
25902    }
25903
25904    private void handleTooltipUp() {
25905        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25906            return;
25907        }
25908        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25909        postDelayed(mTooltipInfo.mHideTooltipRunnable,
25910                ViewConfiguration.getLongPressTooltipHideTimeout());
25911    }
25912
25913    private int getFocusableAttribute(TypedArray attributes) {
25914        TypedValue val = new TypedValue();
25915        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
25916            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
25917                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
25918            } else {
25919                return val.data;
25920            }
25921        } else {
25922            return FOCUSABLE_AUTO;
25923        }
25924    }
25925
25926    /**
25927     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
25928     * is not showing.
25929     * @hide
25930     */
25931    @TestApi
25932    public View getTooltipView() {
25933        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25934            return null;
25935        }
25936        return mTooltipInfo.mTooltipPopup.getContentView();
25937    }
25938}
25939