View.java revision 37bf8b17364c444aabfcaaed8081b3830202c5e6
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.os.Build;
65import android.os.Bundle;
66import android.os.Handler;
67import android.os.IBinder;
68import android.os.Parcel;
69import android.os.Parcelable;
70import android.os.RemoteException;
71import android.os.SystemClock;
72import android.os.SystemProperties;
73import android.os.Trace;
74import android.text.TextUtils;
75import android.util.AttributeSet;
76import android.util.FloatProperty;
77import android.util.LayoutDirection;
78import android.util.Log;
79import android.util.LongSparseLongArray;
80import android.util.Pools.SynchronizedPool;
81import android.util.Property;
82import android.util.SparseArray;
83import android.util.StateSet;
84import android.util.SuperNotCalledException;
85import android.util.TypedValue;
86import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
87import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
88import android.view.AccessibilityIterators.TextSegmentIterator;
89import android.view.AccessibilityIterators.WordTextSegmentIterator;
90import android.view.ContextMenu.ContextMenuInfo;
91import android.view.accessibility.AccessibilityEvent;
92import android.view.accessibility.AccessibilityEventSource;
93import android.view.accessibility.AccessibilityManager;
94import android.view.accessibility.AccessibilityNodeInfo;
95import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
96import android.view.accessibility.AccessibilityNodeProvider;
97import android.view.accessibility.AccessibilityWindowInfo;
98import android.view.animation.Animation;
99import android.view.animation.AnimationUtils;
100import android.view.animation.Transformation;
101import android.view.autofill.AutofillManager;
102import android.view.autofill.AutofillValue;
103import android.view.inputmethod.EditorInfo;
104import android.view.inputmethod.InputConnection;
105import android.view.inputmethod.InputMethodManager;
106import android.widget.Checkable;
107import android.widget.FrameLayout;
108import android.widget.ScrollBarDrawable;
109
110import com.android.internal.R;
111import com.android.internal.util.Preconditions;
112import com.android.internal.view.TooltipPopup;
113import com.android.internal.view.menu.MenuBuilder;
114import com.android.internal.widget.ScrollBarUtils;
115
116import com.google.android.collect.Lists;
117import com.google.android.collect.Maps;
118
119import java.lang.annotation.Retention;
120import java.lang.annotation.RetentionPolicy;
121import java.lang.ref.WeakReference;
122import java.lang.reflect.Field;
123import java.lang.reflect.InvocationTargetException;
124import java.lang.reflect.Method;
125import java.lang.reflect.Modifier;
126import java.util.ArrayList;
127import java.util.Arrays;
128import java.util.Collection;
129import java.util.Collections;
130import java.util.HashMap;
131import java.util.List;
132import java.util.Locale;
133import java.util.Map;
134import java.util.concurrent.CopyOnWriteArrayList;
135import java.util.concurrent.atomic.AtomicInteger;
136import java.util.function.Predicate;
137
138/**
139 * <p>
140 * This class represents the basic building block for user interface components. A View
141 * occupies a rectangular area on the screen and is responsible for drawing and
142 * event handling. View is the base class for <em>widgets</em>, which are
143 * used to create interactive UI components (buttons, text fields, etc.). The
144 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
145 * are invisible containers that hold other Views (or other ViewGroups) and define
146 * their layout properties.
147 * </p>
148 *
149 * <div class="special reference">
150 * <h3>Developer Guides</h3>
151 * <p>For information about using this class to develop your application's user interface,
152 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
153 * </div>
154 *
155 * <a name="Using"></a>
156 * <h3>Using Views</h3>
157 * <p>
158 * All of the views in a window are arranged in a single tree. You can add views
159 * either from code or by specifying a tree of views in one or more XML layout
160 * files. There are many specialized subclasses of views that act as controls or
161 * are capable of displaying text, images, or other content.
162 * </p>
163 * <p>
164 * Once you have created a tree of views, there are typically a few types of
165 * common operations you may wish to perform:
166 * <ul>
167 * <li><strong>Set properties:</strong> for example setting the text of a
168 * {@link android.widget.TextView}. The available properties and the methods
169 * that set them will vary among the different subclasses of views. Note that
170 * properties that are known at build time can be set in the XML layout
171 * files.</li>
172 * <li><strong>Set focus:</strong> The framework will handle moving focus in
173 * response to user input. To force focus to a specific view, call
174 * {@link #requestFocus}.</li>
175 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
176 * that will be notified when something interesting happens to the view. For
177 * example, all views will let you set a listener to be notified when the view
178 * gains or loses focus. You can register such a listener using
179 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
180 * Other view subclasses offer more specialized listeners. For example, a Button
181 * exposes a listener to notify clients when the button is clicked.</li>
182 * <li><strong>Set visibility:</strong> You can hide or show views using
183 * {@link #setVisibility(int)}.</li>
184 * </ul>
185 * </p>
186 * <p><em>
187 * Note: The Android framework is responsible for measuring, laying out and
188 * drawing views. You should not call methods that perform these actions on
189 * views yourself unless you are actually implementing a
190 * {@link android.view.ViewGroup}.
191 * </em></p>
192 *
193 * <a name="Lifecycle"></a>
194 * <h3>Implementing a Custom View</h3>
195 *
196 * <p>
197 * To implement a custom view, you will usually begin by providing overrides for
198 * some of the standard methods that the framework calls on all views. You do
199 * not need to override all of these methods. In fact, you can start by just
200 * overriding {@link #onDraw(android.graphics.Canvas)}.
201 * <table border="2" width="85%" align="center" cellpadding="5">
202 *     <thead>
203 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
204 *     </thead>
205 *
206 *     <tbody>
207 *     <tr>
208 *         <td rowspan="2">Creation</td>
209 *         <td>Constructors</td>
210 *         <td>There is a form of the constructor that are called when the view
211 *         is created from code and a form that is called when the view is
212 *         inflated from a layout file. The second form should parse and apply
213 *         any attributes defined in the layout file.
214 *         </td>
215 *     </tr>
216 *     <tr>
217 *         <td><code>{@link #onFinishInflate()}</code></td>
218 *         <td>Called after a view and all of its children has been inflated
219 *         from XML.</td>
220 *     </tr>
221 *
222 *     <tr>
223 *         <td rowspan="3">Layout</td>
224 *         <td><code>{@link #onMeasure(int, int)}</code></td>
225 *         <td>Called to determine the size requirements for this view and all
226 *         of its children.
227 *         </td>
228 *     </tr>
229 *     <tr>
230 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
231 *         <td>Called when this view should assign a size and position to all
232 *         of its children.
233 *         </td>
234 *     </tr>
235 *     <tr>
236 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
237 *         <td>Called when the size of this view has changed.
238 *         </td>
239 *     </tr>
240 *
241 *     <tr>
242 *         <td>Drawing</td>
243 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
244 *         <td>Called when the view should render its content.
245 *         </td>
246 *     </tr>
247 *
248 *     <tr>
249 *         <td rowspan="4">Event processing</td>
250 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
251 *         <td>Called when a new hardware key event occurs.
252 *         </td>
253 *     </tr>
254 *     <tr>
255 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
256 *         <td>Called when a hardware key up event occurs.
257 *         </td>
258 *     </tr>
259 *     <tr>
260 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
261 *         <td>Called when a trackball motion event occurs.
262 *         </td>
263 *     </tr>
264 *     <tr>
265 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
266 *         <td>Called when a touch screen motion event occurs.
267 *         </td>
268 *     </tr>
269 *
270 *     <tr>
271 *         <td rowspan="2">Focus</td>
272 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
273 *         <td>Called when the view gains or loses focus.
274 *         </td>
275 *     </tr>
276 *
277 *     <tr>
278 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
279 *         <td>Called when the window containing the view gains or loses focus.
280 *         </td>
281 *     </tr>
282 *
283 *     <tr>
284 *         <td rowspan="3">Attaching</td>
285 *         <td><code>{@link #onAttachedToWindow()}</code></td>
286 *         <td>Called when the view is attached to a window.
287 *         </td>
288 *     </tr>
289 *
290 *     <tr>
291 *         <td><code>{@link #onDetachedFromWindow}</code></td>
292 *         <td>Called when the view is detached from its window.
293 *         </td>
294 *     </tr>
295 *
296 *     <tr>
297 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
298 *         <td>Called when the visibility of the window containing the view
299 *         has changed.
300 *         </td>
301 *     </tr>
302 *     </tbody>
303 *
304 * </table>
305 * </p>
306 *
307 * <a name="IDs"></a>
308 * <h3>IDs</h3>
309 * Views may have an integer id associated with them. These ids are typically
310 * assigned in the layout XML files, and are used to find specific views within
311 * the view tree. A common pattern is to:
312 * <ul>
313 * <li>Define a Button in the layout file and assign it a unique ID.
314 * <pre>
315 * &lt;Button
316 *     android:id="@+id/my_button"
317 *     android:layout_width="wrap_content"
318 *     android:layout_height="wrap_content"
319 *     android:text="@string/my_button_text"/&gt;
320 * </pre></li>
321 * <li>From the onCreate method of an Activity, find the Button
322 * <pre class="prettyprint">
323 *      Button myButton = (Button) findViewById(R.id.my_button);
324 * </pre></li>
325 * </ul>
326 * <p>
327 * View IDs need not be unique throughout the tree, but it is good practice to
328 * ensure that they are at least unique within the part of the tree you are
329 * searching.
330 * </p>
331 *
332 * <a name="Position"></a>
333 * <h3>Position</h3>
334 * <p>
335 * The geometry of a view is that of a rectangle. A view has a location,
336 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
337 * two dimensions, expressed as a width and a height. The unit for location
338 * and dimensions is the pixel.
339 * </p>
340 *
341 * <p>
342 * It is possible to retrieve the location of a view by invoking the methods
343 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
344 * coordinate of the rectangle representing the view. The latter returns the
345 * top, or Y, coordinate of the rectangle representing the view. These methods
346 * both return the location of the view relative to its parent. For instance,
347 * when getLeft() returns 20, that means the view is located 20 pixels to the
348 * right of the left edge of its direct parent.
349 * </p>
350 *
351 * <p>
352 * In addition, several convenience methods are offered to avoid unnecessary
353 * computations, namely {@link #getRight()} and {@link #getBottom()}.
354 * These methods return the coordinates of the right and bottom edges of the
355 * rectangle representing the view. For instance, calling {@link #getRight()}
356 * is similar to the following computation: <code>getLeft() + getWidth()</code>
357 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
358 * </p>
359 *
360 * <a name="SizePaddingMargins"></a>
361 * <h3>Size, padding and margins</h3>
362 * <p>
363 * The size of a view is expressed with a width and a height. A view actually
364 * possess two pairs of width and height values.
365 * </p>
366 *
367 * <p>
368 * The first pair is known as <em>measured width</em> and
369 * <em>measured height</em>. These dimensions define how big a view wants to be
370 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
371 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
372 * and {@link #getMeasuredHeight()}.
373 * </p>
374 *
375 * <p>
376 * The second pair is simply known as <em>width</em> and <em>height</em>, or
377 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
378 * dimensions define the actual size of the view on screen, at drawing time and
379 * after layout. These values may, but do not have to, be different from the
380 * measured width and height. The width and height can be obtained by calling
381 * {@link #getWidth()} and {@link #getHeight()}.
382 * </p>
383 *
384 * <p>
385 * To measure its dimensions, a view takes into account its padding. The padding
386 * is expressed in pixels for the left, top, right and bottom parts of the view.
387 * Padding can be used to offset the content of the view by a specific amount of
388 * pixels. For instance, a left padding of 2 will push the view's content by
389 * 2 pixels to the right of the left edge. Padding can be set using the
390 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
391 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
392 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
393 * {@link #getPaddingEnd()}.
394 * </p>
395 *
396 * <p>
397 * Even though a view can define a padding, it does not provide any support for
398 * margins. However, view groups provide such a support. Refer to
399 * {@link android.view.ViewGroup} and
400 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
401 * </p>
402 *
403 * <a name="Layout"></a>
404 * <h3>Layout</h3>
405 * <p>
406 * Layout is a two pass process: a measure pass and a layout pass. The measuring
407 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
408 * of the view tree. Each view pushes dimension specifications down the tree
409 * during the recursion. At the end of the measure pass, every view has stored
410 * its measurements. The second pass happens in
411 * {@link #layout(int,int,int,int)} and is also top-down. During
412 * this pass each parent is responsible for positioning all of its children
413 * using the sizes computed in the measure pass.
414 * </p>
415 *
416 * <p>
417 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
418 * {@link #getMeasuredHeight()} values must be set, along with those for all of
419 * that view's descendants. A view's measured width and measured height values
420 * must respect the constraints imposed by the view's parents. This guarantees
421 * that at the end of the measure pass, all parents accept all of their
422 * children's measurements. A parent view may call measure() more than once on
423 * its children. For example, the parent may measure each child once with
424 * unspecified dimensions to find out how big they want to be, then call
425 * measure() on them again with actual numbers if the sum of all the children's
426 * unconstrained sizes is too big or too small.
427 * </p>
428 *
429 * <p>
430 * The measure pass uses two classes to communicate dimensions. The
431 * {@link MeasureSpec} class is used by views to tell their parents how they
432 * want to be measured and positioned. The base LayoutParams class just
433 * describes how big the view wants to be for both width and height. For each
434 * dimension, it can specify one of:
435 * <ul>
436 * <li> an exact number
437 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
438 * (minus padding)
439 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
440 * enclose its content (plus padding).
441 * </ul>
442 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
443 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
444 * an X and Y value.
445 * </p>
446 *
447 * <p>
448 * MeasureSpecs are used to push requirements down the tree from parent to
449 * child. A MeasureSpec can be in one of three modes:
450 * <ul>
451 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
452 * of a child view. For example, a LinearLayout may call measure() on its child
453 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
454 * tall the child view wants to be given a width of 240 pixels.
455 * <li>EXACTLY: This is used by the parent to impose an exact size on the
456 * child. The child must use this size, and guarantee that all of its
457 * descendants will fit within this size.
458 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
459 * child. The child must guarantee that it and all of its descendants will fit
460 * within this size.
461 * </ul>
462 * </p>
463 *
464 * <p>
465 * To initiate a layout, call {@link #requestLayout}. This method is typically
466 * called by a view on itself when it believes that is can no longer fit within
467 * its current bounds.
468 * </p>
469 *
470 * <a name="Drawing"></a>
471 * <h3>Drawing</h3>
472 * <p>
473 * Drawing is handled by walking the tree and recording the drawing commands of
474 * any View that needs to update. After this, the drawing commands of the
475 * entire tree are issued to screen, clipped to the newly damaged area.
476 * </p>
477 *
478 * <p>
479 * The tree is largely recorded and drawn in order, with parents drawn before
480 * (i.e., behind) their children, with siblings drawn in the order they appear
481 * in the tree. If you set a background drawable for a View, then the View will
482 * draw it before calling back to its <code>onDraw()</code> method. The child
483 * drawing order can be overridden with
484 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
485 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
486 * </p>
487 *
488 * <p>
489 * To force a view to draw, call {@link #invalidate()}.
490 * </p>
491 *
492 * <a name="EventHandlingThreading"></a>
493 * <h3>Event Handling and Threading</h3>
494 * <p>
495 * The basic cycle of a view is as follows:
496 * <ol>
497 * <li>An event comes in and is dispatched to the appropriate view. The view
498 * handles the event and notifies any listeners.</li>
499 * <li>If in the course of processing the event, the view's bounds may need
500 * to be changed, the view will call {@link #requestLayout()}.</li>
501 * <li>Similarly, if in the course of processing the event the view's appearance
502 * may need to be changed, the view will call {@link #invalidate()}.</li>
503 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
504 * the framework will take care of measuring, laying out, and drawing the tree
505 * as appropriate.</li>
506 * </ol>
507 * </p>
508 *
509 * <p><em>Note: The entire view tree is single threaded. You must always be on
510 * the UI thread when calling any method on any view.</em>
511 * If you are doing work on other threads and want to update the state of a view
512 * from that thread, you should use a {@link Handler}.
513 * </p>
514 *
515 * <a name="FocusHandling"></a>
516 * <h3>Focus Handling</h3>
517 * <p>
518 * The framework will handle routine focus movement in response to user input.
519 * This includes changing the focus as views are removed or hidden, or as new
520 * views become available. Views indicate their willingness to take focus
521 * through the {@link #isFocusable} method. To change whether a view can take
522 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
523 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
524 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
525 * </p>
526 * <p>
527 * Focus movement is based on an algorithm which finds the nearest neighbor in a
528 * given direction. In rare cases, the default algorithm may not match the
529 * intended behavior of the developer. In these situations, you can provide
530 * explicit overrides by using these XML attributes in the layout file:
531 * <pre>
532 * nextFocusDown
533 * nextFocusLeft
534 * nextFocusRight
535 * nextFocusUp
536 * </pre>
537 * </p>
538 *
539 *
540 * <p>
541 * To get a particular view to take focus, call {@link #requestFocus()}.
542 * </p>
543 *
544 * <a name="TouchMode"></a>
545 * <h3>Touch Mode</h3>
546 * <p>
547 * When a user is navigating a user interface via directional keys such as a D-pad, it is
548 * necessary to give focus to actionable items such as buttons so the user can see
549 * what will take input.  If the device has touch capabilities, however, and the user
550 * begins interacting with the interface by touching it, it is no longer necessary to
551 * always highlight, or give focus to, a particular view.  This motivates a mode
552 * for interaction named 'touch mode'.
553 * </p>
554 * <p>
555 * For a touch capable device, once the user touches the screen, the device
556 * will enter touch mode.  From this point onward, only views for which
557 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
558 * Other views that are touchable, like buttons, will not take focus when touched; they will
559 * only fire the on click listeners.
560 * </p>
561 * <p>
562 * Any time a user hits a directional key, such as a D-pad direction, the view device will
563 * exit touch mode, and find a view to take focus, so that the user may resume interacting
564 * with the user interface without touching the screen again.
565 * </p>
566 * <p>
567 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
568 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
569 * </p>
570 *
571 * <a name="Scrolling"></a>
572 * <h3>Scrolling</h3>
573 * <p>
574 * The framework provides basic support for views that wish to internally
575 * scroll their content. This includes keeping track of the X and Y scroll
576 * offset as well as mechanisms for drawing scrollbars. See
577 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
578 * {@link #awakenScrollBars()} for more details.
579 * </p>
580 *
581 * <a name="Tags"></a>
582 * <h3>Tags</h3>
583 * <p>
584 * Unlike IDs, tags are not used to identify views. Tags are essentially an
585 * extra piece of information that can be associated with a view. They are most
586 * often used as a convenience to store data related to views in the views
587 * themselves rather than by putting them in a separate structure.
588 * </p>
589 * <p>
590 * Tags may be specified with character sequence values in layout XML as either
591 * a single tag using the {@link android.R.styleable#View_tag android:tag}
592 * attribute or multiple tags using the {@code <tag>} child element:
593 * <pre>
594 *     &ltView ...
595 *           android:tag="@string/mytag_value" /&gt;
596 *     &ltView ...&gt;
597 *         &lttag android:id="@+id/mytag"
598 *              android:value="@string/mytag_value" /&gt;
599 *     &lt/View>
600 * </pre>
601 * </p>
602 * <p>
603 * Tags may also be specified with arbitrary objects from code using
604 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
605 * </p>
606 *
607 * <a name="Themes"></a>
608 * <h3>Themes</h3>
609 * <p>
610 * By default, Views are created using the theme of the Context object supplied
611 * to their constructor; however, a different theme may be specified by using
612 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
613 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
614 * code.
615 * </p>
616 * <p>
617 * When the {@link android.R.styleable#View_theme android:theme} attribute is
618 * used in XML, the specified theme is applied on top of the inflation
619 * context's theme (see {@link LayoutInflater}) and used for the view itself as
620 * well as any child elements.
621 * </p>
622 * <p>
623 * In the following example, both views will be created using the Material dark
624 * color scheme; however, because an overlay theme is used which only defines a
625 * subset of attributes, the value of
626 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
627 * the inflation context's theme (e.g. the Activity theme) will be preserved.
628 * <pre>
629 *     &ltLinearLayout
630 *             ...
631 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
632 *         &ltView ...&gt;
633 *     &lt/LinearLayout&gt;
634 * </pre>
635 * </p>
636 *
637 * <a name="Properties"></a>
638 * <h3>Properties</h3>
639 * <p>
640 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
641 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
642 * available both in the {@link Property} form as well as in similarly-named setter/getter
643 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
644 * be used to set persistent state associated with these rendering-related properties on the view.
645 * The properties and methods can also be used in conjunction with
646 * {@link android.animation.Animator Animator}-based animations, described more in the
647 * <a href="#Animation">Animation</a> section.
648 * </p>
649 *
650 * <a name="Animation"></a>
651 * <h3>Animation</h3>
652 * <p>
653 * Starting with Android 3.0, the preferred way of animating views is to use the
654 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
655 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
656 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
657 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
658 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
659 * makes animating these View properties particularly easy and efficient.
660 * </p>
661 * <p>
662 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
663 * You can attach an {@link Animation} object to a view using
664 * {@link #setAnimation(Animation)} or
665 * {@link #startAnimation(Animation)}. The animation can alter the scale,
666 * rotation, translation and alpha of a view over time. If the animation is
667 * attached to a view that has children, the animation will affect the entire
668 * subtree rooted by that node. When an animation is started, the framework will
669 * take care of redrawing the appropriate views until the animation completes.
670 * </p>
671 *
672 * <a name="Security"></a>
673 * <h3>Security</h3>
674 * <p>
675 * Sometimes it is essential that an application be able to verify that an action
676 * is being performed with the full knowledge and consent of the user, such as
677 * granting a permission request, making a purchase or clicking on an advertisement.
678 * Unfortunately, a malicious application could try to spoof the user into
679 * performing these actions, unaware, by concealing the intended purpose of the view.
680 * As a remedy, the framework offers a touch filtering mechanism that can be used to
681 * improve the security of views that provide access to sensitive functionality.
682 * </p><p>
683 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
684 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
685 * will discard touches that are received whenever the view's window is obscured by
686 * another visible window.  As a result, the view will not receive touches whenever a
687 * toast, dialog or other window appears above the view's window.
688 * </p><p>
689 * For more fine-grained control over security, consider overriding the
690 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
691 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
692 * </p>
693 *
694 * @attr ref android.R.styleable#View_alpha
695 * @attr ref android.R.styleable#View_background
696 * @attr ref android.R.styleable#View_clickable
697 * @attr ref android.R.styleable#View_contentDescription
698 * @attr ref android.R.styleable#View_drawingCacheQuality
699 * @attr ref android.R.styleable#View_duplicateParentState
700 * @attr ref android.R.styleable#View_id
701 * @attr ref android.R.styleable#View_requiresFadingEdge
702 * @attr ref android.R.styleable#View_fadeScrollbars
703 * @attr ref android.R.styleable#View_fadingEdgeLength
704 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
705 * @attr ref android.R.styleable#View_fitsSystemWindows
706 * @attr ref android.R.styleable#View_isScrollContainer
707 * @attr ref android.R.styleable#View_focusable
708 * @attr ref android.R.styleable#View_focusableInTouchMode
709 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
710 * @attr ref android.R.styleable#View_keepScreenOn
711 * @attr ref android.R.styleable#View_layerType
712 * @attr ref android.R.styleable#View_layoutDirection
713 * @attr ref android.R.styleable#View_longClickable
714 * @attr ref android.R.styleable#View_minHeight
715 * @attr ref android.R.styleable#View_minWidth
716 * @attr ref android.R.styleable#View_nextFocusDown
717 * @attr ref android.R.styleable#View_nextFocusLeft
718 * @attr ref android.R.styleable#View_nextFocusRight
719 * @attr ref android.R.styleable#View_nextFocusUp
720 * @attr ref android.R.styleable#View_onClick
721 * @attr ref android.R.styleable#View_padding
722 * @attr ref android.R.styleable#View_paddingBottom
723 * @attr ref android.R.styleable#View_paddingLeft
724 * @attr ref android.R.styleable#View_paddingRight
725 * @attr ref android.R.styleable#View_paddingTop
726 * @attr ref android.R.styleable#View_paddingStart
727 * @attr ref android.R.styleable#View_paddingEnd
728 * @attr ref android.R.styleable#View_saveEnabled
729 * @attr ref android.R.styleable#View_rotation
730 * @attr ref android.R.styleable#View_rotationX
731 * @attr ref android.R.styleable#View_rotationY
732 * @attr ref android.R.styleable#View_scaleX
733 * @attr ref android.R.styleable#View_scaleY
734 * @attr ref android.R.styleable#View_scrollX
735 * @attr ref android.R.styleable#View_scrollY
736 * @attr ref android.R.styleable#View_scrollbarSize
737 * @attr ref android.R.styleable#View_scrollbarStyle
738 * @attr ref android.R.styleable#View_scrollbars
739 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
740 * @attr ref android.R.styleable#View_scrollbarFadeDuration
741 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
742 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
743 * @attr ref android.R.styleable#View_scrollbarThumbVertical
744 * @attr ref android.R.styleable#View_scrollbarTrackVertical
745 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
746 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
747 * @attr ref android.R.styleable#View_stateListAnimator
748 * @attr ref android.R.styleable#View_transitionName
749 * @attr ref android.R.styleable#View_soundEffectsEnabled
750 * @attr ref android.R.styleable#View_tag
751 * @attr ref android.R.styleable#View_textAlignment
752 * @attr ref android.R.styleable#View_textDirection
753 * @attr ref android.R.styleable#View_transformPivotX
754 * @attr ref android.R.styleable#View_transformPivotY
755 * @attr ref android.R.styleable#View_translationX
756 * @attr ref android.R.styleable#View_translationY
757 * @attr ref android.R.styleable#View_translationZ
758 * @attr ref android.R.styleable#View_visibility
759 * @attr ref android.R.styleable#View_theme
760 *
761 * @see android.view.ViewGroup
762 */
763@UiThread
764public class View implements Drawable.Callback, KeyEvent.Callback,
765        AccessibilityEventSource {
766    private static final boolean DBG = false;
767
768    /** @hide */
769    public static boolean DEBUG_DRAW = false;
770
771    /**
772     * The logging tag used by this class with android.util.Log.
773     */
774    protected static final String VIEW_LOG_TAG = "View";
775
776    /**
777     * When set to true, apps will draw debugging information about their layouts.
778     *
779     * @hide
780     */
781    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
782
783    /**
784     * When set to true, this view will save its attribute data.
785     *
786     * @hide
787     */
788    public static boolean mDebugViewAttributes = false;
789
790    /**
791     * Used to mark a View that has no ID.
792     */
793    public static final int NO_ID = -1;
794
795    /**
796     * Signals that compatibility booleans have been initialized according to
797     * target SDK versions.
798     */
799    private static boolean sCompatibilityDone = false;
800
801    /**
802     * Use the old (broken) way of building MeasureSpecs.
803     */
804    private static boolean sUseBrokenMakeMeasureSpec = false;
805
806    /**
807     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
808     */
809    static boolean sUseZeroUnspecifiedMeasureSpec = false;
810
811    /**
812     * Ignore any optimizations using the measure cache.
813     */
814    private static boolean sIgnoreMeasureCache = false;
815
816    /**
817     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
818     */
819    private static boolean sAlwaysRemeasureExactly = false;
820
821    /**
822     * Relax constraints around whether setLayoutParams() must be called after
823     * modifying the layout params.
824     */
825    private static boolean sLayoutParamsAlwaysChanged = false;
826
827    /**
828     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
829     * without throwing
830     */
831    static boolean sTextureViewIgnoresDrawableSetters = false;
832
833    /**
834     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
835     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
836     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
837     * check is implemented for backwards compatibility.
838     *
839     * {@hide}
840     */
841    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
842
843    /**
844     * Prior to N, when drag enters into child of a view that has already received an
845     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
846     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
847     * false from its event handler for these events.
848     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
849     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
850     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
851     */
852    static boolean sCascadedDragDrop;
853
854    /**
855     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
856     * to determine things like whether or not to permit item click events. We can't break
857     * apps that do this just because more things (clickable things) are now auto-focusable
858     * and they would get different results, so give old behavior to old apps.
859     */
860    static boolean sHasFocusableExcludeAutoFocusable;
861
862    /**
863     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
864     * made focusable by default. As a result, apps could (incorrectly) change the clickable
865     * setting of views off the UI thread. Now that clickable can effect the focusable state,
866     * changing the clickable attribute off the UI thread will cause an exception (since changing
867     * the focusable state checks). In order to prevent apps from crashing, we will handle this
868     * specific case and just not notify parents on new focusables resulting from marking views
869     * clickable from outside the UI thread.
870     */
871    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
872
873    /** @hide */
874    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
875    @Retention(RetentionPolicy.SOURCE)
876    public @interface Focusable {}
877
878    /**
879     * This view does not want keystrokes.
880     * <p>
881     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
882     * android:focusable}.
883     */
884    public static final int NOT_FOCUSABLE = 0x00000000;
885
886    /**
887     * This view wants keystrokes.
888     * <p>
889     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
890     * android:focusable}.
891     */
892    public static final int FOCUSABLE = 0x00000001;
893
894    /**
895     * This view determines focusability automatically. This is the default.
896     * <p>
897     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
898     * android:focusable}.
899     */
900    public static final int FOCUSABLE_AUTO = 0x00000010;
901
902    /**
903     * Mask for use with setFlags indicating bits used for focus.
904     */
905    private static final int FOCUSABLE_MASK = 0x00000011;
906
907    /**
908     * This view will adjust its padding to fit sytem windows (e.g. status bar)
909     */
910    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
911
912    /** @hide */
913    @IntDef({VISIBLE, INVISIBLE, GONE})
914    @Retention(RetentionPolicy.SOURCE)
915    public @interface Visibility {}
916
917    /**
918     * This view is visible.
919     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
920     * android:visibility}.
921     */
922    public static final int VISIBLE = 0x00000000;
923
924    /**
925     * This view is invisible, but it still takes up space for layout purposes.
926     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
927     * android:visibility}.
928     */
929    public static final int INVISIBLE = 0x00000004;
930
931    /**
932     * This view is invisible, and it doesn't take any space for layout
933     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
934     * android:visibility}.
935     */
936    public static final int GONE = 0x00000008;
937
938    /**
939     * Mask for use with setFlags indicating bits used for visibility.
940     * {@hide}
941     */
942    static final int VISIBILITY_MASK = 0x0000000C;
943
944    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
945
946    /** @hide */
947    @IntDef({
948            AUTOFILL_MODE_INHERIT,
949            AUTOFILL_MODE_AUTO,
950            AUTOFILL_MODE_MANUAL
951    })
952    @Retention(RetentionPolicy.SOURCE)
953    public @interface AutofillMode {}
954
955    /**
956     * This view inherits the autofill state from it's parent. If there is no parent it is
957     * {@link #AUTOFILL_MODE_AUTO}.
958     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
959     * {@code android:autofillMode}.
960     */
961    public static final int AUTOFILL_MODE_INHERIT = 0;
962
963    /**
964     * Allows this view to automatically trigger an autofill request when it get focus.
965     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
966     * {@code android:autofillMode}.
967     */
968    public static final int AUTOFILL_MODE_AUTO = 1;
969
970    /**
971     * Do not trigger an autofill request if this view is focused. The user can still force
972     * an autofill request.
973     * <p>This does not prevent this field from being autofilled if an autofill operation is
974     * triggered from a different view.</p>
975     *
976     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code
977     * android:autofillMode}.
978     */
979    public static final int AUTOFILL_MODE_MANUAL = 2;
980
981    /**
982     * This view contains an email address.
983     *
984     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_EMAIL_ADDRESS}"
985     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
986     */
987    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
988
989    /**
990     * The view contains a real name.
991     *
992     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_NAME}" to
993     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
994     */
995    public static final String AUTOFILL_HINT_NAME = "name";
996
997    /**
998     * The view contains a user name.
999     *
1000     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_USERNAME}" to
1001     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1002     */
1003    public static final String AUTOFILL_HINT_USERNAME = "username";
1004
1005    /**
1006     * The view contains a password.
1007     *
1008     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_PASSWORD}" to
1009     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1010     */
1011    public static final String AUTOFILL_HINT_PASSWORD = "password";
1012
1013    /**
1014     * The view contains a phone number.
1015     *
1016     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_PHONE}" to
1017     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1018     */
1019    public static final String AUTOFILL_HINT_PHONE = "phone";
1020
1021    /**
1022     * The view contains a postal address.
1023     *
1024     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_ADDRESS}"
1025     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1026     */
1027    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1028
1029    /**
1030     * The view contains a postal code.
1031     *
1032     * Use with {@link #setAutofillHint(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_CODE}" to
1033     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1034     */
1035    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1036
1037    /**
1038     * The view contains a credit card number.
1039     *
1040     * Use with {@link #setAutofillHint(String[])}, or set "{@value
1041     * #AUTOFILL_HINT_CREDIT_CARD_NUMBER}" to <a href="#attr_android:autofillHint"> {@code
1042     * android:autofillHint}.
1043     */
1044    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1045
1046    /**
1047     * The view contains a credit card security code.
1048     *
1049     * Use with {@link #setAutofillHint(String[])}, or set "{@value
1050     * #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}" to <a href="#attr_android:autofillHint"> {@code
1051     * android:autofillHint}.
1052     */
1053    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1054
1055    /**
1056     * The view contains a credit card expiration date.
1057     *
1058     * Use with {@link #setAutofillHint(String[])}, or set "{@value
1059     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}" to <a href="#attr_android:autofillHint"> {@code
1060     * android:autofillHint}.
1061     */
1062    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1063            "creditCardExpirationDate";
1064
1065    /**
1066     * The view contains the month a credit card expires.
1067     *
1068     * Use with {@link #setAutofillHint(String[])}, or set "{@value
1069     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}" to <a href="#attr_android:autofillHint"> {@code
1070     * android:autofillHint}.
1071     */
1072    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1073            "creditCardExpirationMonth";
1074
1075    /**
1076     * The view contains the year a credit card expires.
1077     *
1078     * Use with {@link #setAutofillHint(String[])}, or set "{@value
1079     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}" to <a href="#attr_android:autofillHint"> {@code
1080     * android:autofillHint}.
1081     */
1082    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1083            "creditCardExpirationYear";
1084
1085    /**
1086     * The view contains the day a credit card expires.
1087     *
1088     * Use with {@link #setAutofillHint(String[])}, or set "{@value
1089     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}" to <a href="#attr_android:autofillHint"> {@code
1090     * android:autofillHint}.
1091     */
1092    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1093
1094    /**
1095     * Hintd for the autofill services that describes the content of the view.
1096     */
1097    private @Nullable String[] mAutofillHint;
1098
1099    /** @hide */
1100    @IntDef({
1101            AUTOFILL_TYPE_NONE,
1102            AUTOFILL_TYPE_TEXT,
1103            AUTOFILL_TYPE_TOGGLE,
1104            AUTOFILL_TYPE_LIST,
1105            AUTOFILL_TYPE_DATE
1106    })
1107    @Retention(RetentionPolicy.SOURCE)
1108    public @interface AutofillType {}
1109
1110    /**
1111     * Autofill type for views that cannot be autofilled.
1112     */
1113    public static final int AUTOFILL_TYPE_NONE = 0;
1114
1115    /**
1116     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1117     *
1118     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1119     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1120     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1121     */
1122    public static final int AUTOFILL_TYPE_TEXT = 1;
1123
1124    /**
1125     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1126     *
1127     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1128     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1129     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1130     */
1131    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1132
1133    /**
1134     * Autofill type for a selection list field, which is filled by an {@code int}
1135     * representing the element index inside the list (starting at {@code 0}).
1136     *
1137     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1138     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1139     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1140     *
1141     * <p>The available options in the selection list are typically provided by
1142     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1143     */
1144    public static final int AUTOFILL_TYPE_LIST = 3;
1145
1146
1147    /**
1148     * Autofill type for a field that contains a date, which is represented by a long representing
1149     * the number of milliseconds since the standard base time known as "the epoch", namely
1150     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1151     *
1152     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1153     * {@link AutofillValue#forDate(long)}, and the values passed to
1154     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1155     */
1156    public static final int AUTOFILL_TYPE_DATE = 4;
1157
1158    /** @hide */
1159    @IntDef({
1160            IMPORTANT_FOR_AUTOFILL_AUTO,
1161            IMPORTANT_FOR_AUTOFILL_YES,
1162            IMPORTANT_FOR_AUTOFILL_NO
1163    })
1164    @Retention(RetentionPolicy.SOURCE)
1165    public @interface AutofillImportance {}
1166
1167    /**
1168     * Automatically determine whether a view is important for auto-fill.
1169     */
1170    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1171
1172    /**
1173     * The view is important for important for auto-fill.
1174     */
1175    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1176
1177    /**
1178     * The view is not important for auto-fill.
1179     */
1180    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1181
1182    /**
1183     * This view is enabled. Interpretation varies by subclass.
1184     * Use with ENABLED_MASK when calling setFlags.
1185     * {@hide}
1186     */
1187    static final int ENABLED = 0x00000000;
1188
1189    /**
1190     * This view is disabled. Interpretation varies by subclass.
1191     * Use with ENABLED_MASK when calling setFlags.
1192     * {@hide}
1193     */
1194    static final int DISABLED = 0x00000020;
1195
1196   /**
1197    * Mask for use with setFlags indicating bits used for indicating whether
1198    * this view is enabled
1199    * {@hide}
1200    */
1201    static final int ENABLED_MASK = 0x00000020;
1202
1203    /**
1204     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1205     * called and further optimizations will be performed. It is okay to have
1206     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1207     * {@hide}
1208     */
1209    static final int WILL_NOT_DRAW = 0x00000080;
1210
1211    /**
1212     * Mask for use with setFlags indicating bits used for indicating whether
1213     * this view is will draw
1214     * {@hide}
1215     */
1216    static final int DRAW_MASK = 0x00000080;
1217
1218    /**
1219     * <p>This view doesn't show scrollbars.</p>
1220     * {@hide}
1221     */
1222    static final int SCROLLBARS_NONE = 0x00000000;
1223
1224    /**
1225     * <p>This view shows horizontal scrollbars.</p>
1226     * {@hide}
1227     */
1228    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1229
1230    /**
1231     * <p>This view shows vertical scrollbars.</p>
1232     * {@hide}
1233     */
1234    static final int SCROLLBARS_VERTICAL = 0x00000200;
1235
1236    /**
1237     * <p>Mask for use with setFlags indicating bits used for indicating which
1238     * scrollbars are enabled.</p>
1239     * {@hide}
1240     */
1241    static final int SCROLLBARS_MASK = 0x00000300;
1242
1243    /**
1244     * Indicates that the view should filter touches when its window is obscured.
1245     * Refer to the class comments for more information about this security feature.
1246     * {@hide}
1247     */
1248    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1249
1250    /**
1251     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1252     * that they are optional and should be skipped if the window has
1253     * requested system UI flags that ignore those insets for layout.
1254     */
1255    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1256
1257    /**
1258     * <p>This view doesn't show fading edges.</p>
1259     * {@hide}
1260     */
1261    static final int FADING_EDGE_NONE = 0x00000000;
1262
1263    /**
1264     * <p>This view shows horizontal fading edges.</p>
1265     * {@hide}
1266     */
1267    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1268
1269    /**
1270     * <p>This view shows vertical fading edges.</p>
1271     * {@hide}
1272     */
1273    static final int FADING_EDGE_VERTICAL = 0x00002000;
1274
1275    /**
1276     * <p>Mask for use with setFlags indicating bits used for indicating which
1277     * fading edges are enabled.</p>
1278     * {@hide}
1279     */
1280    static final int FADING_EDGE_MASK = 0x00003000;
1281
1282    /**
1283     * <p>Indicates this view can be clicked. When clickable, a View reacts
1284     * to clicks by notifying the OnClickListener.<p>
1285     * {@hide}
1286     */
1287    static final int CLICKABLE = 0x00004000;
1288
1289    /**
1290     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1291     * {@hide}
1292     */
1293    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1294
1295    /**
1296     * <p>Indicates that no icicle should be saved for this view.<p>
1297     * {@hide}
1298     */
1299    static final int SAVE_DISABLED = 0x000010000;
1300
1301    /**
1302     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1303     * property.</p>
1304     * {@hide}
1305     */
1306    static final int SAVE_DISABLED_MASK = 0x000010000;
1307
1308    /**
1309     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1310     * {@hide}
1311     */
1312    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1313
1314    /**
1315     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1316     * {@hide}
1317     */
1318    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1319
1320    /** @hide */
1321    @Retention(RetentionPolicy.SOURCE)
1322    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1323    public @interface DrawingCacheQuality {}
1324
1325    /**
1326     * <p>Enables low quality mode for the drawing cache.</p>
1327     */
1328    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1329
1330    /**
1331     * <p>Enables high quality mode for the drawing cache.</p>
1332     */
1333    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1334
1335    /**
1336     * <p>Enables automatic quality mode for the drawing cache.</p>
1337     */
1338    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1339
1340    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1341            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1342    };
1343
1344    /**
1345     * <p>Mask for use with setFlags indicating bits used for the cache
1346     * quality property.</p>
1347     * {@hide}
1348     */
1349    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1350
1351    /**
1352     * <p>
1353     * Indicates this view can be long clicked. When long clickable, a View
1354     * reacts to long clicks by notifying the OnLongClickListener or showing a
1355     * context menu.
1356     * </p>
1357     * {@hide}
1358     */
1359    static final int LONG_CLICKABLE = 0x00200000;
1360
1361    /**
1362     * <p>Indicates that this view gets its drawable states from its direct parent
1363     * and ignores its original internal states.</p>
1364     *
1365     * @hide
1366     */
1367    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1368
1369    /**
1370     * <p>
1371     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1372     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1373     * OnContextClickListener.
1374     * </p>
1375     * {@hide}
1376     */
1377    static final int CONTEXT_CLICKABLE = 0x00800000;
1378
1379
1380    /** @hide */
1381    @IntDef({
1382        SCROLLBARS_INSIDE_OVERLAY,
1383        SCROLLBARS_INSIDE_INSET,
1384        SCROLLBARS_OUTSIDE_OVERLAY,
1385        SCROLLBARS_OUTSIDE_INSET
1386    })
1387    @Retention(RetentionPolicy.SOURCE)
1388    public @interface ScrollBarStyle {}
1389
1390    /**
1391     * The scrollbar style to display the scrollbars inside the content area,
1392     * without increasing the padding. The scrollbars will be overlaid with
1393     * translucency on the view's content.
1394     */
1395    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1396
1397    /**
1398     * The scrollbar style to display the scrollbars inside the padded area,
1399     * increasing the padding of the view. The scrollbars will not overlap the
1400     * content area of the view.
1401     */
1402    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1403
1404    /**
1405     * The scrollbar style to display the scrollbars at the edge of the view,
1406     * without increasing the padding. The scrollbars will be overlaid with
1407     * translucency.
1408     */
1409    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1410
1411    /**
1412     * The scrollbar style to display the scrollbars at the edge of the view,
1413     * increasing the padding of the view. The scrollbars will only overlap the
1414     * background, if any.
1415     */
1416    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1417
1418    /**
1419     * Mask to check if the scrollbar style is overlay or inset.
1420     * {@hide}
1421     */
1422    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1423
1424    /**
1425     * Mask to check if the scrollbar style is inside or outside.
1426     * {@hide}
1427     */
1428    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1429
1430    /**
1431     * Mask for scrollbar style.
1432     * {@hide}
1433     */
1434    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1435
1436    /**
1437     * View flag indicating that the screen should remain on while the
1438     * window containing this view is visible to the user.  This effectively
1439     * takes care of automatically setting the WindowManager's
1440     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1441     */
1442    public static final int KEEP_SCREEN_ON = 0x04000000;
1443
1444    /**
1445     * View flag indicating whether this view should have sound effects enabled
1446     * for events such as clicking and touching.
1447     */
1448    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1449
1450    /**
1451     * View flag indicating whether this view should have haptic feedback
1452     * enabled for events such as long presses.
1453     */
1454    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1455
1456    /**
1457     * <p>Indicates that the view hierarchy should stop saving state when
1458     * it reaches this view.  If state saving is initiated immediately at
1459     * the view, it will be allowed.
1460     * {@hide}
1461     */
1462    static final int PARENT_SAVE_DISABLED = 0x20000000;
1463
1464    /**
1465     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1466     * {@hide}
1467     */
1468    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1469
1470    private static Paint sDebugPaint;
1471
1472    /**
1473     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1474     * {@hide}
1475     */
1476    static final int TOOLTIP = 0x40000000;
1477
1478    /** @hide */
1479    @IntDef(flag = true,
1480            value = {
1481                FOCUSABLES_ALL,
1482                FOCUSABLES_TOUCH_MODE
1483            })
1484    @Retention(RetentionPolicy.SOURCE)
1485    public @interface FocusableMode {}
1486
1487    /**
1488     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1489     * should add all focusable Views regardless if they are focusable in touch mode.
1490     */
1491    public static final int FOCUSABLES_ALL = 0x00000000;
1492
1493    /**
1494     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1495     * should add only Views focusable in touch mode.
1496     */
1497    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1498
1499    /** @hide */
1500    @IntDef({
1501            FOCUS_BACKWARD,
1502            FOCUS_FORWARD,
1503            FOCUS_LEFT,
1504            FOCUS_UP,
1505            FOCUS_RIGHT,
1506            FOCUS_DOWN
1507    })
1508    @Retention(RetentionPolicy.SOURCE)
1509    public @interface FocusDirection {}
1510
1511    /** @hide */
1512    @IntDef({
1513            FOCUS_LEFT,
1514            FOCUS_UP,
1515            FOCUS_RIGHT,
1516            FOCUS_DOWN
1517    })
1518    @Retention(RetentionPolicy.SOURCE)
1519    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1520
1521    /**
1522     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1523     * item.
1524     */
1525    public static final int FOCUS_BACKWARD = 0x00000001;
1526
1527    /**
1528     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1529     * item.
1530     */
1531    public static final int FOCUS_FORWARD = 0x00000002;
1532
1533    /**
1534     * Use with {@link #focusSearch(int)}. Move focus to the left.
1535     */
1536    public static final int FOCUS_LEFT = 0x00000011;
1537
1538    /**
1539     * Use with {@link #focusSearch(int)}. Move focus up.
1540     */
1541    public static final int FOCUS_UP = 0x00000021;
1542
1543    /**
1544     * Use with {@link #focusSearch(int)}. Move focus to the right.
1545     */
1546    public static final int FOCUS_RIGHT = 0x00000042;
1547
1548    /**
1549     * Use with {@link #focusSearch(int)}. Move focus down.
1550     */
1551    public static final int FOCUS_DOWN = 0x00000082;
1552
1553    /**
1554     * Bits of {@link #getMeasuredWidthAndState()} and
1555     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1556     */
1557    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1558
1559    /**
1560     * Bits of {@link #getMeasuredWidthAndState()} and
1561     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1562     */
1563    public static final int MEASURED_STATE_MASK = 0xff000000;
1564
1565    /**
1566     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1567     * for functions that combine both width and height into a single int,
1568     * such as {@link #getMeasuredState()} and the childState argument of
1569     * {@link #resolveSizeAndState(int, int, int)}.
1570     */
1571    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1572
1573    /**
1574     * Bit of {@link #getMeasuredWidthAndState()} and
1575     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1576     * is smaller that the space the view would like to have.
1577     */
1578    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1579
1580    /**
1581     * Base View state sets
1582     */
1583    // Singles
1584    /**
1585     * Indicates the view has no states set. States are used with
1586     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1587     * view depending on its state.
1588     *
1589     * @see android.graphics.drawable.Drawable
1590     * @see #getDrawableState()
1591     */
1592    protected static final int[] EMPTY_STATE_SET;
1593    /**
1594     * Indicates the view is enabled. States are used with
1595     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1596     * view depending on its state.
1597     *
1598     * @see android.graphics.drawable.Drawable
1599     * @see #getDrawableState()
1600     */
1601    protected static final int[] ENABLED_STATE_SET;
1602    /**
1603     * Indicates the view is focused. States are used with
1604     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1605     * view depending on its state.
1606     *
1607     * @see android.graphics.drawable.Drawable
1608     * @see #getDrawableState()
1609     */
1610    protected static final int[] FOCUSED_STATE_SET;
1611    /**
1612     * Indicates the view is selected. States are used with
1613     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1614     * view depending on its state.
1615     *
1616     * @see android.graphics.drawable.Drawable
1617     * @see #getDrawableState()
1618     */
1619    protected static final int[] SELECTED_STATE_SET;
1620    /**
1621     * Indicates the view is pressed. States are used with
1622     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1623     * view depending on its state.
1624     *
1625     * @see android.graphics.drawable.Drawable
1626     * @see #getDrawableState()
1627     */
1628    protected static final int[] PRESSED_STATE_SET;
1629    /**
1630     * Indicates the view's window has focus. States are used with
1631     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1632     * view depending on its state.
1633     *
1634     * @see android.graphics.drawable.Drawable
1635     * @see #getDrawableState()
1636     */
1637    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1638    // Doubles
1639    /**
1640     * Indicates the view is enabled and has the focus.
1641     *
1642     * @see #ENABLED_STATE_SET
1643     * @see #FOCUSED_STATE_SET
1644     */
1645    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1646    /**
1647     * Indicates the view is enabled and selected.
1648     *
1649     * @see #ENABLED_STATE_SET
1650     * @see #SELECTED_STATE_SET
1651     */
1652    protected static final int[] ENABLED_SELECTED_STATE_SET;
1653    /**
1654     * Indicates the view is enabled and that its window has focus.
1655     *
1656     * @see #ENABLED_STATE_SET
1657     * @see #WINDOW_FOCUSED_STATE_SET
1658     */
1659    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1660    /**
1661     * Indicates the view is focused and selected.
1662     *
1663     * @see #FOCUSED_STATE_SET
1664     * @see #SELECTED_STATE_SET
1665     */
1666    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1667    /**
1668     * Indicates the view has the focus and that its window has the focus.
1669     *
1670     * @see #FOCUSED_STATE_SET
1671     * @see #WINDOW_FOCUSED_STATE_SET
1672     */
1673    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1674    /**
1675     * Indicates the view is selected and that its window has the focus.
1676     *
1677     * @see #SELECTED_STATE_SET
1678     * @see #WINDOW_FOCUSED_STATE_SET
1679     */
1680    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1681    // Triples
1682    /**
1683     * Indicates the view is enabled, focused and selected.
1684     *
1685     * @see #ENABLED_STATE_SET
1686     * @see #FOCUSED_STATE_SET
1687     * @see #SELECTED_STATE_SET
1688     */
1689    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1690    /**
1691     * Indicates the view is enabled, focused and its window has the focus.
1692     *
1693     * @see #ENABLED_STATE_SET
1694     * @see #FOCUSED_STATE_SET
1695     * @see #WINDOW_FOCUSED_STATE_SET
1696     */
1697    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1698    /**
1699     * Indicates the view is enabled, selected and its window has the focus.
1700     *
1701     * @see #ENABLED_STATE_SET
1702     * @see #SELECTED_STATE_SET
1703     * @see #WINDOW_FOCUSED_STATE_SET
1704     */
1705    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1706    /**
1707     * Indicates the view is focused, selected and its window has the focus.
1708     *
1709     * @see #FOCUSED_STATE_SET
1710     * @see #SELECTED_STATE_SET
1711     * @see #WINDOW_FOCUSED_STATE_SET
1712     */
1713    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1714    /**
1715     * Indicates the view is enabled, focused, selected and its window
1716     * has the focus.
1717     *
1718     * @see #ENABLED_STATE_SET
1719     * @see #FOCUSED_STATE_SET
1720     * @see #SELECTED_STATE_SET
1721     * @see #WINDOW_FOCUSED_STATE_SET
1722     */
1723    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1724    /**
1725     * Indicates the view is pressed and its window has the focus.
1726     *
1727     * @see #PRESSED_STATE_SET
1728     * @see #WINDOW_FOCUSED_STATE_SET
1729     */
1730    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1731    /**
1732     * Indicates the view is pressed and selected.
1733     *
1734     * @see #PRESSED_STATE_SET
1735     * @see #SELECTED_STATE_SET
1736     */
1737    protected static final int[] PRESSED_SELECTED_STATE_SET;
1738    /**
1739     * Indicates the view is pressed, selected and its window has the focus.
1740     *
1741     * @see #PRESSED_STATE_SET
1742     * @see #SELECTED_STATE_SET
1743     * @see #WINDOW_FOCUSED_STATE_SET
1744     */
1745    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1746    /**
1747     * Indicates the view is pressed and focused.
1748     *
1749     * @see #PRESSED_STATE_SET
1750     * @see #FOCUSED_STATE_SET
1751     */
1752    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1753    /**
1754     * Indicates the view is pressed, focused and its window has the focus.
1755     *
1756     * @see #PRESSED_STATE_SET
1757     * @see #FOCUSED_STATE_SET
1758     * @see #WINDOW_FOCUSED_STATE_SET
1759     */
1760    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1761    /**
1762     * Indicates the view is pressed, focused and selected.
1763     *
1764     * @see #PRESSED_STATE_SET
1765     * @see #SELECTED_STATE_SET
1766     * @see #FOCUSED_STATE_SET
1767     */
1768    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1769    /**
1770     * Indicates the view is pressed, focused, selected and its window has the focus.
1771     *
1772     * @see #PRESSED_STATE_SET
1773     * @see #FOCUSED_STATE_SET
1774     * @see #SELECTED_STATE_SET
1775     * @see #WINDOW_FOCUSED_STATE_SET
1776     */
1777    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1778    /**
1779     * Indicates the view is pressed and enabled.
1780     *
1781     * @see #PRESSED_STATE_SET
1782     * @see #ENABLED_STATE_SET
1783     */
1784    protected static final int[] PRESSED_ENABLED_STATE_SET;
1785    /**
1786     * Indicates the view is pressed, enabled and its window has the focus.
1787     *
1788     * @see #PRESSED_STATE_SET
1789     * @see #ENABLED_STATE_SET
1790     * @see #WINDOW_FOCUSED_STATE_SET
1791     */
1792    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1793    /**
1794     * Indicates the view is pressed, enabled and selected.
1795     *
1796     * @see #PRESSED_STATE_SET
1797     * @see #ENABLED_STATE_SET
1798     * @see #SELECTED_STATE_SET
1799     */
1800    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1801    /**
1802     * Indicates the view is pressed, enabled, selected and its window has the
1803     * focus.
1804     *
1805     * @see #PRESSED_STATE_SET
1806     * @see #ENABLED_STATE_SET
1807     * @see #SELECTED_STATE_SET
1808     * @see #WINDOW_FOCUSED_STATE_SET
1809     */
1810    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1811    /**
1812     * Indicates the view is pressed, enabled and focused.
1813     *
1814     * @see #PRESSED_STATE_SET
1815     * @see #ENABLED_STATE_SET
1816     * @see #FOCUSED_STATE_SET
1817     */
1818    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1819    /**
1820     * Indicates the view is pressed, enabled, focused and its window has the
1821     * focus.
1822     *
1823     * @see #PRESSED_STATE_SET
1824     * @see #ENABLED_STATE_SET
1825     * @see #FOCUSED_STATE_SET
1826     * @see #WINDOW_FOCUSED_STATE_SET
1827     */
1828    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1829    /**
1830     * Indicates the view is pressed, enabled, focused and selected.
1831     *
1832     * @see #PRESSED_STATE_SET
1833     * @see #ENABLED_STATE_SET
1834     * @see #SELECTED_STATE_SET
1835     * @see #FOCUSED_STATE_SET
1836     */
1837    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1838    /**
1839     * Indicates the view is pressed, enabled, focused, selected and its window
1840     * has the focus.
1841     *
1842     * @see #PRESSED_STATE_SET
1843     * @see #ENABLED_STATE_SET
1844     * @see #SELECTED_STATE_SET
1845     * @see #FOCUSED_STATE_SET
1846     * @see #WINDOW_FOCUSED_STATE_SET
1847     */
1848    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1849
1850    static {
1851        EMPTY_STATE_SET = StateSet.get(0);
1852
1853        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1854
1855        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1856        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1857                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1858
1859        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1860        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1861                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1862        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1863                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1864        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1865                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1866                        | StateSet.VIEW_STATE_FOCUSED);
1867
1868        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1869        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1870                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1871        ENABLED_SELECTED_STATE_SET = StateSet.get(
1872                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1873        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1874                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1875                        | StateSet.VIEW_STATE_ENABLED);
1876        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1877                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1878        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1879                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1880                        | StateSet.VIEW_STATE_ENABLED);
1881        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1882                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1883                        | StateSet.VIEW_STATE_ENABLED);
1884        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1885                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1886                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1887
1888        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1889        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1890                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1891        PRESSED_SELECTED_STATE_SET = StateSet.get(
1892                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1893        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1894                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1895                        | StateSet.VIEW_STATE_PRESSED);
1896        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1897                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1898        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1899                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1900                        | StateSet.VIEW_STATE_PRESSED);
1901        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1902                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1903                        | StateSet.VIEW_STATE_PRESSED);
1904        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1905                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1906                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1907        PRESSED_ENABLED_STATE_SET = StateSet.get(
1908                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1909        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1910                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1911                        | StateSet.VIEW_STATE_PRESSED);
1912        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1913                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1914                        | StateSet.VIEW_STATE_PRESSED);
1915        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1916                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1917                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1918        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1919                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1920                        | StateSet.VIEW_STATE_PRESSED);
1921        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1922                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1923                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1924        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1925                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1926                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1927        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1928                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1929                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1930                        | StateSet.VIEW_STATE_PRESSED);
1931    }
1932
1933    /**
1934     * Accessibility event types that are dispatched for text population.
1935     */
1936    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1937            AccessibilityEvent.TYPE_VIEW_CLICKED
1938            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1939            | AccessibilityEvent.TYPE_VIEW_SELECTED
1940            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1941            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1942            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1943            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1944            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1945            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1946            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1947            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1948
1949    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1950
1951    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1952
1953    /**
1954     * Temporary Rect currently for use in setBackground().  This will probably
1955     * be extended in the future to hold our own class with more than just
1956     * a Rect. :)
1957     */
1958    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1959
1960    /**
1961     * Map used to store views' tags.
1962     */
1963    private SparseArray<Object> mKeyedTags;
1964
1965    /**
1966     * The next available accessibility id.
1967     */
1968    private static int sNextAccessibilityViewId;
1969
1970    /**
1971     * The animation currently associated with this view.
1972     * @hide
1973     */
1974    protected Animation mCurrentAnimation = null;
1975
1976    /**
1977     * Width as measured during measure pass.
1978     * {@hide}
1979     */
1980    @ViewDebug.ExportedProperty(category = "measurement")
1981    int mMeasuredWidth;
1982
1983    /**
1984     * Height as measured during measure pass.
1985     * {@hide}
1986     */
1987    @ViewDebug.ExportedProperty(category = "measurement")
1988    int mMeasuredHeight;
1989
1990    /**
1991     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1992     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1993     * its display list. This flag, used only when hw accelerated, allows us to clear the
1994     * flag while retaining this information until it's needed (at getDisplayList() time and
1995     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1996     *
1997     * {@hide}
1998     */
1999    boolean mRecreateDisplayList = false;
2000
2001    /**
2002     * The view's identifier.
2003     * {@hide}
2004     *
2005     * @see #setId(int)
2006     * @see #getId()
2007     */
2008    @IdRes
2009    @ViewDebug.ExportedProperty(resolveId = true)
2010    int mID = NO_ID;
2011
2012    /**
2013     * The stable ID of this view for accessibility purposes.
2014     */
2015    int mAccessibilityViewId = NO_ID;
2016
2017    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2018
2019    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2020
2021    /**
2022     * The view's tag.
2023     * {@hide}
2024     *
2025     * @see #setTag(Object)
2026     * @see #getTag()
2027     */
2028    protected Object mTag = null;
2029
2030    // for mPrivateFlags:
2031    /** {@hide} */
2032    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2033    /** {@hide} */
2034    static final int PFLAG_FOCUSED                     = 0x00000002;
2035    /** {@hide} */
2036    static final int PFLAG_SELECTED                    = 0x00000004;
2037    /** {@hide} */
2038    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2039    /** {@hide} */
2040    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2041    /** {@hide} */
2042    static final int PFLAG_DRAWN                       = 0x00000020;
2043    /**
2044     * When this flag is set, this view is running an animation on behalf of its
2045     * children and should therefore not cancel invalidate requests, even if they
2046     * lie outside of this view's bounds.
2047     *
2048     * {@hide}
2049     */
2050    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2051    /** {@hide} */
2052    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2053    /** {@hide} */
2054    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2055    /** {@hide} */
2056    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2057    /** {@hide} */
2058    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2059    /** {@hide} */
2060    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2061    /** {@hide} */
2062    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2063
2064    private static final int PFLAG_PRESSED             = 0x00004000;
2065
2066    /** {@hide} */
2067    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2068    /**
2069     * Flag used to indicate that this view should be drawn once more (and only once
2070     * more) after its animation has completed.
2071     * {@hide}
2072     */
2073    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2074
2075    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2076
2077    /**
2078     * Indicates that the View returned true when onSetAlpha() was called and that
2079     * the alpha must be restored.
2080     * {@hide}
2081     */
2082    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2083
2084    /**
2085     * Set by {@link #setScrollContainer(boolean)}.
2086     */
2087    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2088
2089    /**
2090     * Set by {@link #setScrollContainer(boolean)}.
2091     */
2092    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2093
2094    /**
2095     * View flag indicating whether this view was invalidated (fully or partially.)
2096     *
2097     * @hide
2098     */
2099    static final int PFLAG_DIRTY                       = 0x00200000;
2100
2101    /**
2102     * View flag indicating whether this view was invalidated by an opaque
2103     * invalidate request.
2104     *
2105     * @hide
2106     */
2107    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2108
2109    /**
2110     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2111     *
2112     * @hide
2113     */
2114    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2115
2116    /**
2117     * Indicates whether the background is opaque.
2118     *
2119     * @hide
2120     */
2121    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2122
2123    /**
2124     * Indicates whether the scrollbars are opaque.
2125     *
2126     * @hide
2127     */
2128    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2129
2130    /**
2131     * Indicates whether the view is opaque.
2132     *
2133     * @hide
2134     */
2135    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2136
2137    /**
2138     * Indicates a prepressed state;
2139     * the short time between ACTION_DOWN and recognizing
2140     * a 'real' press. Prepressed is used to recognize quick taps
2141     * even when they are shorter than ViewConfiguration.getTapTimeout().
2142     *
2143     * @hide
2144     */
2145    private static final int PFLAG_PREPRESSED          = 0x02000000;
2146
2147    /**
2148     * Indicates whether the view is temporarily detached.
2149     *
2150     * @hide
2151     */
2152    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2153
2154    /**
2155     * Indicates that we should awaken scroll bars once attached
2156     *
2157     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2158     * during window attachment and it is no longer needed. Feel free to repurpose it.
2159     *
2160     * @hide
2161     */
2162    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2163
2164    /**
2165     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2166     * @hide
2167     */
2168    private static final int PFLAG_HOVERED             = 0x10000000;
2169
2170    /**
2171     * no longer needed, should be reused
2172     */
2173    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2174
2175    /** {@hide} */
2176    static final int PFLAG_ACTIVATED                   = 0x40000000;
2177
2178    /**
2179     * Indicates that this view was specifically invalidated, not just dirtied because some
2180     * child view was invalidated. The flag is used to determine when we need to recreate
2181     * a view's display list (as opposed to just returning a reference to its existing
2182     * display list).
2183     *
2184     * @hide
2185     */
2186    static final int PFLAG_INVALIDATED                 = 0x80000000;
2187
2188    /**
2189     * Masks for mPrivateFlags2, as generated by dumpFlags():
2190     *
2191     * |-------|-------|-------|-------|
2192     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2193     *                                1  PFLAG2_DRAG_HOVERED
2194     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2195     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2196     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2197     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2198     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2199     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2200     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2201     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2202     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2203     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2204     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2205     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2206     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2207     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2208     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2209     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2210     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2211     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2212     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2213     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2214     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2215     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2216     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2217     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2218     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2219     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2220     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2221     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2222     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2223     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2224     *    1                              PFLAG2_PADDING_RESOLVED
2225     *   1                               PFLAG2_DRAWABLE_RESOLVED
2226     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2227     * |-------|-------|-------|-------|
2228     */
2229
2230    /**
2231     * Indicates that this view has reported that it can accept the current drag's content.
2232     * Cleared when the drag operation concludes.
2233     * @hide
2234     */
2235    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2236
2237    /**
2238     * Indicates that this view is currently directly under the drag location in a
2239     * drag-and-drop operation involving content that it can accept.  Cleared when
2240     * the drag exits the view, or when the drag operation concludes.
2241     * @hide
2242     */
2243    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2244
2245    /** @hide */
2246    @IntDef({
2247        LAYOUT_DIRECTION_LTR,
2248        LAYOUT_DIRECTION_RTL,
2249        LAYOUT_DIRECTION_INHERIT,
2250        LAYOUT_DIRECTION_LOCALE
2251    })
2252    @Retention(RetentionPolicy.SOURCE)
2253    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2254    public @interface LayoutDir {}
2255
2256    /** @hide */
2257    @IntDef({
2258        LAYOUT_DIRECTION_LTR,
2259        LAYOUT_DIRECTION_RTL
2260    })
2261    @Retention(RetentionPolicy.SOURCE)
2262    public @interface ResolvedLayoutDir {}
2263
2264    /**
2265     * A flag to indicate that the layout direction of this view has not been defined yet.
2266     * @hide
2267     */
2268    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2269
2270    /**
2271     * Horizontal layout direction of this view is from Left to Right.
2272     * Use with {@link #setLayoutDirection}.
2273     */
2274    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2275
2276    /**
2277     * Horizontal layout direction of this view is from Right to Left.
2278     * Use with {@link #setLayoutDirection}.
2279     */
2280    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2281
2282    /**
2283     * Horizontal layout direction of this view is inherited from its parent.
2284     * Use with {@link #setLayoutDirection}.
2285     */
2286    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2287
2288    /**
2289     * Horizontal layout direction of this view is from deduced from the default language
2290     * script for the locale. Use with {@link #setLayoutDirection}.
2291     */
2292    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2293
2294    /**
2295     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2296     * @hide
2297     */
2298    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2299
2300    /**
2301     * Mask for use with private flags indicating bits used for horizontal layout direction.
2302     * @hide
2303     */
2304    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2305
2306    /**
2307     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2308     * right-to-left direction.
2309     * @hide
2310     */
2311    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2312
2313    /**
2314     * Indicates whether the view horizontal layout direction has been resolved.
2315     * @hide
2316     */
2317    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2318
2319    /**
2320     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2321     * @hide
2322     */
2323    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2324            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2325
2326    /*
2327     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2328     * flag value.
2329     * @hide
2330     */
2331    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2332            LAYOUT_DIRECTION_LTR,
2333            LAYOUT_DIRECTION_RTL,
2334            LAYOUT_DIRECTION_INHERIT,
2335            LAYOUT_DIRECTION_LOCALE
2336    };
2337
2338    /**
2339     * Default horizontal layout direction.
2340     */
2341    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2342
2343    /**
2344     * Default horizontal layout direction.
2345     * @hide
2346     */
2347    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2348
2349    /**
2350     * Text direction is inherited through {@link ViewGroup}
2351     */
2352    public static final int TEXT_DIRECTION_INHERIT = 0;
2353
2354    /**
2355     * Text direction is using "first strong algorithm". The first strong directional character
2356     * determines the paragraph direction. If there is no strong directional character, the
2357     * paragraph direction is the view's resolved layout direction.
2358     */
2359    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2360
2361    /**
2362     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2363     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2364     * If there are neither, the paragraph direction is the view's resolved layout direction.
2365     */
2366    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2367
2368    /**
2369     * Text direction is forced to LTR.
2370     */
2371    public static final int TEXT_DIRECTION_LTR = 3;
2372
2373    /**
2374     * Text direction is forced to RTL.
2375     */
2376    public static final int TEXT_DIRECTION_RTL = 4;
2377
2378    /**
2379     * Text direction is coming from the system Locale.
2380     */
2381    public static final int TEXT_DIRECTION_LOCALE = 5;
2382
2383    /**
2384     * Text direction is using "first strong algorithm". The first strong directional character
2385     * determines the paragraph direction. If there is no strong directional character, the
2386     * paragraph direction is LTR.
2387     */
2388    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2389
2390    /**
2391     * Text direction is using "first strong algorithm". The first strong directional character
2392     * determines the paragraph direction. If there is no strong directional character, the
2393     * paragraph direction is RTL.
2394     */
2395    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2396
2397    /**
2398     * Default text direction is inherited
2399     */
2400    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2401
2402    /**
2403     * Default resolved text direction
2404     * @hide
2405     */
2406    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2407
2408    /**
2409     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2410     * @hide
2411     */
2412    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2413
2414    /**
2415     * Mask for use with private flags indicating bits used for text direction.
2416     * @hide
2417     */
2418    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2419            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2420
2421    /**
2422     * Array of text direction flags for mapping attribute "textDirection" to correct
2423     * flag value.
2424     * @hide
2425     */
2426    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2427            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2428            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2429            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2430            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2431            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2432            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2433            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2434            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2435    };
2436
2437    /**
2438     * Indicates whether the view text direction has been resolved.
2439     * @hide
2440     */
2441    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2442            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2443
2444    /**
2445     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2446     * @hide
2447     */
2448    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2449
2450    /**
2451     * Mask for use with private flags indicating bits used for resolved text direction.
2452     * @hide
2453     */
2454    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2455            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2456
2457    /**
2458     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2459     * @hide
2460     */
2461    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2462            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2463
2464    /** @hide */
2465    @IntDef({
2466        TEXT_ALIGNMENT_INHERIT,
2467        TEXT_ALIGNMENT_GRAVITY,
2468        TEXT_ALIGNMENT_CENTER,
2469        TEXT_ALIGNMENT_TEXT_START,
2470        TEXT_ALIGNMENT_TEXT_END,
2471        TEXT_ALIGNMENT_VIEW_START,
2472        TEXT_ALIGNMENT_VIEW_END
2473    })
2474    @Retention(RetentionPolicy.SOURCE)
2475    public @interface TextAlignment {}
2476
2477    /**
2478     * Default text alignment. The text alignment of this View is inherited from its parent.
2479     * Use with {@link #setTextAlignment(int)}
2480     */
2481    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2482
2483    /**
2484     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2485     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2486     *
2487     * Use with {@link #setTextAlignment(int)}
2488     */
2489    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2490
2491    /**
2492     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2493     *
2494     * Use with {@link #setTextAlignment(int)}
2495     */
2496    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2497
2498    /**
2499     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2500     *
2501     * Use with {@link #setTextAlignment(int)}
2502     */
2503    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2504
2505    /**
2506     * Center the paragraph, e.g. ALIGN_CENTER.
2507     *
2508     * Use with {@link #setTextAlignment(int)}
2509     */
2510    public static final int TEXT_ALIGNMENT_CENTER = 4;
2511
2512    /**
2513     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2514     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2515     *
2516     * Use with {@link #setTextAlignment(int)}
2517     */
2518    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2519
2520    /**
2521     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2522     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2523     *
2524     * Use with {@link #setTextAlignment(int)}
2525     */
2526    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2527
2528    /**
2529     * Default text alignment is inherited
2530     */
2531    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2532
2533    /**
2534     * Default resolved text alignment
2535     * @hide
2536     */
2537    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2538
2539    /**
2540      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2541      * @hide
2542      */
2543    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2544
2545    /**
2546      * Mask for use with private flags indicating bits used for text alignment.
2547      * @hide
2548      */
2549    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2550
2551    /**
2552     * Array of text direction flags for mapping attribute "textAlignment" to correct
2553     * flag value.
2554     * @hide
2555     */
2556    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2557            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2558            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2559            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2560            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2561            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2562            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2563            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2564    };
2565
2566    /**
2567     * Indicates whether the view text alignment has been resolved.
2568     * @hide
2569     */
2570    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2571
2572    /**
2573     * Bit shift to get the resolved text alignment.
2574     * @hide
2575     */
2576    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2577
2578    /**
2579     * Mask for use with private flags indicating bits used for text alignment.
2580     * @hide
2581     */
2582    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2583            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2584
2585    /**
2586     * Indicates whether if the view text alignment has been resolved to gravity
2587     */
2588    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2589            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2590
2591    // Accessiblity constants for mPrivateFlags2
2592
2593    /**
2594     * Shift for the bits in {@link #mPrivateFlags2} related to the
2595     * "importantForAccessibility" attribute.
2596     */
2597    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2598
2599    /**
2600     * Automatically determine whether a view is important for accessibility.
2601     */
2602    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2603
2604    /**
2605     * The view is important for accessibility.
2606     */
2607    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2608
2609    /**
2610     * The view is not important for accessibility.
2611     */
2612    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2613
2614    /**
2615     * The view is not important for accessibility, nor are any of its
2616     * descendant views.
2617     */
2618    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2619
2620    /**
2621     * The default whether the view is important for accessibility.
2622     */
2623    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2624
2625    /**
2626     * Mask for obtaining the bits which specify how to determine
2627     * whether a view is important for accessibility.
2628     */
2629    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2630        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2631        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2632        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2633
2634    /**
2635     * Shift for the bits in {@link #mPrivateFlags2} related to the
2636     * "accessibilityLiveRegion" attribute.
2637     */
2638    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2639
2640    /**
2641     * Live region mode specifying that accessibility services should not
2642     * automatically announce changes to this view. This is the default live
2643     * region mode for most views.
2644     * <p>
2645     * Use with {@link #setAccessibilityLiveRegion(int)}.
2646     */
2647    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2648
2649    /**
2650     * Live region mode specifying that accessibility services should announce
2651     * changes to this view.
2652     * <p>
2653     * Use with {@link #setAccessibilityLiveRegion(int)}.
2654     */
2655    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2656
2657    /**
2658     * Live region mode specifying that accessibility services should interrupt
2659     * ongoing speech to immediately announce changes to this view.
2660     * <p>
2661     * Use with {@link #setAccessibilityLiveRegion(int)}.
2662     */
2663    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2664
2665    /**
2666     * The default whether the view is important for accessibility.
2667     */
2668    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2669
2670    /**
2671     * Mask for obtaining the bits which specify a view's accessibility live
2672     * region mode.
2673     */
2674    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2675            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2676            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2677
2678    /**
2679     * Flag indicating whether a view has accessibility focus.
2680     */
2681    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2682
2683    /**
2684     * Flag whether the accessibility state of the subtree rooted at this view changed.
2685     */
2686    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2687
2688    /**
2689     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2690     * is used to check whether later changes to the view's transform should invalidate the
2691     * view to force the quickReject test to run again.
2692     */
2693    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2694
2695    /**
2696     * Flag indicating that start/end padding has been resolved into left/right padding
2697     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2698     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2699     * during measurement. In some special cases this is required such as when an adapter-based
2700     * view measures prospective children without attaching them to a window.
2701     */
2702    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2703
2704    /**
2705     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2706     */
2707    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2708
2709    /**
2710     * Indicates that the view is tracking some sort of transient state
2711     * that the app should not need to be aware of, but that the framework
2712     * should take special care to preserve.
2713     */
2714    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2715
2716    /**
2717     * Group of bits indicating that RTL properties resolution is done.
2718     */
2719    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2720            PFLAG2_TEXT_DIRECTION_RESOLVED |
2721            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2722            PFLAG2_PADDING_RESOLVED |
2723            PFLAG2_DRAWABLE_RESOLVED;
2724
2725    // There are a couple of flags left in mPrivateFlags2
2726
2727    /* End of masks for mPrivateFlags2 */
2728
2729    /**
2730     * Masks for mPrivateFlags3, as generated by dumpFlags():
2731     *
2732     * |-------|-------|-------|-------|
2733     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2734     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2735     *                               1   PFLAG3_IS_LAID_OUT
2736     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2737     *                             1     PFLAG3_CALLED_SUPER
2738     *                            1      PFLAG3_APPLYING_INSETS
2739     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2740     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2741     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2742     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2743     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2744     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2745     *                     1             PFLAG3_SCROLL_INDICATOR_START
2746     *                    1              PFLAG3_SCROLL_INDICATOR_END
2747     *                   1               PFLAG3_ASSIST_BLOCKED
2748     *                  1                PFLAG3_CLUSTER
2749     *                 x                 * NO LONGER NEEDED, SHOULD BE REUSED *
2750     *                1                  PFLAG3_FINGER_DOWN
2751     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2752<<<<<<< HEAD
2753     *             11                    PFLAG3_AUTO_FILL_MODE_MASK
2754     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
2755=======
2756     *             11                    PFLAG3_AUTOFILL_MODE_MASK
2757     *           xx                      * NO LONGER NEEDED, SHOULD BE REUSED *
2758>>>>>>> Replaced auto-fill by autofill to keep it consistent with API style.
2759     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2760     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2761     *        1                          PFLAG3_TEMPORARY_DETACH
2762     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2763     * |-------|-------|-------|-------|
2764     */
2765
2766    /**
2767     * Flag indicating that view has a transform animation set on it. This is used to track whether
2768     * an animation is cleared between successive frames, in order to tell the associated
2769     * DisplayList to clear its animation matrix.
2770     */
2771    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2772
2773    /**
2774     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2775     * animation is cleared between successive frames, in order to tell the associated
2776     * DisplayList to restore its alpha value.
2777     */
2778    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2779
2780    /**
2781     * Flag indicating that the view has been through at least one layout since it
2782     * was last attached to a window.
2783     */
2784    static final int PFLAG3_IS_LAID_OUT = 0x4;
2785
2786    /**
2787     * Flag indicating that a call to measure() was skipped and should be done
2788     * instead when layout() is invoked.
2789     */
2790    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2791
2792    /**
2793     * Flag indicating that an overridden method correctly called down to
2794     * the superclass implementation as required by the API spec.
2795     */
2796    static final int PFLAG3_CALLED_SUPER = 0x10;
2797
2798    /**
2799     * Flag indicating that we're in the process of applying window insets.
2800     */
2801    static final int PFLAG3_APPLYING_INSETS = 0x20;
2802
2803    /**
2804     * Flag indicating that we're in the process of fitting system windows using the old method.
2805     */
2806    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2807
2808    /**
2809     * Flag indicating that nested scrolling is enabled for this view.
2810     * The view will optionally cooperate with views up its parent chain to allow for
2811     * integrated nested scrolling along the same axis.
2812     */
2813    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2814
2815    /**
2816     * Flag indicating that the bottom scroll indicator should be displayed
2817     * when this view can scroll up.
2818     */
2819    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2820
2821    /**
2822     * Flag indicating that the bottom scroll indicator should be displayed
2823     * when this view can scroll down.
2824     */
2825    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2826
2827    /**
2828     * Flag indicating that the left scroll indicator should be displayed
2829     * when this view can scroll left.
2830     */
2831    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2832
2833    /**
2834     * Flag indicating that the right scroll indicator should be displayed
2835     * when this view can scroll right.
2836     */
2837    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2838
2839    /**
2840     * Flag indicating that the start scroll indicator should be displayed
2841     * when this view can scroll in the start direction.
2842     */
2843    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2844
2845    /**
2846     * Flag indicating that the end scroll indicator should be displayed
2847     * when this view can scroll in the end direction.
2848     */
2849    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2850
2851    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2852
2853    static final int SCROLL_INDICATORS_NONE = 0x0000;
2854
2855    /**
2856     * Mask for use with setFlags indicating bits used for indicating which
2857     * scroll indicators are enabled.
2858     */
2859    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2860            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2861            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2862            | PFLAG3_SCROLL_INDICATOR_END;
2863
2864    /**
2865     * Left-shift required to translate between public scroll indicator flags
2866     * and internal PFLAGS3 flags. When used as a right-shift, translates
2867     * PFLAGS3 flags to public flags.
2868     */
2869    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2870
2871    /** @hide */
2872    @Retention(RetentionPolicy.SOURCE)
2873    @IntDef(flag = true,
2874            value = {
2875                    SCROLL_INDICATOR_TOP,
2876                    SCROLL_INDICATOR_BOTTOM,
2877                    SCROLL_INDICATOR_LEFT,
2878                    SCROLL_INDICATOR_RIGHT,
2879                    SCROLL_INDICATOR_START,
2880                    SCROLL_INDICATOR_END,
2881            })
2882    public @interface ScrollIndicators {}
2883
2884    /**
2885     * Scroll indicator direction for the top edge of the view.
2886     *
2887     * @see #setScrollIndicators(int)
2888     * @see #setScrollIndicators(int, int)
2889     * @see #getScrollIndicators()
2890     */
2891    public static final int SCROLL_INDICATOR_TOP =
2892            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2893
2894    /**
2895     * Scroll indicator direction for the bottom edge of the view.
2896     *
2897     * @see #setScrollIndicators(int)
2898     * @see #setScrollIndicators(int, int)
2899     * @see #getScrollIndicators()
2900     */
2901    public static final int SCROLL_INDICATOR_BOTTOM =
2902            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2903
2904    /**
2905     * Scroll indicator direction for the left edge of the view.
2906     *
2907     * @see #setScrollIndicators(int)
2908     * @see #setScrollIndicators(int, int)
2909     * @see #getScrollIndicators()
2910     */
2911    public static final int SCROLL_INDICATOR_LEFT =
2912            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2913
2914    /**
2915     * Scroll indicator direction for the right edge of the view.
2916     *
2917     * @see #setScrollIndicators(int)
2918     * @see #setScrollIndicators(int, int)
2919     * @see #getScrollIndicators()
2920     */
2921    public static final int SCROLL_INDICATOR_RIGHT =
2922            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2923
2924    /**
2925     * Scroll indicator direction for the starting edge of the view.
2926     * <p>
2927     * Resolved according to the view's layout direction, see
2928     * {@link #getLayoutDirection()} for more information.
2929     *
2930     * @see #setScrollIndicators(int)
2931     * @see #setScrollIndicators(int, int)
2932     * @see #getScrollIndicators()
2933     */
2934    public static final int SCROLL_INDICATOR_START =
2935            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2936
2937    /**
2938     * Scroll indicator direction for the ending edge of the view.
2939     * <p>
2940     * Resolved according to the view's layout direction, see
2941     * {@link #getLayoutDirection()} for more information.
2942     *
2943     * @see #setScrollIndicators(int)
2944     * @see #setScrollIndicators(int, int)
2945     * @see #getScrollIndicators()
2946     */
2947    public static final int SCROLL_INDICATOR_END =
2948            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2949
2950    /**
2951     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2952     * into this view.<p>
2953     */
2954    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2955
2956    /**
2957     * Flag indicating that the view is a root of a keyboard navigation cluster.
2958     *
2959     * @see #isKeyboardNavigationCluster()
2960     * @see #setKeyboardNavigationCluster(boolean)
2961     */
2962    private static final int PFLAG3_CLUSTER = 0x8000;
2963
2964    /**
2965     * Indicates that the user is currently touching the screen.
2966     * Currently used for the tooltip positioning only.
2967     */
2968    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2969
2970    /**
2971     * Flag indicating that this view is the default-focus view.
2972     *
2973     * @see #isFocusedByDefault()
2974     * @see #setFocusedByDefault(boolean)
2975     */
2976    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2977
2978    /**
2979     * Shift for the place where the autofill mode is stored in the pflags
2980     *
2981     * @see #getAutofillMode()
2982     * @see #setAutofillMode(int)
2983     */
2984    private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
2985
2986    /**
2987     * Mask for autofill modes
2988     *
2989     * @see #getAutofillMode()
2990     * @see #setAutofillMode(int)
2991     */
2992    private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
2993            | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
2994
2995    /**
2996     * Shift for the bits in {@link #mPrivateFlags3} related to the
2997     * "importantForAutofill" attribute.
2998     */
2999    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
3000
3001    /**
3002     * Mask for obtaining the bits which specify how to determine
3003     * whether a view is important for autofill.
3004     */
3005    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3006            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
3007            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3008
3009    /**
3010     * Whether this view has rendered elements that overlap (see {@link
3011     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3012     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3013     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3014     * determined by whatever {@link #hasOverlappingRendering()} returns.
3015     */
3016    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3017
3018    /**
3019     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3020     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3021     */
3022    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3023
3024    /**
3025     * Flag indicating that the view is temporarily detached from the parent view.
3026     *
3027     * @see #onStartTemporaryDetach()
3028     * @see #onFinishTemporaryDetach()
3029     */
3030    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3031
3032    /**
3033     * Flag indicating that the view does not wish to be revealed within its parent
3034     * hierarchy when it gains focus. Expressed in the negative since the historical
3035     * default behavior is to reveal on focus; this flag suppresses that behavior.
3036     *
3037     * @see #setRevealOnFocusHint(boolean)
3038     * @see #getRevealOnFocusHint()
3039     */
3040    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3041
3042    /* End of masks for mPrivateFlags3 */
3043
3044    /**
3045     * Always allow a user to over-scroll this view, provided it is a
3046     * view that can scroll.
3047     *
3048     * @see #getOverScrollMode()
3049     * @see #setOverScrollMode(int)
3050     */
3051    public static final int OVER_SCROLL_ALWAYS = 0;
3052
3053    /**
3054     * Allow a user to over-scroll this view only if the content is large
3055     * enough to meaningfully scroll, provided it is a view that can scroll.
3056     *
3057     * @see #getOverScrollMode()
3058     * @see #setOverScrollMode(int)
3059     */
3060    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3061
3062    /**
3063     * Never allow a user to over-scroll this view.
3064     *
3065     * @see #getOverScrollMode()
3066     * @see #setOverScrollMode(int)
3067     */
3068    public static final int OVER_SCROLL_NEVER = 2;
3069
3070    /**
3071     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3072     * requested the system UI (status bar) to be visible (the default).
3073     *
3074     * @see #setSystemUiVisibility(int)
3075     */
3076    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3077
3078    /**
3079     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3080     * system UI to enter an unobtrusive "low profile" mode.
3081     *
3082     * <p>This is for use in games, book readers, video players, or any other
3083     * "immersive" application where the usual system chrome is deemed too distracting.
3084     *
3085     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3086     *
3087     * @see #setSystemUiVisibility(int)
3088     */
3089    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3090
3091    /**
3092     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3093     * system navigation be temporarily hidden.
3094     *
3095     * <p>This is an even less obtrusive state than that called for by
3096     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3097     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3098     * those to disappear. This is useful (in conjunction with the
3099     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3100     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3101     * window flags) for displaying content using every last pixel on the display.
3102     *
3103     * <p>There is a limitation: because navigation controls are so important, the least user
3104     * interaction will cause them to reappear immediately.  When this happens, both
3105     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3106     * so that both elements reappear at the same time.
3107     *
3108     * @see #setSystemUiVisibility(int)
3109     */
3110    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3111
3112    /**
3113     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3114     * into the normal fullscreen mode so that its content can take over the screen
3115     * while still allowing the user to interact with the application.
3116     *
3117     * <p>This has the same visual effect as
3118     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3119     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3120     * meaning that non-critical screen decorations (such as the status bar) will be
3121     * hidden while the user is in the View's window, focusing the experience on
3122     * that content.  Unlike the window flag, if you are using ActionBar in
3123     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3124     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3125     * hide the action bar.
3126     *
3127     * <p>This approach to going fullscreen is best used over the window flag when
3128     * it is a transient state -- that is, the application does this at certain
3129     * points in its user interaction where it wants to allow the user to focus
3130     * on content, but not as a continuous state.  For situations where the application
3131     * would like to simply stay full screen the entire time (such as a game that
3132     * wants to take over the screen), the
3133     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3134     * is usually a better approach.  The state set here will be removed by the system
3135     * in various situations (such as the user moving to another application) like
3136     * the other system UI states.
3137     *
3138     * <p>When using this flag, the application should provide some easy facility
3139     * for the user to go out of it.  A common example would be in an e-book
3140     * reader, where tapping on the screen brings back whatever screen and UI
3141     * decorations that had been hidden while the user was immersed in reading
3142     * the book.
3143     *
3144     * @see #setSystemUiVisibility(int)
3145     */
3146    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3147
3148    /**
3149     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3150     * flags, we would like a stable view of the content insets given to
3151     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3152     * will always represent the worst case that the application can expect
3153     * as a continuous state.  In the stock Android UI this is the space for
3154     * the system bar, nav bar, and status bar, but not more transient elements
3155     * such as an input method.
3156     *
3157     * The stable layout your UI sees is based on the system UI modes you can
3158     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3159     * then you will get a stable layout for changes of the
3160     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3161     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3162     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3163     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3164     * with a stable layout.  (Note that you should avoid using
3165     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3166     *
3167     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3168     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3169     * then a hidden status bar will be considered a "stable" state for purposes
3170     * here.  This allows your UI to continually hide the status bar, while still
3171     * using the system UI flags to hide the action bar while still retaining
3172     * a stable layout.  Note that changing the window fullscreen flag will never
3173     * provide a stable layout for a clean transition.
3174     *
3175     * <p>If you are using ActionBar in
3176     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3177     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3178     * insets it adds to those given to the application.
3179     */
3180    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3181
3182    /**
3183     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3184     * to be laid out as if it has requested
3185     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3186     * allows it to avoid artifacts when switching in and out of that mode, at
3187     * the expense that some of its user interface may be covered by screen
3188     * decorations when they are shown.  You can perform layout of your inner
3189     * UI elements to account for the navigation system UI through the
3190     * {@link #fitSystemWindows(Rect)} method.
3191     */
3192    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3193
3194    /**
3195     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3196     * to be laid out as if it has requested
3197     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3198     * allows it to avoid artifacts when switching in and out of that mode, at
3199     * the expense that some of its user interface may be covered by screen
3200     * decorations when they are shown.  You can perform layout of your inner
3201     * UI elements to account for non-fullscreen system UI through the
3202     * {@link #fitSystemWindows(Rect)} method.
3203     */
3204    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3205
3206    /**
3207     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3208     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3209     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3210     * user interaction.
3211     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3212     * has an effect when used in combination with that flag.</p>
3213     */
3214    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3215
3216    /**
3217     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3218     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3219     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3220     * experience while also hiding the system bars.  If this flag is not set,
3221     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3222     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3223     * if the user swipes from the top of the screen.
3224     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3225     * system gestures, such as swiping from the top of the screen.  These transient system bars
3226     * will overlay app’s content, may have some degree of transparency, and will automatically
3227     * hide after a short timeout.
3228     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3229     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3230     * with one or both of those flags.</p>
3231     */
3232    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3233
3234    /**
3235     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3236     * is compatible with light status bar backgrounds.
3237     *
3238     * <p>For this to take effect, the window must request
3239     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3240     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3241     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3242     *         FLAG_TRANSLUCENT_STATUS}.
3243     *
3244     * @see android.R.attr#windowLightStatusBar
3245     */
3246    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3247
3248    /**
3249     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3250     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3251     */
3252    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3253
3254    /**
3255     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3256     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3257     */
3258    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3259
3260    /**
3261     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3262     * that is compatible with light navigation bar backgrounds.
3263     *
3264     * <p>For this to take effect, the window must request
3265     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3266     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3267     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3268     *         FLAG_TRANSLUCENT_NAVIGATION}.
3269     */
3270    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3271
3272    /**
3273     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3274     */
3275    @Deprecated
3276    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3277
3278    /**
3279     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3280     */
3281    @Deprecated
3282    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3283
3284    /**
3285     * @hide
3286     *
3287     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3288     * out of the public fields to keep the undefined bits out of the developer's way.
3289     *
3290     * Flag to make the status bar not expandable.  Unless you also
3291     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3292     */
3293    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3294
3295    /**
3296     * @hide
3297     *
3298     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3299     * out of the public fields to keep the undefined bits out of the developer's way.
3300     *
3301     * Flag to hide notification icons and scrolling ticker text.
3302     */
3303    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3304
3305    /**
3306     * @hide
3307     *
3308     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3309     * out of the public fields to keep the undefined bits out of the developer's way.
3310     *
3311     * Flag to disable incoming notification alerts.  This will not block
3312     * icons, but it will block sound, vibrating and other visual or aural notifications.
3313     */
3314    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3315
3316    /**
3317     * @hide
3318     *
3319     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3320     * out of the public fields to keep the undefined bits out of the developer's way.
3321     *
3322     * Flag to hide only the scrolling ticker.  Note that
3323     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3324     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3325     */
3326    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3327
3328    /**
3329     * @hide
3330     *
3331     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3332     * out of the public fields to keep the undefined bits out of the developer's way.
3333     *
3334     * Flag to hide the center system info area.
3335     */
3336    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3337
3338    /**
3339     * @hide
3340     *
3341     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3342     * out of the public fields to keep the undefined bits out of the developer's way.
3343     *
3344     * Flag to hide only the home button.  Don't use this
3345     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3346     */
3347    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3348
3349    /**
3350     * @hide
3351     *
3352     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3353     * out of the public fields to keep the undefined bits out of the developer's way.
3354     *
3355     * Flag to hide only the back button. Don't use this
3356     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3357     */
3358    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3359
3360    /**
3361     * @hide
3362     *
3363     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3364     * out of the public fields to keep the undefined bits out of the developer's way.
3365     *
3366     * Flag to hide only the clock.  You might use this if your activity has
3367     * its own clock making the status bar's clock redundant.
3368     */
3369    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3370
3371    /**
3372     * @hide
3373     *
3374     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3375     * out of the public fields to keep the undefined bits out of the developer's way.
3376     *
3377     * Flag to hide only the recent apps button. Don't use this
3378     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3379     */
3380    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3381
3382    /**
3383     * @hide
3384     *
3385     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3386     * out of the public fields to keep the undefined bits out of the developer's way.
3387     *
3388     * Flag to disable the global search gesture. Don't use this
3389     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3390     */
3391    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3392
3393    /**
3394     * @hide
3395     *
3396     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3397     * out of the public fields to keep the undefined bits out of the developer's way.
3398     *
3399     * Flag to specify that the status bar is displayed in transient mode.
3400     */
3401    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3402
3403    /**
3404     * @hide
3405     *
3406     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3407     * out of the public fields to keep the undefined bits out of the developer's way.
3408     *
3409     * Flag to specify that the navigation bar is displayed in transient mode.
3410     */
3411    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3412
3413    /**
3414     * @hide
3415     *
3416     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3417     * out of the public fields to keep the undefined bits out of the developer's way.
3418     *
3419     * Flag to specify that the hidden status bar would like to be shown.
3420     */
3421    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3422
3423    /**
3424     * @hide
3425     *
3426     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3427     * out of the public fields to keep the undefined bits out of the developer's way.
3428     *
3429     * Flag to specify that the hidden navigation bar would like to be shown.
3430     */
3431    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3432
3433    /**
3434     * @hide
3435     *
3436     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3437     * out of the public fields to keep the undefined bits out of the developer's way.
3438     *
3439     * Flag to specify that the status bar is displayed in translucent mode.
3440     */
3441    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3442
3443    /**
3444     * @hide
3445     *
3446     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3447     * out of the public fields to keep the undefined bits out of the developer's way.
3448     *
3449     * Flag to specify that the navigation bar is displayed in translucent mode.
3450     */
3451    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3452
3453    /**
3454     * @hide
3455     *
3456     * Makes navigation bar transparent (but not the status bar).
3457     */
3458    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3459
3460    /**
3461     * @hide
3462     *
3463     * Makes status bar transparent (but not the navigation bar).
3464     */
3465    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3466
3467    /**
3468     * @hide
3469     *
3470     * Makes both status bar and navigation bar transparent.
3471     */
3472    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3473            | STATUS_BAR_TRANSPARENT;
3474
3475    /**
3476     * @hide
3477     */
3478    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3479
3480    /**
3481     * These are the system UI flags that can be cleared by events outside
3482     * of an application.  Currently this is just the ability to tap on the
3483     * screen while hiding the navigation bar to have it return.
3484     * @hide
3485     */
3486    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3487            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3488            | SYSTEM_UI_FLAG_FULLSCREEN;
3489
3490    /**
3491     * Flags that can impact the layout in relation to system UI.
3492     */
3493    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3494            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3495            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3496
3497    /** @hide */
3498    @IntDef(flag = true,
3499            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3500    @Retention(RetentionPolicy.SOURCE)
3501    public @interface FindViewFlags {}
3502
3503    /**
3504     * Find views that render the specified text.
3505     *
3506     * @see #findViewsWithText(ArrayList, CharSequence, int)
3507     */
3508    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3509
3510    /**
3511     * Find find views that contain the specified content description.
3512     *
3513     * @see #findViewsWithText(ArrayList, CharSequence, int)
3514     */
3515    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3516
3517    /**
3518     * Find views that contain {@link AccessibilityNodeProvider}. Such
3519     * a View is a root of virtual view hierarchy and may contain the searched
3520     * text. If this flag is set Views with providers are automatically
3521     * added and it is a responsibility of the client to call the APIs of
3522     * the provider to determine whether the virtual tree rooted at this View
3523     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3524     * representing the virtual views with this text.
3525     *
3526     * @see #findViewsWithText(ArrayList, CharSequence, int)
3527     *
3528     * @hide
3529     */
3530    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3531
3532    /**
3533     * The undefined cursor position.
3534     *
3535     * @hide
3536     */
3537    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3538
3539    /**
3540     * Indicates that the screen has changed state and is now off.
3541     *
3542     * @see #onScreenStateChanged(int)
3543     */
3544    public static final int SCREEN_STATE_OFF = 0x0;
3545
3546    /**
3547     * Indicates that the screen has changed state and is now on.
3548     *
3549     * @see #onScreenStateChanged(int)
3550     */
3551    public static final int SCREEN_STATE_ON = 0x1;
3552
3553    /**
3554     * Indicates no axis of view scrolling.
3555     */
3556    public static final int SCROLL_AXIS_NONE = 0;
3557
3558    /**
3559     * Indicates scrolling along the horizontal axis.
3560     */
3561    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3562
3563    /**
3564     * Indicates scrolling along the vertical axis.
3565     */
3566    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3567
3568    /**
3569     * Controls the over-scroll mode for this view.
3570     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3571     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3572     * and {@link #OVER_SCROLL_NEVER}.
3573     */
3574    private int mOverScrollMode;
3575
3576    /**
3577     * The parent this view is attached to.
3578     * {@hide}
3579     *
3580     * @see #getParent()
3581     */
3582    protected ViewParent mParent;
3583
3584    /**
3585     * {@hide}
3586     */
3587    AttachInfo mAttachInfo;
3588
3589    /**
3590     * {@hide}
3591     */
3592    @ViewDebug.ExportedProperty(flagMapping = {
3593        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3594                name = "FORCE_LAYOUT"),
3595        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3596                name = "LAYOUT_REQUIRED"),
3597        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3598            name = "DRAWING_CACHE_INVALID", outputIf = false),
3599        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3600        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3601        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3602        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3603    }, formatToHexString = true)
3604
3605    /* @hide */
3606    public int mPrivateFlags;
3607    int mPrivateFlags2;
3608    int mPrivateFlags3;
3609
3610    /**
3611     * This view's request for the visibility of the status bar.
3612     * @hide
3613     */
3614    @ViewDebug.ExportedProperty(flagMapping = {
3615        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3616                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3617                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3618        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3619                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3620                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3621        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3622                                equals = SYSTEM_UI_FLAG_VISIBLE,
3623                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3624    }, formatToHexString = true)
3625    int mSystemUiVisibility;
3626
3627    /**
3628     * Reference count for transient state.
3629     * @see #setHasTransientState(boolean)
3630     */
3631    int mTransientStateCount = 0;
3632
3633    /**
3634     * Count of how many windows this view has been attached to.
3635     */
3636    int mWindowAttachCount;
3637
3638    /**
3639     * The layout parameters associated with this view and used by the parent
3640     * {@link android.view.ViewGroup} to determine how this view should be
3641     * laid out.
3642     * {@hide}
3643     */
3644    protected ViewGroup.LayoutParams mLayoutParams;
3645
3646    /**
3647     * The view flags hold various views states.
3648     * {@hide}
3649     */
3650    @ViewDebug.ExportedProperty(formatToHexString = true)
3651    int mViewFlags;
3652
3653    static class TransformationInfo {
3654        /**
3655         * The transform matrix for the View. This transform is calculated internally
3656         * based on the translation, rotation, and scale properties.
3657         *
3658         * Do *not* use this variable directly; instead call getMatrix(), which will
3659         * load the value from the View's RenderNode.
3660         */
3661        private final Matrix mMatrix = new Matrix();
3662
3663        /**
3664         * The inverse transform matrix for the View. This transform is calculated
3665         * internally based on the translation, rotation, and scale properties.
3666         *
3667         * Do *not* use this variable directly; instead call getInverseMatrix(),
3668         * which will load the value from the View's RenderNode.
3669         */
3670        private Matrix mInverseMatrix;
3671
3672        /**
3673         * The opacity of the View. This is a value from 0 to 1, where 0 means
3674         * completely transparent and 1 means completely opaque.
3675         */
3676        @ViewDebug.ExportedProperty
3677        float mAlpha = 1f;
3678
3679        /**
3680         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3681         * property only used by transitions, which is composited with the other alpha
3682         * values to calculate the final visual alpha value.
3683         */
3684        float mTransitionAlpha = 1f;
3685    }
3686
3687    /** @hide */
3688    public TransformationInfo mTransformationInfo;
3689
3690    /**
3691     * Current clip bounds. to which all drawing of this view are constrained.
3692     */
3693    Rect mClipBounds = null;
3694
3695    private boolean mLastIsOpaque;
3696
3697    /**
3698     * The distance in pixels from the left edge of this view's parent
3699     * to the left edge of this view.
3700     * {@hide}
3701     */
3702    @ViewDebug.ExportedProperty(category = "layout")
3703    protected int mLeft;
3704    /**
3705     * The distance in pixels from the left edge of this view's parent
3706     * to the right edge of this view.
3707     * {@hide}
3708     */
3709    @ViewDebug.ExportedProperty(category = "layout")
3710    protected int mRight;
3711    /**
3712     * The distance in pixels from the top edge of this view's parent
3713     * to the top edge of this view.
3714     * {@hide}
3715     */
3716    @ViewDebug.ExportedProperty(category = "layout")
3717    protected int mTop;
3718    /**
3719     * The distance in pixels from the top edge of this view's parent
3720     * to the bottom edge of this view.
3721     * {@hide}
3722     */
3723    @ViewDebug.ExportedProperty(category = "layout")
3724    protected int mBottom;
3725
3726    /**
3727     * The offset, in pixels, by which the content of this view is scrolled
3728     * horizontally.
3729     * {@hide}
3730     */
3731    @ViewDebug.ExportedProperty(category = "scrolling")
3732    protected int mScrollX;
3733    /**
3734     * The offset, in pixels, by which the content of this view is scrolled
3735     * vertically.
3736     * {@hide}
3737     */
3738    @ViewDebug.ExportedProperty(category = "scrolling")
3739    protected int mScrollY;
3740
3741    /**
3742     * The left padding in pixels, that is the distance in pixels between the
3743     * left edge of this view and the left edge of its content.
3744     * {@hide}
3745     */
3746    @ViewDebug.ExportedProperty(category = "padding")
3747    protected int mPaddingLeft = 0;
3748    /**
3749     * The right padding in pixels, that is the distance in pixels between the
3750     * right edge of this view and the right edge of its content.
3751     * {@hide}
3752     */
3753    @ViewDebug.ExportedProperty(category = "padding")
3754    protected int mPaddingRight = 0;
3755    /**
3756     * The top padding in pixels, that is the distance in pixels between the
3757     * top edge of this view and the top edge of its content.
3758     * {@hide}
3759     */
3760    @ViewDebug.ExportedProperty(category = "padding")
3761    protected int mPaddingTop;
3762    /**
3763     * The bottom padding in pixels, that is the distance in pixels between the
3764     * bottom edge of this view and the bottom edge of its content.
3765     * {@hide}
3766     */
3767    @ViewDebug.ExportedProperty(category = "padding")
3768    protected int mPaddingBottom;
3769
3770    /**
3771     * The layout insets in pixels, that is the distance in pixels between the
3772     * visible edges of this view its bounds.
3773     */
3774    private Insets mLayoutInsets;
3775
3776    /**
3777     * Briefly describes the view and is primarily used for accessibility support.
3778     */
3779    private CharSequence mContentDescription;
3780
3781    /**
3782     * Specifies the id of a view for which this view serves as a label for
3783     * accessibility purposes.
3784     */
3785    private int mLabelForId = View.NO_ID;
3786
3787    /**
3788     * Predicate for matching labeled view id with its label for
3789     * accessibility purposes.
3790     */
3791    private MatchLabelForPredicate mMatchLabelForPredicate;
3792
3793    /**
3794     * Specifies a view before which this one is visited in accessibility traversal.
3795     */
3796    private int mAccessibilityTraversalBeforeId = NO_ID;
3797
3798    /**
3799     * Specifies a view after which this one is visited in accessibility traversal.
3800     */
3801    private int mAccessibilityTraversalAfterId = NO_ID;
3802
3803    /**
3804     * Predicate for matching a view by its id.
3805     */
3806    private MatchIdPredicate mMatchIdPredicate;
3807
3808    /**
3809     * Cache the paddingRight set by the user to append to the scrollbar's size.
3810     *
3811     * @hide
3812     */
3813    @ViewDebug.ExportedProperty(category = "padding")
3814    protected int mUserPaddingRight;
3815
3816    /**
3817     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3818     *
3819     * @hide
3820     */
3821    @ViewDebug.ExportedProperty(category = "padding")
3822    protected int mUserPaddingBottom;
3823
3824    /**
3825     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3826     *
3827     * @hide
3828     */
3829    @ViewDebug.ExportedProperty(category = "padding")
3830    protected int mUserPaddingLeft;
3831
3832    /**
3833     * Cache the paddingStart set by the user to append to the scrollbar's size.
3834     *
3835     */
3836    @ViewDebug.ExportedProperty(category = "padding")
3837    int mUserPaddingStart;
3838
3839    /**
3840     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3841     *
3842     */
3843    @ViewDebug.ExportedProperty(category = "padding")
3844    int mUserPaddingEnd;
3845
3846    /**
3847     * Cache initial left padding.
3848     *
3849     * @hide
3850     */
3851    int mUserPaddingLeftInitial;
3852
3853    /**
3854     * Cache initial right padding.
3855     *
3856     * @hide
3857     */
3858    int mUserPaddingRightInitial;
3859
3860    /**
3861     * Default undefined padding
3862     */
3863    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3864
3865    /**
3866     * Cache if a left padding has been defined
3867     */
3868    private boolean mLeftPaddingDefined = false;
3869
3870    /**
3871     * Cache if a right padding has been defined
3872     */
3873    private boolean mRightPaddingDefined = false;
3874
3875    /**
3876     * @hide
3877     */
3878    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3879    /**
3880     * @hide
3881     */
3882    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3883
3884    private LongSparseLongArray mMeasureCache;
3885
3886    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3887    private Drawable mBackground;
3888    private TintInfo mBackgroundTint;
3889
3890    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3891    private ForegroundInfo mForegroundInfo;
3892
3893    private Drawable mScrollIndicatorDrawable;
3894
3895    /**
3896     * RenderNode used for backgrounds.
3897     * <p>
3898     * When non-null and valid, this is expected to contain an up-to-date copy
3899     * of the background drawable. It is cleared on temporary detach, and reset
3900     * on cleanup.
3901     */
3902    private RenderNode mBackgroundRenderNode;
3903
3904    private int mBackgroundResource;
3905    private boolean mBackgroundSizeChanged;
3906
3907    private String mTransitionName;
3908
3909    static class TintInfo {
3910        ColorStateList mTintList;
3911        PorterDuff.Mode mTintMode;
3912        boolean mHasTintMode;
3913        boolean mHasTintList;
3914    }
3915
3916    private static class ForegroundInfo {
3917        private Drawable mDrawable;
3918        private TintInfo mTintInfo;
3919        private int mGravity = Gravity.FILL;
3920        private boolean mInsidePadding = true;
3921        private boolean mBoundsChanged = true;
3922        private final Rect mSelfBounds = new Rect();
3923        private final Rect mOverlayBounds = new Rect();
3924    }
3925
3926    static class ListenerInfo {
3927        /**
3928         * Listener used to dispatch focus change events.
3929         * This field should be made private, so it is hidden from the SDK.
3930         * {@hide}
3931         */
3932        protected OnFocusChangeListener mOnFocusChangeListener;
3933
3934        /**
3935         * Listeners for layout change events.
3936         */
3937        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3938
3939        protected OnScrollChangeListener mOnScrollChangeListener;
3940
3941        /**
3942         * Listeners for attach events.
3943         */
3944        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3945
3946        /**
3947         * Listener used to dispatch click events.
3948         * This field should be made private, so it is hidden from the SDK.
3949         * {@hide}
3950         */
3951        public OnClickListener mOnClickListener;
3952
3953        /**
3954         * Listener used to dispatch long click events.
3955         * This field should be made private, so it is hidden from the SDK.
3956         * {@hide}
3957         */
3958        protected OnLongClickListener mOnLongClickListener;
3959
3960        /**
3961         * Listener used to dispatch context click events. This field should be made private, so it
3962         * is hidden from the SDK.
3963         * {@hide}
3964         */
3965        protected OnContextClickListener mOnContextClickListener;
3966
3967        /**
3968         * Listener used to build the context menu.
3969         * This field should be made private, so it is hidden from the SDK.
3970         * {@hide}
3971         */
3972        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3973
3974        private OnKeyListener mOnKeyListener;
3975
3976        private OnTouchListener mOnTouchListener;
3977
3978        private OnHoverListener mOnHoverListener;
3979
3980        private OnGenericMotionListener mOnGenericMotionListener;
3981
3982        private OnDragListener mOnDragListener;
3983
3984        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3985
3986        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3987
3988        OnCapturedPointerListener mOnCapturedPointerListener;
3989    }
3990
3991    ListenerInfo mListenerInfo;
3992
3993    private static class TooltipInfo {
3994        /**
3995         * Text to be displayed in a tooltip popup.
3996         */
3997        @Nullable
3998        CharSequence mTooltipText;
3999
4000        /**
4001         * View-relative position of the tooltip anchor point.
4002         */
4003        int mAnchorX;
4004        int mAnchorY;
4005
4006        /**
4007         * The tooltip popup.
4008         */
4009        @Nullable
4010        TooltipPopup mTooltipPopup;
4011
4012        /**
4013         * Set to true if the tooltip was shown as a result of a long click.
4014         */
4015        boolean mTooltipFromLongClick;
4016
4017        /**
4018         * Keep these Runnables so that they can be used to reschedule.
4019         */
4020        Runnable mShowTooltipRunnable;
4021        Runnable mHideTooltipRunnable;
4022    }
4023
4024    TooltipInfo mTooltipInfo;
4025
4026    // Temporary values used to hold (x,y) coordinates when delegating from the
4027    // two-arg performLongClick() method to the legacy no-arg version.
4028    private float mLongClickX = Float.NaN;
4029    private float mLongClickY = Float.NaN;
4030
4031    /**
4032     * The application environment this view lives in.
4033     * This field should be made private, so it is hidden from the SDK.
4034     * {@hide}
4035     */
4036    @ViewDebug.ExportedProperty(deepExport = true)
4037    protected Context mContext;
4038
4039    private final Resources mResources;
4040
4041    private ScrollabilityCache mScrollCache;
4042
4043    private int[] mDrawableState = null;
4044
4045    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4046
4047    /**
4048     * Animator that automatically runs based on state changes.
4049     */
4050    private StateListAnimator mStateListAnimator;
4051
4052    /**
4053     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4054     * the user may specify which view to go to next.
4055     */
4056    private int mNextFocusLeftId = View.NO_ID;
4057
4058    /**
4059     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4060     * the user may specify which view to go to next.
4061     */
4062    private int mNextFocusRightId = View.NO_ID;
4063
4064    /**
4065     * When this view has focus and the next focus is {@link #FOCUS_UP},
4066     * the user may specify which view to go to next.
4067     */
4068    private int mNextFocusUpId = View.NO_ID;
4069
4070    /**
4071     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4072     * the user may specify which view to go to next.
4073     */
4074    private int mNextFocusDownId = View.NO_ID;
4075
4076    /**
4077     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4078     * the user may specify which view to go to next.
4079     */
4080    int mNextFocusForwardId = View.NO_ID;
4081
4082    /**
4083     * User-specified next keyboard navigation cluster.
4084     */
4085    int mNextClusterForwardId = View.NO_ID;
4086
4087    private CheckForLongPress mPendingCheckForLongPress;
4088    private CheckForTap mPendingCheckForTap = null;
4089    private PerformClick mPerformClick;
4090    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4091
4092    private UnsetPressedState mUnsetPressedState;
4093
4094    /**
4095     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4096     * up event while a long press is invoked as soon as the long press duration is reached, so
4097     * a long press could be performed before the tap is checked, in which case the tap's action
4098     * should not be invoked.
4099     */
4100    private boolean mHasPerformedLongPress;
4101
4102    /**
4103     * Whether a context click button is currently pressed down. This is true when the stylus is
4104     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4105     * pressed. This is false once the button is released or if the stylus has been lifted.
4106     */
4107    private boolean mInContextButtonPress;
4108
4109    /**
4110     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4111     * true after a stylus button press has occured, when the next up event should not be recognized
4112     * as a tap.
4113     */
4114    private boolean mIgnoreNextUpEvent;
4115
4116    /**
4117     * The minimum height of the view. We'll try our best to have the height
4118     * of this view to at least this amount.
4119     */
4120    @ViewDebug.ExportedProperty(category = "measurement")
4121    private int mMinHeight;
4122
4123    /**
4124     * The minimum width of the view. We'll try our best to have the width
4125     * of this view to at least this amount.
4126     */
4127    @ViewDebug.ExportedProperty(category = "measurement")
4128    private int mMinWidth;
4129
4130    /**
4131     * The delegate to handle touch events that are physically in this view
4132     * but should be handled by another view.
4133     */
4134    private TouchDelegate mTouchDelegate = null;
4135
4136    /**
4137     * Solid color to use as a background when creating the drawing cache. Enables
4138     * the cache to use 16 bit bitmaps instead of 32 bit.
4139     */
4140    private int mDrawingCacheBackgroundColor = 0;
4141
4142    /**
4143     * Special tree observer used when mAttachInfo is null.
4144     */
4145    private ViewTreeObserver mFloatingTreeObserver;
4146
4147    /**
4148     * Cache the touch slop from the context that created the view.
4149     */
4150    private int mTouchSlop;
4151
4152    /**
4153     * Object that handles automatic animation of view properties.
4154     */
4155    private ViewPropertyAnimator mAnimator = null;
4156
4157    /**
4158     * List of registered FrameMetricsObservers.
4159     */
4160    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4161
4162    /**
4163     * Flag indicating that a drag can cross window boundaries.  When
4164     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4165     * with this flag set, all visible applications with targetSdkVersion >=
4166     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4167     * in the drag operation and receive the dragged content.
4168     *
4169     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4170     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4171     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4172     */
4173    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4174
4175    /**
4176     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4177     * request read access to the content URI(s) contained in the {@link ClipData} object.
4178     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
4179     */
4180    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4181
4182    /**
4183     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4184     * request write access to the content URI(s) contained in the {@link ClipData} object.
4185     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
4186     */
4187    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4188
4189    /**
4190     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4191     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4192     * reboots until explicitly revoked with
4193     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
4194     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4195     */
4196    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4197            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4198
4199    /**
4200     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4201     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4202     * match against the original granted URI.
4203     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
4204     */
4205    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4206            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4207
4208    /**
4209     * Flag indicating that the drag shadow will be opaque.  When
4210     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4211     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4212     */
4213    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4214
4215    /**
4216     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4217     */
4218    private float mVerticalScrollFactor;
4219
4220    /**
4221     * Position of the vertical scroll bar.
4222     */
4223    private int mVerticalScrollbarPosition;
4224
4225    /**
4226     * Position the scroll bar at the default position as determined by the system.
4227     */
4228    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4229
4230    /**
4231     * Position the scroll bar along the left edge.
4232     */
4233    public static final int SCROLLBAR_POSITION_LEFT = 1;
4234
4235    /**
4236     * Position the scroll bar along the right edge.
4237     */
4238    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4239
4240    /**
4241     * Indicates that the view does not have a layer.
4242     *
4243     * @see #getLayerType()
4244     * @see #setLayerType(int, android.graphics.Paint)
4245     * @see #LAYER_TYPE_SOFTWARE
4246     * @see #LAYER_TYPE_HARDWARE
4247     */
4248    public static final int LAYER_TYPE_NONE = 0;
4249
4250    /**
4251     * <p>Indicates that the view has a software layer. A software layer is backed
4252     * by a bitmap and causes the view to be rendered using Android's software
4253     * rendering pipeline, even if hardware acceleration is enabled.</p>
4254     *
4255     * <p>Software layers have various usages:</p>
4256     * <p>When the application is not using hardware acceleration, a software layer
4257     * is useful to apply a specific color filter and/or blending mode and/or
4258     * translucency to a view and all its children.</p>
4259     * <p>When the application is using hardware acceleration, a software layer
4260     * is useful to render drawing primitives not supported by the hardware
4261     * accelerated pipeline. It can also be used to cache a complex view tree
4262     * into a texture and reduce the complexity of drawing operations. For instance,
4263     * when animating a complex view tree with a translation, a software layer can
4264     * be used to render the view tree only once.</p>
4265     * <p>Software layers should be avoided when the affected view tree updates
4266     * often. Every update will require to re-render the software layer, which can
4267     * potentially be slow (particularly when hardware acceleration is turned on
4268     * since the layer will have to be uploaded into a hardware texture after every
4269     * update.)</p>
4270     *
4271     * @see #getLayerType()
4272     * @see #setLayerType(int, android.graphics.Paint)
4273     * @see #LAYER_TYPE_NONE
4274     * @see #LAYER_TYPE_HARDWARE
4275     */
4276    public static final int LAYER_TYPE_SOFTWARE = 1;
4277
4278    /**
4279     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4280     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4281     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4282     * rendering pipeline, but only if hardware acceleration is turned on for the
4283     * view hierarchy. When hardware acceleration is turned off, hardware layers
4284     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4285     *
4286     * <p>A hardware layer is useful to apply a specific color filter and/or
4287     * blending mode and/or translucency to a view and all its children.</p>
4288     * <p>A hardware layer can be used to cache a complex view tree into a
4289     * texture and reduce the complexity of drawing operations. For instance,
4290     * when animating a complex view tree with a translation, a hardware layer can
4291     * be used to render the view tree only once.</p>
4292     * <p>A hardware layer can also be used to increase the rendering quality when
4293     * rotation transformations are applied on a view. It can also be used to
4294     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4295     *
4296     * @see #getLayerType()
4297     * @see #setLayerType(int, android.graphics.Paint)
4298     * @see #LAYER_TYPE_NONE
4299     * @see #LAYER_TYPE_SOFTWARE
4300     */
4301    public static final int LAYER_TYPE_HARDWARE = 2;
4302
4303    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4304            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4305            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4306            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4307    })
4308    int mLayerType = LAYER_TYPE_NONE;
4309    Paint mLayerPaint;
4310
4311    /**
4312     * Set to true when drawing cache is enabled and cannot be created.
4313     *
4314     * @hide
4315     */
4316    public boolean mCachingFailed;
4317    private Bitmap mDrawingCache;
4318    private Bitmap mUnscaledDrawingCache;
4319
4320    /**
4321     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4322     * <p>
4323     * When non-null and valid, this is expected to contain an up-to-date copy
4324     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4325     * cleanup.
4326     */
4327    final RenderNode mRenderNode;
4328
4329    /**
4330     * Set to true when the view is sending hover accessibility events because it
4331     * is the innermost hovered view.
4332     */
4333    private boolean mSendingHoverAccessibilityEvents;
4334
4335    /**
4336     * Delegate for injecting accessibility functionality.
4337     */
4338    AccessibilityDelegate mAccessibilityDelegate;
4339
4340    /**
4341     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4342     * and add/remove objects to/from the overlay directly through the Overlay methods.
4343     */
4344    ViewOverlay mOverlay;
4345
4346    /**
4347     * The currently active parent view for receiving delegated nested scrolling events.
4348     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4349     * by {@link #stopNestedScroll()} at the same point where we clear
4350     * requestDisallowInterceptTouchEvent.
4351     */
4352    private ViewParent mNestedScrollingParent;
4353
4354    /**
4355     * Consistency verifier for debugging purposes.
4356     * @hide
4357     */
4358    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4359            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4360                    new InputEventConsistencyVerifier(this, 0) : null;
4361
4362    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4363
4364    private int[] mTempNestedScrollConsumed;
4365
4366    /**
4367     * An overlay is going to draw this View instead of being drawn as part of this
4368     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4369     * when this view is invalidated.
4370     */
4371    GhostView mGhostView;
4372
4373    /**
4374     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4375     * @hide
4376     */
4377    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4378    public String[] mAttributes;
4379
4380    /**
4381     * Maps a Resource id to its name.
4382     */
4383    private static SparseArray<String> mAttributeMap;
4384
4385    /**
4386     * Queue of pending runnables. Used to postpone calls to post() until this
4387     * view is attached and has a handler.
4388     */
4389    private HandlerActionQueue mRunQueue;
4390
4391    /**
4392     * The pointer icon when the mouse hovers on this view. The default is null.
4393     */
4394    private PointerIcon mPointerIcon;
4395
4396    /**
4397     * @hide
4398     */
4399    String mStartActivityRequestWho;
4400
4401    @Nullable
4402    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4403
4404    /**
4405     * Simple constructor to use when creating a view from code.
4406     *
4407     * @param context The Context the view is running in, through which it can
4408     *        access the current theme, resources, etc.
4409     */
4410    public View(Context context) {
4411        mContext = context;
4412        mResources = context != null ? context.getResources() : null;
4413        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4414        // Set some flags defaults
4415        mPrivateFlags2 =
4416                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4417                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4418                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4419                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4420                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4421                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4422        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4423        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4424        mUserPaddingStart = UNDEFINED_PADDING;
4425        mUserPaddingEnd = UNDEFINED_PADDING;
4426        mRenderNode = RenderNode.create(getClass().getName(), this);
4427
4428        if (!sCompatibilityDone && context != null) {
4429            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4430
4431            // Older apps may need this compatibility hack for measurement.
4432            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4433
4434            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4435            // of whether a layout was requested on that View.
4436            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4437
4438            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4439
4440            // In M and newer, our widgets can pass a "hint" value in the size
4441            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4442            // know what the expected parent size is going to be, so e.g. list items can size
4443            // themselves at 1/3 the size of their container. It breaks older apps though,
4444            // specifically apps that use some popular open source libraries.
4445            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4446
4447            // Old versions of the platform would give different results from
4448            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4449            // modes, so we always need to run an additional EXACTLY pass.
4450            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4451
4452            // Prior to N, layout params could change without requiring a
4453            // subsequent call to setLayoutParams() and they would usually
4454            // work. Partial layout breaks this assumption.
4455            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4456
4457            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4458            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4459            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4460
4461            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4462            // in apps so we target check it to avoid breaking existing apps.
4463            sPreserveMarginParamsInLayoutParamConversion =
4464                    targetSdkVersion >= Build.VERSION_CODES.N;
4465
4466            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4467
4468            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4469
4470            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4471
4472            sCompatibilityDone = true;
4473        }
4474    }
4475
4476    /**
4477     * Constructor that is called when inflating a view from XML. This is called
4478     * when a view is being constructed from an XML file, supplying attributes
4479     * that were specified in the XML file. This version uses a default style of
4480     * 0, so the only attribute values applied are those in the Context's Theme
4481     * and the given AttributeSet.
4482     *
4483     * <p>
4484     * The method onFinishInflate() will be called after all children have been
4485     * added.
4486     *
4487     * @param context The Context the view is running in, through which it can
4488     *        access the current theme, resources, etc.
4489     * @param attrs The attributes of the XML tag that is inflating the view.
4490     * @see #View(Context, AttributeSet, int)
4491     */
4492    public View(Context context, @Nullable AttributeSet attrs) {
4493        this(context, attrs, 0);
4494    }
4495
4496    /**
4497     * Perform inflation from XML and apply a class-specific base style from a
4498     * theme attribute. This constructor of View allows subclasses to use their
4499     * own base style when they are inflating. For example, a Button class's
4500     * constructor would call this version of the super class constructor and
4501     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4502     * allows the theme's button style to modify all of the base view attributes
4503     * (in particular its background) as well as the Button class's attributes.
4504     *
4505     * @param context The Context the view is running in, through which it can
4506     *        access the current theme, resources, etc.
4507     * @param attrs The attributes of the XML tag that is inflating the view.
4508     * @param defStyleAttr An attribute in the current theme that contains a
4509     *        reference to a style resource that supplies default values for
4510     *        the view. Can be 0 to not look for defaults.
4511     * @see #View(Context, AttributeSet)
4512     */
4513    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4514        this(context, attrs, defStyleAttr, 0);
4515    }
4516
4517    /**
4518     * Perform inflation from XML and apply a class-specific base style from a
4519     * theme attribute or style resource. This constructor of View allows
4520     * subclasses to use their own base style when they are inflating.
4521     * <p>
4522     * When determining the final value of a particular attribute, there are
4523     * four inputs that come into play:
4524     * <ol>
4525     * <li>Any attribute values in the given AttributeSet.
4526     * <li>The style resource specified in the AttributeSet (named "style").
4527     * <li>The default style specified by <var>defStyleAttr</var>.
4528     * <li>The default style specified by <var>defStyleRes</var>.
4529     * <li>The base values in this theme.
4530     * </ol>
4531     * <p>
4532     * Each of these inputs is considered in-order, with the first listed taking
4533     * precedence over the following ones. In other words, if in the
4534     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4535     * , then the button's text will <em>always</em> be black, regardless of
4536     * what is specified in any of the styles.
4537     *
4538     * @param context The Context the view is running in, through which it can
4539     *        access the current theme, resources, etc.
4540     * @param attrs The attributes of the XML tag that is inflating the view.
4541     * @param defStyleAttr An attribute in the current theme that contains a
4542     *        reference to a style resource that supplies default values for
4543     *        the view. Can be 0 to not look for defaults.
4544     * @param defStyleRes A resource identifier of a style resource that
4545     *        supplies default values for the view, used only if
4546     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4547     *        to not look for defaults.
4548     * @see #View(Context, AttributeSet, int)
4549     */
4550    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4551        this(context);
4552
4553        final TypedArray a = context.obtainStyledAttributes(
4554                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4555
4556        if (mDebugViewAttributes) {
4557            saveAttributeData(attrs, a);
4558        }
4559
4560        Drawable background = null;
4561
4562        int leftPadding = -1;
4563        int topPadding = -1;
4564        int rightPadding = -1;
4565        int bottomPadding = -1;
4566        int startPadding = UNDEFINED_PADDING;
4567        int endPadding = UNDEFINED_PADDING;
4568
4569        int padding = -1;
4570        int paddingHorizontal = -1;
4571        int paddingVertical = -1;
4572
4573        int viewFlagValues = 0;
4574        int viewFlagMasks = 0;
4575
4576        boolean setScrollContainer = false;
4577
4578        int x = 0;
4579        int y = 0;
4580
4581        float tx = 0;
4582        float ty = 0;
4583        float tz = 0;
4584        float elevation = 0;
4585        float rotation = 0;
4586        float rotationX = 0;
4587        float rotationY = 0;
4588        float sx = 1f;
4589        float sy = 1f;
4590        boolean transformSet = false;
4591
4592        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4593        int overScrollMode = mOverScrollMode;
4594        boolean initializeScrollbars = false;
4595        boolean initializeScrollIndicators = false;
4596
4597        boolean startPaddingDefined = false;
4598        boolean endPaddingDefined = false;
4599        boolean leftPaddingDefined = false;
4600        boolean rightPaddingDefined = false;
4601
4602        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4603
4604        // Set default values.
4605        viewFlagValues |= FOCUSABLE_AUTO;
4606        viewFlagMasks |= FOCUSABLE_AUTO;
4607
4608        final int N = a.getIndexCount();
4609        for (int i = 0; i < N; i++) {
4610            int attr = a.getIndex(i);
4611            switch (attr) {
4612                case com.android.internal.R.styleable.View_background:
4613                    background = a.getDrawable(attr);
4614                    break;
4615                case com.android.internal.R.styleable.View_padding:
4616                    padding = a.getDimensionPixelSize(attr, -1);
4617                    mUserPaddingLeftInitial = padding;
4618                    mUserPaddingRightInitial = padding;
4619                    leftPaddingDefined = true;
4620                    rightPaddingDefined = true;
4621                    break;
4622                case com.android.internal.R.styleable.View_paddingHorizontal:
4623                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4624                    mUserPaddingLeftInitial = paddingHorizontal;
4625                    mUserPaddingRightInitial = paddingHorizontal;
4626                    leftPaddingDefined = true;
4627                    rightPaddingDefined = true;
4628                    break;
4629                case com.android.internal.R.styleable.View_paddingVertical:
4630                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4631                    break;
4632                 case com.android.internal.R.styleable.View_paddingLeft:
4633                    leftPadding = a.getDimensionPixelSize(attr, -1);
4634                    mUserPaddingLeftInitial = leftPadding;
4635                    leftPaddingDefined = true;
4636                    break;
4637                case com.android.internal.R.styleable.View_paddingTop:
4638                    topPadding = a.getDimensionPixelSize(attr, -1);
4639                    break;
4640                case com.android.internal.R.styleable.View_paddingRight:
4641                    rightPadding = a.getDimensionPixelSize(attr, -1);
4642                    mUserPaddingRightInitial = rightPadding;
4643                    rightPaddingDefined = true;
4644                    break;
4645                case com.android.internal.R.styleable.View_paddingBottom:
4646                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4647                    break;
4648                case com.android.internal.R.styleable.View_paddingStart:
4649                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4650                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4651                    break;
4652                case com.android.internal.R.styleable.View_paddingEnd:
4653                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4654                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4655                    break;
4656                case com.android.internal.R.styleable.View_scrollX:
4657                    x = a.getDimensionPixelOffset(attr, 0);
4658                    break;
4659                case com.android.internal.R.styleable.View_scrollY:
4660                    y = a.getDimensionPixelOffset(attr, 0);
4661                    break;
4662                case com.android.internal.R.styleable.View_alpha:
4663                    setAlpha(a.getFloat(attr, 1f));
4664                    break;
4665                case com.android.internal.R.styleable.View_transformPivotX:
4666                    setPivotX(a.getDimension(attr, 0));
4667                    break;
4668                case com.android.internal.R.styleable.View_transformPivotY:
4669                    setPivotY(a.getDimension(attr, 0));
4670                    break;
4671                case com.android.internal.R.styleable.View_translationX:
4672                    tx = a.getDimension(attr, 0);
4673                    transformSet = true;
4674                    break;
4675                case com.android.internal.R.styleable.View_translationY:
4676                    ty = a.getDimension(attr, 0);
4677                    transformSet = true;
4678                    break;
4679                case com.android.internal.R.styleable.View_translationZ:
4680                    tz = a.getDimension(attr, 0);
4681                    transformSet = true;
4682                    break;
4683                case com.android.internal.R.styleable.View_elevation:
4684                    elevation = a.getDimension(attr, 0);
4685                    transformSet = true;
4686                    break;
4687                case com.android.internal.R.styleable.View_rotation:
4688                    rotation = a.getFloat(attr, 0);
4689                    transformSet = true;
4690                    break;
4691                case com.android.internal.R.styleable.View_rotationX:
4692                    rotationX = a.getFloat(attr, 0);
4693                    transformSet = true;
4694                    break;
4695                case com.android.internal.R.styleable.View_rotationY:
4696                    rotationY = a.getFloat(attr, 0);
4697                    transformSet = true;
4698                    break;
4699                case com.android.internal.R.styleable.View_scaleX:
4700                    sx = a.getFloat(attr, 1f);
4701                    transformSet = true;
4702                    break;
4703                case com.android.internal.R.styleable.View_scaleY:
4704                    sy = a.getFloat(attr, 1f);
4705                    transformSet = true;
4706                    break;
4707                case com.android.internal.R.styleable.View_id:
4708                    mID = a.getResourceId(attr, NO_ID);
4709                    break;
4710                case com.android.internal.R.styleable.View_tag:
4711                    mTag = a.getText(attr);
4712                    break;
4713                case com.android.internal.R.styleable.View_fitsSystemWindows:
4714                    if (a.getBoolean(attr, false)) {
4715                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4716                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4717                    }
4718                    break;
4719                case com.android.internal.R.styleable.View_focusable:
4720                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4721                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4722                        viewFlagMasks |= FOCUSABLE_MASK;
4723                    }
4724                    break;
4725                case com.android.internal.R.styleable.View_focusableInTouchMode:
4726                    if (a.getBoolean(attr, false)) {
4727                        // unset auto focus since focusableInTouchMode implies explicit focusable
4728                        viewFlagValues &= ~FOCUSABLE_AUTO;
4729                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4730                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4731                    }
4732                    break;
4733                case com.android.internal.R.styleable.View_clickable:
4734                    if (a.getBoolean(attr, false)) {
4735                        viewFlagValues |= CLICKABLE;
4736                        viewFlagMasks |= CLICKABLE;
4737                    }
4738                    break;
4739                case com.android.internal.R.styleable.View_longClickable:
4740                    if (a.getBoolean(attr, false)) {
4741                        viewFlagValues |= LONG_CLICKABLE;
4742                        viewFlagMasks |= LONG_CLICKABLE;
4743                    }
4744                    break;
4745                case com.android.internal.R.styleable.View_contextClickable:
4746                    if (a.getBoolean(attr, false)) {
4747                        viewFlagValues |= CONTEXT_CLICKABLE;
4748                        viewFlagMasks |= CONTEXT_CLICKABLE;
4749                    }
4750                    break;
4751                case com.android.internal.R.styleable.View_saveEnabled:
4752                    if (!a.getBoolean(attr, true)) {
4753                        viewFlagValues |= SAVE_DISABLED;
4754                        viewFlagMasks |= SAVE_DISABLED_MASK;
4755                    }
4756                    break;
4757                case com.android.internal.R.styleable.View_duplicateParentState:
4758                    if (a.getBoolean(attr, false)) {
4759                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4760                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4761                    }
4762                    break;
4763                case com.android.internal.R.styleable.View_visibility:
4764                    final int visibility = a.getInt(attr, 0);
4765                    if (visibility != 0) {
4766                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4767                        viewFlagMasks |= VISIBILITY_MASK;
4768                    }
4769                    break;
4770                case com.android.internal.R.styleable.View_layoutDirection:
4771                    // Clear any layout direction flags (included resolved bits) already set
4772                    mPrivateFlags2 &=
4773                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4774                    // Set the layout direction flags depending on the value of the attribute
4775                    final int layoutDirection = a.getInt(attr, -1);
4776                    final int value = (layoutDirection != -1) ?
4777                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4778                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4779                    break;
4780                case com.android.internal.R.styleable.View_drawingCacheQuality:
4781                    final int cacheQuality = a.getInt(attr, 0);
4782                    if (cacheQuality != 0) {
4783                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4784                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4785                    }
4786                    break;
4787                case com.android.internal.R.styleable.View_contentDescription:
4788                    setContentDescription(a.getString(attr));
4789                    break;
4790                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4791                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4792                    break;
4793                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4794                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4795                    break;
4796                case com.android.internal.R.styleable.View_labelFor:
4797                    setLabelFor(a.getResourceId(attr, NO_ID));
4798                    break;
4799                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4800                    if (!a.getBoolean(attr, true)) {
4801                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4802                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4803                    }
4804                    break;
4805                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4806                    if (!a.getBoolean(attr, true)) {
4807                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4808                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4809                    }
4810                    break;
4811                case R.styleable.View_scrollbars:
4812                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4813                    if (scrollbars != SCROLLBARS_NONE) {
4814                        viewFlagValues |= scrollbars;
4815                        viewFlagMasks |= SCROLLBARS_MASK;
4816                        initializeScrollbars = true;
4817                    }
4818                    break;
4819                //noinspection deprecation
4820                case R.styleable.View_fadingEdge:
4821                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4822                        // Ignore the attribute starting with ICS
4823                        break;
4824                    }
4825                    // With builds < ICS, fall through and apply fading edges
4826                case R.styleable.View_requiresFadingEdge:
4827                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4828                    if (fadingEdge != FADING_EDGE_NONE) {
4829                        viewFlagValues |= fadingEdge;
4830                        viewFlagMasks |= FADING_EDGE_MASK;
4831                        initializeFadingEdgeInternal(a);
4832                    }
4833                    break;
4834                case R.styleable.View_scrollbarStyle:
4835                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4836                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4837                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4838                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4839                    }
4840                    break;
4841                case R.styleable.View_isScrollContainer:
4842                    setScrollContainer = true;
4843                    if (a.getBoolean(attr, false)) {
4844                        setScrollContainer(true);
4845                    }
4846                    break;
4847                case com.android.internal.R.styleable.View_keepScreenOn:
4848                    if (a.getBoolean(attr, false)) {
4849                        viewFlagValues |= KEEP_SCREEN_ON;
4850                        viewFlagMasks |= KEEP_SCREEN_ON;
4851                    }
4852                    break;
4853                case R.styleable.View_filterTouchesWhenObscured:
4854                    if (a.getBoolean(attr, false)) {
4855                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4856                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4857                    }
4858                    break;
4859                case R.styleable.View_nextFocusLeft:
4860                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4861                    break;
4862                case R.styleable.View_nextFocusRight:
4863                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4864                    break;
4865                case R.styleable.View_nextFocusUp:
4866                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4867                    break;
4868                case R.styleable.View_nextFocusDown:
4869                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4870                    break;
4871                case R.styleable.View_nextFocusForward:
4872                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4873                    break;
4874                case R.styleable.View_nextClusterForward:
4875                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4876                    break;
4877                case R.styleable.View_minWidth:
4878                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4879                    break;
4880                case R.styleable.View_minHeight:
4881                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4882                    break;
4883                case R.styleable.View_onClick:
4884                    if (context.isRestricted()) {
4885                        throw new IllegalStateException("The android:onClick attribute cannot "
4886                                + "be used within a restricted context");
4887                    }
4888
4889                    final String handlerName = a.getString(attr);
4890                    if (handlerName != null) {
4891                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4892                    }
4893                    break;
4894                case R.styleable.View_overScrollMode:
4895                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4896                    break;
4897                case R.styleable.View_verticalScrollbarPosition:
4898                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4899                    break;
4900                case R.styleable.View_layerType:
4901                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4902                    break;
4903                case R.styleable.View_textDirection:
4904                    // Clear any text direction flag already set
4905                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4906                    // Set the text direction flags depending on the value of the attribute
4907                    final int textDirection = a.getInt(attr, -1);
4908                    if (textDirection != -1) {
4909                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4910                    }
4911                    break;
4912                case R.styleable.View_textAlignment:
4913                    // Clear any text alignment flag already set
4914                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4915                    // Set the text alignment flag depending on the value of the attribute
4916                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4917                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4918                    break;
4919                case R.styleable.View_importantForAccessibility:
4920                    setImportantForAccessibility(a.getInt(attr,
4921                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4922                    break;
4923                case R.styleable.View_accessibilityLiveRegion:
4924                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4925                    break;
4926                case R.styleable.View_transitionName:
4927                    setTransitionName(a.getString(attr));
4928                    break;
4929                case R.styleable.View_nestedScrollingEnabled:
4930                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4931                    break;
4932                case R.styleable.View_stateListAnimator:
4933                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4934                            a.getResourceId(attr, 0)));
4935                    break;
4936                case R.styleable.View_backgroundTint:
4937                    // This will get applied later during setBackground().
4938                    if (mBackgroundTint == null) {
4939                        mBackgroundTint = new TintInfo();
4940                    }
4941                    mBackgroundTint.mTintList = a.getColorStateList(
4942                            R.styleable.View_backgroundTint);
4943                    mBackgroundTint.mHasTintList = true;
4944                    break;
4945                case R.styleable.View_backgroundTintMode:
4946                    // This will get applied later during setBackground().
4947                    if (mBackgroundTint == null) {
4948                        mBackgroundTint = new TintInfo();
4949                    }
4950                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4951                            R.styleable.View_backgroundTintMode, -1), null);
4952                    mBackgroundTint.mHasTintMode = true;
4953                    break;
4954                case R.styleable.View_outlineProvider:
4955                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4956                            PROVIDER_BACKGROUND));
4957                    break;
4958                case R.styleable.View_foreground:
4959                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4960                        setForeground(a.getDrawable(attr));
4961                    }
4962                    break;
4963                case R.styleable.View_foregroundGravity:
4964                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4965                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4966                    }
4967                    break;
4968                case R.styleable.View_foregroundTintMode:
4969                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4970                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4971                    }
4972                    break;
4973                case R.styleable.View_foregroundTint:
4974                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4975                        setForegroundTintList(a.getColorStateList(attr));
4976                    }
4977                    break;
4978                case R.styleable.View_foregroundInsidePadding:
4979                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4980                        if (mForegroundInfo == null) {
4981                            mForegroundInfo = new ForegroundInfo();
4982                        }
4983                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4984                                mForegroundInfo.mInsidePadding);
4985                    }
4986                    break;
4987                case R.styleable.View_scrollIndicators:
4988                    final int scrollIndicators =
4989                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4990                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4991                    if (scrollIndicators != 0) {
4992                        mPrivateFlags3 |= scrollIndicators;
4993                        initializeScrollIndicators = true;
4994                    }
4995                    break;
4996                case R.styleable.View_pointerIcon:
4997                    final int resourceId = a.getResourceId(attr, 0);
4998                    if (resourceId != 0) {
4999                        setPointerIcon(PointerIcon.load(
5000                                context.getResources(), resourceId));
5001                    } else {
5002                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5003                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5004                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5005                        }
5006                    }
5007                    break;
5008                case R.styleable.View_forceHasOverlappingRendering:
5009                    if (a.peekValue(attr) != null) {
5010                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5011                    }
5012                    break;
5013                case R.styleable.View_tooltipText:
5014                    setTooltipText(a.getText(attr));
5015                    break;
5016                case R.styleable.View_keyboardNavigationCluster:
5017                    if (a.peekValue(attr) != null) {
5018                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5019                    }
5020                    break;
5021                case R.styleable.View_focusedByDefault:
5022                    if (a.peekValue(attr) != null) {
5023                        setFocusedByDefault(a.getBoolean(attr, true));
5024                    }
5025                    break;
5026                case R.styleable.View_autofillMode:
5027                    if (a.peekValue(attr) != null) {
5028                        setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
5029                    }
5030                    break;
5031                case R.styleable.View_autofillHint:
5032                    if (a.peekValue(attr) != null) {
5033                        CharSequence[] rawHints = null;
5034                        String rawString = null;
5035
5036                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5037                            int resId = a.getResourceId(attr, 0);
5038
5039                            try {
5040                                rawHints = a.getTextArray(attr);
5041                            } catch (NullPointerException e) {
5042                                rawString = getResources().getString(resId);
5043                            }
5044                        } else {
5045                            rawString = a.getString(attr);
5046                        }
5047
5048                        if (rawHints == null) {
5049                            if (rawString == null) {
5050                                throw new IllegalArgumentException(
5051                                        "Could not resolve autofillHint");
5052                            } else {
5053                                rawHints = rawString.split(",");
5054                            }
5055                        }
5056
5057                        String[] hints = new String[rawHints.length];
5058
5059                        int numHints = rawHints.length;
5060                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5061                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5062                        }
5063                        setAutofillHint(hints);
5064                    }
5065                    break;
5066                case R.styleable.View_importantForAutofill:
5067                    if (a.peekValue(attr) != null) {
5068                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5069                    }
5070                    break;
5071            }
5072        }
5073
5074        setOverScrollMode(overScrollMode);
5075
5076        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5077        // the resolved layout direction). Those cached values will be used later during padding
5078        // resolution.
5079        mUserPaddingStart = startPadding;
5080        mUserPaddingEnd = endPadding;
5081
5082        if (background != null) {
5083            setBackground(background);
5084        }
5085
5086        // setBackground above will record that padding is currently provided by the background.
5087        // If we have padding specified via xml, record that here instead and use it.
5088        mLeftPaddingDefined = leftPaddingDefined;
5089        mRightPaddingDefined = rightPaddingDefined;
5090
5091        if (padding >= 0) {
5092            leftPadding = padding;
5093            topPadding = padding;
5094            rightPadding = padding;
5095            bottomPadding = padding;
5096            mUserPaddingLeftInitial = padding;
5097            mUserPaddingRightInitial = padding;
5098        } else {
5099            if (paddingHorizontal >= 0) {
5100                leftPadding = paddingHorizontal;
5101                rightPadding = paddingHorizontal;
5102                mUserPaddingLeftInitial = paddingHorizontal;
5103                mUserPaddingRightInitial = paddingHorizontal;
5104            }
5105            if (paddingVertical >= 0) {
5106                topPadding = paddingVertical;
5107                bottomPadding = paddingVertical;
5108            }
5109        }
5110
5111        if (isRtlCompatibilityMode()) {
5112            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5113            // left / right padding are used if defined (meaning here nothing to do). If they are not
5114            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5115            // start / end and resolve them as left / right (layout direction is not taken into account).
5116            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5117            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5118            // defined.
5119            if (!mLeftPaddingDefined && startPaddingDefined) {
5120                leftPadding = startPadding;
5121            }
5122            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5123            if (!mRightPaddingDefined && endPaddingDefined) {
5124                rightPadding = endPadding;
5125            }
5126            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5127        } else {
5128            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5129            // values defined. Otherwise, left /right values are used.
5130            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5131            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5132            // defined.
5133            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5134
5135            if (mLeftPaddingDefined && !hasRelativePadding) {
5136                mUserPaddingLeftInitial = leftPadding;
5137            }
5138            if (mRightPaddingDefined && !hasRelativePadding) {
5139                mUserPaddingRightInitial = rightPadding;
5140            }
5141        }
5142
5143        internalSetPadding(
5144                mUserPaddingLeftInitial,
5145                topPadding >= 0 ? topPadding : mPaddingTop,
5146                mUserPaddingRightInitial,
5147                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5148
5149        if (viewFlagMasks != 0) {
5150            setFlags(viewFlagValues, viewFlagMasks);
5151        }
5152
5153        if (initializeScrollbars) {
5154            initializeScrollbarsInternal(a);
5155        }
5156
5157        if (initializeScrollIndicators) {
5158            initializeScrollIndicatorsInternal();
5159        }
5160
5161        a.recycle();
5162
5163        // Needs to be called after mViewFlags is set
5164        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5165            recomputePadding();
5166        }
5167
5168        if (x != 0 || y != 0) {
5169            scrollTo(x, y);
5170        }
5171
5172        if (transformSet) {
5173            setTranslationX(tx);
5174            setTranslationY(ty);
5175            setTranslationZ(tz);
5176            setElevation(elevation);
5177            setRotation(rotation);
5178            setRotationX(rotationX);
5179            setRotationY(rotationY);
5180            setScaleX(sx);
5181            setScaleY(sy);
5182        }
5183
5184        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5185            setScrollContainer(true);
5186        }
5187
5188        computeOpaqueFlags();
5189    }
5190
5191    /**
5192     * An implementation of OnClickListener that attempts to lazily load a
5193     * named click handling method from a parent or ancestor context.
5194     */
5195    private static class DeclaredOnClickListener implements OnClickListener {
5196        private final View mHostView;
5197        private final String mMethodName;
5198
5199        private Method mResolvedMethod;
5200        private Context mResolvedContext;
5201
5202        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5203            mHostView = hostView;
5204            mMethodName = methodName;
5205        }
5206
5207        @Override
5208        public void onClick(@NonNull View v) {
5209            if (mResolvedMethod == null) {
5210                resolveMethod(mHostView.getContext(), mMethodName);
5211            }
5212
5213            try {
5214                mResolvedMethod.invoke(mResolvedContext, v);
5215            } catch (IllegalAccessException e) {
5216                throw new IllegalStateException(
5217                        "Could not execute non-public method for android:onClick", e);
5218            } catch (InvocationTargetException e) {
5219                throw new IllegalStateException(
5220                        "Could not execute method for android:onClick", e);
5221            }
5222        }
5223
5224        @NonNull
5225        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5226            while (context != null) {
5227                try {
5228                    if (!context.isRestricted()) {
5229                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5230                        if (method != null) {
5231                            mResolvedMethod = method;
5232                            mResolvedContext = context;
5233                            return;
5234                        }
5235                    }
5236                } catch (NoSuchMethodException e) {
5237                    // Failed to find method, keep searching up the hierarchy.
5238                }
5239
5240                if (context instanceof ContextWrapper) {
5241                    context = ((ContextWrapper) context).getBaseContext();
5242                } else {
5243                    // Can't search up the hierarchy, null out and fail.
5244                    context = null;
5245                }
5246            }
5247
5248            final int id = mHostView.getId();
5249            final String idText = id == NO_ID ? "" : " with id '"
5250                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5251            throw new IllegalStateException("Could not find method " + mMethodName
5252                    + "(View) in a parent or ancestor Context for android:onClick "
5253                    + "attribute defined on view " + mHostView.getClass() + idText);
5254        }
5255    }
5256
5257    /**
5258     * Non-public constructor for use in testing
5259     */
5260    View() {
5261        mResources = null;
5262        mRenderNode = RenderNode.create(getClass().getName(), this);
5263    }
5264
5265    final boolean debugDraw() {
5266        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5267    }
5268
5269    private static SparseArray<String> getAttributeMap() {
5270        if (mAttributeMap == null) {
5271            mAttributeMap = new SparseArray<>();
5272        }
5273        return mAttributeMap;
5274    }
5275
5276    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5277        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5278        final int indexCount = t.getIndexCount();
5279        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5280
5281        int i = 0;
5282
5283        // Store raw XML attributes.
5284        for (int j = 0; j < attrsCount; ++j) {
5285            attributes[i] = attrs.getAttributeName(j);
5286            attributes[i + 1] = attrs.getAttributeValue(j);
5287            i += 2;
5288        }
5289
5290        // Store resolved styleable attributes.
5291        final Resources res = t.getResources();
5292        final SparseArray<String> attributeMap = getAttributeMap();
5293        for (int j = 0; j < indexCount; ++j) {
5294            final int index = t.getIndex(j);
5295            if (!t.hasValueOrEmpty(index)) {
5296                // Value is undefined. Skip it.
5297                continue;
5298            }
5299
5300            final int resourceId = t.getResourceId(index, 0);
5301            if (resourceId == 0) {
5302                // Value is not a reference. Skip it.
5303                continue;
5304            }
5305
5306            String resourceName = attributeMap.get(resourceId);
5307            if (resourceName == null) {
5308                try {
5309                    resourceName = res.getResourceName(resourceId);
5310                } catch (Resources.NotFoundException e) {
5311                    resourceName = "0x" + Integer.toHexString(resourceId);
5312                }
5313                attributeMap.put(resourceId, resourceName);
5314            }
5315
5316            attributes[i] = resourceName;
5317            attributes[i + 1] = t.getString(index);
5318            i += 2;
5319        }
5320
5321        // Trim to fit contents.
5322        final String[] trimmed = new String[i];
5323        System.arraycopy(attributes, 0, trimmed, 0, i);
5324        mAttributes = trimmed;
5325    }
5326
5327    public String toString() {
5328        StringBuilder out = new StringBuilder(128);
5329        out.append(getClass().getName());
5330        out.append('{');
5331        out.append(Integer.toHexString(System.identityHashCode(this)));
5332        out.append(' ');
5333        switch (mViewFlags&VISIBILITY_MASK) {
5334            case VISIBLE: out.append('V'); break;
5335            case INVISIBLE: out.append('I'); break;
5336            case GONE: out.append('G'); break;
5337            default: out.append('.'); break;
5338        }
5339        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5340        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5341        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5342        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5343        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5344        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5345        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5346        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5347        out.append(' ');
5348        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5349        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5350        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5351        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5352            out.append('p');
5353        } else {
5354            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5355        }
5356        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5357        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5358        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5359        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5360        out.append(' ');
5361        out.append(mLeft);
5362        out.append(',');
5363        out.append(mTop);
5364        out.append('-');
5365        out.append(mRight);
5366        out.append(',');
5367        out.append(mBottom);
5368        final int id = getId();
5369        if (id != NO_ID) {
5370            out.append(" #");
5371            out.append(Integer.toHexString(id));
5372            final Resources r = mResources;
5373            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5374                try {
5375                    String pkgname;
5376                    switch (id&0xff000000) {
5377                        case 0x7f000000:
5378                            pkgname="app";
5379                            break;
5380                        case 0x01000000:
5381                            pkgname="android";
5382                            break;
5383                        default:
5384                            pkgname = r.getResourcePackageName(id);
5385                            break;
5386                    }
5387                    String typename = r.getResourceTypeName(id);
5388                    String entryname = r.getResourceEntryName(id);
5389                    out.append(" ");
5390                    out.append(pkgname);
5391                    out.append(":");
5392                    out.append(typename);
5393                    out.append("/");
5394                    out.append(entryname);
5395                } catch (Resources.NotFoundException e) {
5396                }
5397            }
5398        }
5399        out.append("}");
5400        return out.toString();
5401    }
5402
5403    /**
5404     * <p>
5405     * Initializes the fading edges from a given set of styled attributes. This
5406     * method should be called by subclasses that need fading edges and when an
5407     * instance of these subclasses is created programmatically rather than
5408     * being inflated from XML. This method is automatically called when the XML
5409     * is inflated.
5410     * </p>
5411     *
5412     * @param a the styled attributes set to initialize the fading edges from
5413     *
5414     * @removed
5415     */
5416    protected void initializeFadingEdge(TypedArray a) {
5417        // This method probably shouldn't have been included in the SDK to begin with.
5418        // It relies on 'a' having been initialized using an attribute filter array that is
5419        // not publicly available to the SDK. The old method has been renamed
5420        // to initializeFadingEdgeInternal and hidden for framework use only;
5421        // this one initializes using defaults to make it safe to call for apps.
5422
5423        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5424
5425        initializeFadingEdgeInternal(arr);
5426
5427        arr.recycle();
5428    }
5429
5430    /**
5431     * <p>
5432     * Initializes the fading edges from a given set of styled attributes. This
5433     * method should be called by subclasses that need fading edges and when an
5434     * instance of these subclasses is created programmatically rather than
5435     * being inflated from XML. This method is automatically called when the XML
5436     * is inflated.
5437     * </p>
5438     *
5439     * @param a the styled attributes set to initialize the fading edges from
5440     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5441     */
5442    protected void initializeFadingEdgeInternal(TypedArray a) {
5443        initScrollCache();
5444
5445        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5446                R.styleable.View_fadingEdgeLength,
5447                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5448    }
5449
5450    /**
5451     * Returns the size of the vertical faded edges used to indicate that more
5452     * content in this view is visible.
5453     *
5454     * @return The size in pixels of the vertical faded edge or 0 if vertical
5455     *         faded edges are not enabled for this view.
5456     * @attr ref android.R.styleable#View_fadingEdgeLength
5457     */
5458    public int getVerticalFadingEdgeLength() {
5459        if (isVerticalFadingEdgeEnabled()) {
5460            ScrollabilityCache cache = mScrollCache;
5461            if (cache != null) {
5462                return cache.fadingEdgeLength;
5463            }
5464        }
5465        return 0;
5466    }
5467
5468    /**
5469     * Set the size of the faded edge used to indicate that more content in this
5470     * view is available.  Will not change whether the fading edge is enabled; use
5471     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5472     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5473     * for the vertical or horizontal fading edges.
5474     *
5475     * @param length The size in pixels of the faded edge used to indicate that more
5476     *        content in this view is visible.
5477     */
5478    public void setFadingEdgeLength(int length) {
5479        initScrollCache();
5480        mScrollCache.fadingEdgeLength = length;
5481    }
5482
5483    /**
5484     * Returns the size of the horizontal faded edges used to indicate that more
5485     * content in this view is visible.
5486     *
5487     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5488     *         faded edges are not enabled for this view.
5489     * @attr ref android.R.styleable#View_fadingEdgeLength
5490     */
5491    public int getHorizontalFadingEdgeLength() {
5492        if (isHorizontalFadingEdgeEnabled()) {
5493            ScrollabilityCache cache = mScrollCache;
5494            if (cache != null) {
5495                return cache.fadingEdgeLength;
5496            }
5497        }
5498        return 0;
5499    }
5500
5501    /**
5502     * Returns the width of the vertical scrollbar.
5503     *
5504     * @return The width in pixels of the vertical scrollbar or 0 if there
5505     *         is no vertical scrollbar.
5506     */
5507    public int getVerticalScrollbarWidth() {
5508        ScrollabilityCache cache = mScrollCache;
5509        if (cache != null) {
5510            ScrollBarDrawable scrollBar = cache.scrollBar;
5511            if (scrollBar != null) {
5512                int size = scrollBar.getSize(true);
5513                if (size <= 0) {
5514                    size = cache.scrollBarSize;
5515                }
5516                return size;
5517            }
5518            return 0;
5519        }
5520        return 0;
5521    }
5522
5523    /**
5524     * Returns the height of the horizontal scrollbar.
5525     *
5526     * @return The height in pixels of the horizontal scrollbar or 0 if
5527     *         there is no horizontal scrollbar.
5528     */
5529    protected int getHorizontalScrollbarHeight() {
5530        ScrollabilityCache cache = mScrollCache;
5531        if (cache != null) {
5532            ScrollBarDrawable scrollBar = cache.scrollBar;
5533            if (scrollBar != null) {
5534                int size = scrollBar.getSize(false);
5535                if (size <= 0) {
5536                    size = cache.scrollBarSize;
5537                }
5538                return size;
5539            }
5540            return 0;
5541        }
5542        return 0;
5543    }
5544
5545    /**
5546     * <p>
5547     * Initializes the scrollbars from a given set of styled attributes. This
5548     * method should be called by subclasses that need scrollbars and when an
5549     * instance of these subclasses is created programmatically rather than
5550     * being inflated from XML. This method is automatically called when the XML
5551     * is inflated.
5552     * </p>
5553     *
5554     * @param a the styled attributes set to initialize the scrollbars from
5555     *
5556     * @removed
5557     */
5558    protected void initializeScrollbars(TypedArray a) {
5559        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5560        // using the View filter array which is not available to the SDK. As such, internal
5561        // framework usage now uses initializeScrollbarsInternal and we grab a default
5562        // TypedArray with the right filter instead here.
5563        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5564
5565        initializeScrollbarsInternal(arr);
5566
5567        // We ignored the method parameter. Recycle the one we actually did use.
5568        arr.recycle();
5569    }
5570
5571    /**
5572     * <p>
5573     * Initializes the scrollbars from a given set of styled attributes. This
5574     * method should be called by subclasses that need scrollbars and when an
5575     * instance of these subclasses is created programmatically rather than
5576     * being inflated from XML. This method is automatically called when the XML
5577     * is inflated.
5578     * </p>
5579     *
5580     * @param a the styled attributes set to initialize the scrollbars from
5581     * @hide
5582     */
5583    protected void initializeScrollbarsInternal(TypedArray a) {
5584        initScrollCache();
5585
5586        final ScrollabilityCache scrollabilityCache = mScrollCache;
5587
5588        if (scrollabilityCache.scrollBar == null) {
5589            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5590            scrollabilityCache.scrollBar.setState(getDrawableState());
5591            scrollabilityCache.scrollBar.setCallback(this);
5592        }
5593
5594        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5595
5596        if (!fadeScrollbars) {
5597            scrollabilityCache.state = ScrollabilityCache.ON;
5598        }
5599        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5600
5601
5602        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5603                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5604                        .getScrollBarFadeDuration());
5605        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5606                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5607                ViewConfiguration.getScrollDefaultDelay());
5608
5609
5610        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5611                com.android.internal.R.styleable.View_scrollbarSize,
5612                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5613
5614        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5615        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5616
5617        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5618        if (thumb != null) {
5619            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5620        }
5621
5622        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5623                false);
5624        if (alwaysDraw) {
5625            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5626        }
5627
5628        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5629        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5630
5631        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5632        if (thumb != null) {
5633            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5634        }
5635
5636        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5637                false);
5638        if (alwaysDraw) {
5639            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5640        }
5641
5642        // Apply layout direction to the new Drawables if needed
5643        final int layoutDirection = getLayoutDirection();
5644        if (track != null) {
5645            track.setLayoutDirection(layoutDirection);
5646        }
5647        if (thumb != null) {
5648            thumb.setLayoutDirection(layoutDirection);
5649        }
5650
5651        // Re-apply user/background padding so that scrollbar(s) get added
5652        resolvePadding();
5653    }
5654
5655    private void initializeScrollIndicatorsInternal() {
5656        // Some day maybe we'll break this into top/left/start/etc. and let the
5657        // client control it. Until then, you can have any scroll indicator you
5658        // want as long as it's a 1dp foreground-colored rectangle.
5659        if (mScrollIndicatorDrawable == null) {
5660            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5661        }
5662    }
5663
5664    /**
5665     * <p>
5666     * Initalizes the scrollability cache if necessary.
5667     * </p>
5668     */
5669    private void initScrollCache() {
5670        if (mScrollCache == null) {
5671            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5672        }
5673    }
5674
5675    private ScrollabilityCache getScrollCache() {
5676        initScrollCache();
5677        return mScrollCache;
5678    }
5679
5680    /**
5681     * Set the position of the vertical scroll bar. Should be one of
5682     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5683     * {@link #SCROLLBAR_POSITION_RIGHT}.
5684     *
5685     * @param position Where the vertical scroll bar should be positioned.
5686     */
5687    public void setVerticalScrollbarPosition(int position) {
5688        if (mVerticalScrollbarPosition != position) {
5689            mVerticalScrollbarPosition = position;
5690            computeOpaqueFlags();
5691            resolvePadding();
5692        }
5693    }
5694
5695    /**
5696     * @return The position where the vertical scroll bar will show, if applicable.
5697     * @see #setVerticalScrollbarPosition(int)
5698     */
5699    public int getVerticalScrollbarPosition() {
5700        return mVerticalScrollbarPosition;
5701    }
5702
5703    boolean isOnScrollbar(float x, float y) {
5704        if (mScrollCache == null) {
5705            return false;
5706        }
5707        x += getScrollX();
5708        y += getScrollY();
5709        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5710            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5711            getVerticalScrollBarBounds(null, touchBounds);
5712            if (touchBounds.contains((int) x, (int) y)) {
5713                return true;
5714            }
5715        }
5716        if (isHorizontalScrollBarEnabled()) {
5717            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5718            getHorizontalScrollBarBounds(null, touchBounds);
5719            if (touchBounds.contains((int) x, (int) y)) {
5720                return true;
5721            }
5722        }
5723        return false;
5724    }
5725
5726    boolean isOnScrollbarThumb(float x, float y) {
5727        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5728    }
5729
5730    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5731        if (mScrollCache == null) {
5732            return false;
5733        }
5734        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5735            x += getScrollX();
5736            y += getScrollY();
5737            final Rect bounds = mScrollCache.mScrollBarBounds;
5738            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5739            getVerticalScrollBarBounds(bounds, touchBounds);
5740            final int range = computeVerticalScrollRange();
5741            final int offset = computeVerticalScrollOffset();
5742            final int extent = computeVerticalScrollExtent();
5743            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5744                    extent, range);
5745            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5746                    extent, range, offset);
5747            final int thumbTop = bounds.top + thumbOffset;
5748            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5749            if (x >= touchBounds.left && x <= touchBounds.right
5750                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5751                return true;
5752            }
5753        }
5754        return false;
5755    }
5756
5757    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5758        if (mScrollCache == null) {
5759            return false;
5760        }
5761        if (isHorizontalScrollBarEnabled()) {
5762            x += getScrollX();
5763            y += getScrollY();
5764            final Rect bounds = mScrollCache.mScrollBarBounds;
5765            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5766            getHorizontalScrollBarBounds(bounds, touchBounds);
5767            final int range = computeHorizontalScrollRange();
5768            final int offset = computeHorizontalScrollOffset();
5769            final int extent = computeHorizontalScrollExtent();
5770            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5771                    extent, range);
5772            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5773                    extent, range, offset);
5774            final int thumbLeft = bounds.left + thumbOffset;
5775            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5776            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5777                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5778                return true;
5779            }
5780        }
5781        return false;
5782    }
5783
5784    boolean isDraggingScrollBar() {
5785        return mScrollCache != null
5786                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5787    }
5788
5789    /**
5790     * Sets the state of all scroll indicators.
5791     * <p>
5792     * See {@link #setScrollIndicators(int, int)} for usage information.
5793     *
5794     * @param indicators a bitmask of indicators that should be enabled, or
5795     *                   {@code 0} to disable all indicators
5796     * @see #setScrollIndicators(int, int)
5797     * @see #getScrollIndicators()
5798     * @attr ref android.R.styleable#View_scrollIndicators
5799     */
5800    public void setScrollIndicators(@ScrollIndicators int indicators) {
5801        setScrollIndicators(indicators,
5802                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5803    }
5804
5805    /**
5806     * Sets the state of the scroll indicators specified by the mask. To change
5807     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5808     * <p>
5809     * When a scroll indicator is enabled, it will be displayed if the view
5810     * can scroll in the direction of the indicator.
5811     * <p>
5812     * Multiple indicator types may be enabled or disabled by passing the
5813     * logical OR of the desired types. If multiple types are specified, they
5814     * will all be set to the same enabled state.
5815     * <p>
5816     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5817     *
5818     * @param indicators the indicator direction, or the logical OR of multiple
5819     *             indicator directions. One or more of:
5820     *             <ul>
5821     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5822     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5823     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5824     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5825     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5826     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5827     *             </ul>
5828     * @see #setScrollIndicators(int)
5829     * @see #getScrollIndicators()
5830     * @attr ref android.R.styleable#View_scrollIndicators
5831     */
5832    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5833        // Shift and sanitize mask.
5834        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5835        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5836
5837        // Shift and mask indicators.
5838        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5839        indicators &= mask;
5840
5841        // Merge with non-masked flags.
5842        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5843
5844        if (mPrivateFlags3 != updatedFlags) {
5845            mPrivateFlags3 = updatedFlags;
5846
5847            if (indicators != 0) {
5848                initializeScrollIndicatorsInternal();
5849            }
5850            invalidate();
5851        }
5852    }
5853
5854    /**
5855     * Returns a bitmask representing the enabled scroll indicators.
5856     * <p>
5857     * For example, if the top and left scroll indicators are enabled and all
5858     * other indicators are disabled, the return value will be
5859     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5860     * <p>
5861     * To check whether the bottom scroll indicator is enabled, use the value
5862     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5863     *
5864     * @return a bitmask representing the enabled scroll indicators
5865     */
5866    @ScrollIndicators
5867    public int getScrollIndicators() {
5868        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5869                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5870    }
5871
5872    ListenerInfo getListenerInfo() {
5873        if (mListenerInfo != null) {
5874            return mListenerInfo;
5875        }
5876        mListenerInfo = new ListenerInfo();
5877        return mListenerInfo;
5878    }
5879
5880    /**
5881     * Register a callback to be invoked when the scroll X or Y positions of
5882     * this view change.
5883     * <p>
5884     * <b>Note:</b> Some views handle scrolling independently from View and may
5885     * have their own separate listeners for scroll-type events. For example,
5886     * {@link android.widget.ListView ListView} allows clients to register an
5887     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5888     * to listen for changes in list scroll position.
5889     *
5890     * @param l The listener to notify when the scroll X or Y position changes.
5891     * @see android.view.View#getScrollX()
5892     * @see android.view.View#getScrollY()
5893     */
5894    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5895        getListenerInfo().mOnScrollChangeListener = l;
5896    }
5897
5898    /**
5899     * Register a callback to be invoked when focus of this view changed.
5900     *
5901     * @param l The callback that will run.
5902     */
5903    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5904        getListenerInfo().mOnFocusChangeListener = l;
5905    }
5906
5907    /**
5908     * Add a listener that will be called when the bounds of the view change due to
5909     * layout processing.
5910     *
5911     * @param listener The listener that will be called when layout bounds change.
5912     */
5913    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5914        ListenerInfo li = getListenerInfo();
5915        if (li.mOnLayoutChangeListeners == null) {
5916            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5917        }
5918        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5919            li.mOnLayoutChangeListeners.add(listener);
5920        }
5921    }
5922
5923    /**
5924     * Remove a listener for layout changes.
5925     *
5926     * @param listener The listener for layout bounds change.
5927     */
5928    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5929        ListenerInfo li = mListenerInfo;
5930        if (li == null || li.mOnLayoutChangeListeners == null) {
5931            return;
5932        }
5933        li.mOnLayoutChangeListeners.remove(listener);
5934    }
5935
5936    /**
5937     * Add a listener for attach state changes.
5938     *
5939     * This listener will be called whenever this view is attached or detached
5940     * from a window. Remove the listener using
5941     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5942     *
5943     * @param listener Listener to attach
5944     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5945     */
5946    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5947        ListenerInfo li = getListenerInfo();
5948        if (li.mOnAttachStateChangeListeners == null) {
5949            li.mOnAttachStateChangeListeners
5950                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5951        }
5952        li.mOnAttachStateChangeListeners.add(listener);
5953    }
5954
5955    /**
5956     * Remove a listener for attach state changes. The listener will receive no further
5957     * notification of window attach/detach events.
5958     *
5959     * @param listener Listener to remove
5960     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5961     */
5962    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5963        ListenerInfo li = mListenerInfo;
5964        if (li == null || li.mOnAttachStateChangeListeners == null) {
5965            return;
5966        }
5967        li.mOnAttachStateChangeListeners.remove(listener);
5968    }
5969
5970    /**
5971     * Returns the focus-change callback registered for this view.
5972     *
5973     * @return The callback, or null if one is not registered.
5974     */
5975    public OnFocusChangeListener getOnFocusChangeListener() {
5976        ListenerInfo li = mListenerInfo;
5977        return li != null ? li.mOnFocusChangeListener : null;
5978    }
5979
5980    /**
5981     * Register a callback to be invoked when this view is clicked. If this view is not
5982     * clickable, it becomes clickable.
5983     *
5984     * @param l The callback that will run
5985     *
5986     * @see #setClickable(boolean)
5987     */
5988    public void setOnClickListener(@Nullable OnClickListener l) {
5989        if (!isClickable()) {
5990            setClickable(true);
5991        }
5992        getListenerInfo().mOnClickListener = l;
5993    }
5994
5995    /**
5996     * Return whether this view has an attached OnClickListener.  Returns
5997     * true if there is a listener, false if there is none.
5998     */
5999    public boolean hasOnClickListeners() {
6000        ListenerInfo li = mListenerInfo;
6001        return (li != null && li.mOnClickListener != null);
6002    }
6003
6004    /**
6005     * Register a callback to be invoked when this view is clicked and held. If this view is not
6006     * long clickable, it becomes long clickable.
6007     *
6008     * @param l The callback that will run
6009     *
6010     * @see #setLongClickable(boolean)
6011     */
6012    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6013        if (!isLongClickable()) {
6014            setLongClickable(true);
6015        }
6016        getListenerInfo().mOnLongClickListener = l;
6017    }
6018
6019    /**
6020     * Register a callback to be invoked when this view is context clicked. If the view is not
6021     * context clickable, it becomes context clickable.
6022     *
6023     * @param l The callback that will run
6024     * @see #setContextClickable(boolean)
6025     */
6026    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6027        if (!isContextClickable()) {
6028            setContextClickable(true);
6029        }
6030        getListenerInfo().mOnContextClickListener = l;
6031    }
6032
6033    /**
6034     * Register a callback to be invoked when the context menu for this view is
6035     * being built. If this view is not long clickable, it becomes long clickable.
6036     *
6037     * @param l The callback that will run
6038     *
6039     */
6040    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6041        if (!isLongClickable()) {
6042            setLongClickable(true);
6043        }
6044        getListenerInfo().mOnCreateContextMenuListener = l;
6045    }
6046
6047    /**
6048     * Set an observer to collect stats for each frame rendered for this view.
6049     *
6050     * @hide
6051     */
6052    public void addFrameMetricsListener(Window window,
6053            Window.OnFrameMetricsAvailableListener listener,
6054            Handler handler) {
6055        if (mAttachInfo != null) {
6056            if (mAttachInfo.mThreadedRenderer != null) {
6057                if (mFrameMetricsObservers == null) {
6058                    mFrameMetricsObservers = new ArrayList<>();
6059                }
6060
6061                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6062                        handler.getLooper(), listener);
6063                mFrameMetricsObservers.add(fmo);
6064                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6065            } else {
6066                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6067            }
6068        } else {
6069            if (mFrameMetricsObservers == null) {
6070                mFrameMetricsObservers = new ArrayList<>();
6071            }
6072
6073            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6074                    handler.getLooper(), listener);
6075            mFrameMetricsObservers.add(fmo);
6076        }
6077    }
6078
6079    /**
6080     * Remove observer configured to collect frame stats for this view.
6081     *
6082     * @hide
6083     */
6084    public void removeFrameMetricsListener(
6085            Window.OnFrameMetricsAvailableListener listener) {
6086        ThreadedRenderer renderer = getThreadedRenderer();
6087        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6088        if (fmo == null) {
6089            throw new IllegalArgumentException(
6090                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6091        }
6092
6093        if (mFrameMetricsObservers != null) {
6094            mFrameMetricsObservers.remove(fmo);
6095            if (renderer != null) {
6096                renderer.removeFrameMetricsObserver(fmo);
6097            }
6098        }
6099    }
6100
6101    private void registerPendingFrameMetricsObservers() {
6102        if (mFrameMetricsObservers != null) {
6103            ThreadedRenderer renderer = getThreadedRenderer();
6104            if (renderer != null) {
6105                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6106                    renderer.addFrameMetricsObserver(fmo);
6107                }
6108            } else {
6109                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6110            }
6111        }
6112    }
6113
6114    private FrameMetricsObserver findFrameMetricsObserver(
6115            Window.OnFrameMetricsAvailableListener listener) {
6116        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6117            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6118            if (observer.mListener == listener) {
6119                return observer;
6120            }
6121        }
6122
6123        return null;
6124    }
6125
6126    /**
6127     * Call this view's OnClickListener, if it is defined.  Performs all normal
6128     * actions associated with clicking: reporting accessibility event, playing
6129     * a sound, etc.
6130     *
6131     * @return True there was an assigned OnClickListener that was called, false
6132     *         otherwise is returned.
6133     */
6134    public boolean performClick() {
6135        final boolean result;
6136        final ListenerInfo li = mListenerInfo;
6137        if (li != null && li.mOnClickListener != null) {
6138            playSoundEffect(SoundEffectConstants.CLICK);
6139            li.mOnClickListener.onClick(this);
6140            result = true;
6141        } else {
6142            result = false;
6143        }
6144
6145        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6146
6147        notifyEnterOrExitForAutoFillIfNeeded(true);
6148
6149        return result;
6150    }
6151
6152    /**
6153     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6154     * this only calls the listener, and does not do any associated clicking
6155     * actions like reporting an accessibility event.
6156     *
6157     * @return True there was an assigned OnClickListener that was called, false
6158     *         otherwise is returned.
6159     */
6160    public boolean callOnClick() {
6161        ListenerInfo li = mListenerInfo;
6162        if (li != null && li.mOnClickListener != null) {
6163            li.mOnClickListener.onClick(this);
6164            return true;
6165        }
6166        return false;
6167    }
6168
6169    /**
6170     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6171     * context menu if the OnLongClickListener did not consume the event.
6172     *
6173     * @return {@code true} if one of the above receivers consumed the event,
6174     *         {@code false} otherwise
6175     */
6176    public boolean performLongClick() {
6177        return performLongClickInternal(mLongClickX, mLongClickY);
6178    }
6179
6180    /**
6181     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6182     * context menu if the OnLongClickListener did not consume the event,
6183     * anchoring it to an (x,y) coordinate.
6184     *
6185     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6186     *          to disable anchoring
6187     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6188     *          to disable anchoring
6189     * @return {@code true} if one of the above receivers consumed the event,
6190     *         {@code false} otherwise
6191     */
6192    public boolean performLongClick(float x, float y) {
6193        mLongClickX = x;
6194        mLongClickY = y;
6195        final boolean handled = performLongClick();
6196        mLongClickX = Float.NaN;
6197        mLongClickY = Float.NaN;
6198        return handled;
6199    }
6200
6201    /**
6202     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6203     * context menu if the OnLongClickListener did not consume the event,
6204     * optionally anchoring it to an (x,y) coordinate.
6205     *
6206     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6207     *          to disable anchoring
6208     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6209     *          to disable anchoring
6210     * @return {@code true} if one of the above receivers consumed the event,
6211     *         {@code false} otherwise
6212     */
6213    private boolean performLongClickInternal(float x, float y) {
6214        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6215
6216        boolean handled = false;
6217        final ListenerInfo li = mListenerInfo;
6218        if (li != null && li.mOnLongClickListener != null) {
6219            handled = li.mOnLongClickListener.onLongClick(View.this);
6220        }
6221        if (!handled) {
6222            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6223            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6224        }
6225        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6226            if (!handled) {
6227                handled = showLongClickTooltip((int) x, (int) y);
6228            }
6229        }
6230        if (handled) {
6231            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6232        }
6233        return handled;
6234    }
6235
6236    /**
6237     * Call this view's OnContextClickListener, if it is defined.
6238     *
6239     * @param x the x coordinate of the context click
6240     * @param y the y coordinate of the context click
6241     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6242     *         otherwise.
6243     */
6244    public boolean performContextClick(float x, float y) {
6245        return performContextClick();
6246    }
6247
6248    /**
6249     * Call this view's OnContextClickListener, if it is defined.
6250     *
6251     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6252     *         otherwise.
6253     */
6254    public boolean performContextClick() {
6255        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6256
6257        boolean handled = false;
6258        ListenerInfo li = mListenerInfo;
6259        if (li != null && li.mOnContextClickListener != null) {
6260            handled = li.mOnContextClickListener.onContextClick(View.this);
6261        }
6262        if (handled) {
6263            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6264        }
6265        return handled;
6266    }
6267
6268    /**
6269     * Performs button-related actions during a touch down event.
6270     *
6271     * @param event The event.
6272     * @return True if the down was consumed.
6273     *
6274     * @hide
6275     */
6276    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6277        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6278            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6279            showContextMenu(event.getX(), event.getY());
6280            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6281            return true;
6282        }
6283        return false;
6284    }
6285
6286    /**
6287     * Shows the context menu for this view.
6288     *
6289     * @return {@code true} if the context menu was shown, {@code false}
6290     *         otherwise
6291     * @see #showContextMenu(float, float)
6292     */
6293    public boolean showContextMenu() {
6294        return getParent().showContextMenuForChild(this);
6295    }
6296
6297    /**
6298     * Shows the context menu for this view anchored to the specified
6299     * view-relative coordinate.
6300     *
6301     * @param x the X coordinate in pixels relative to the view to which the
6302     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6303     * @param y the Y coordinate in pixels relative to the view to which the
6304     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6305     * @return {@code true} if the context menu was shown, {@code false}
6306     *         otherwise
6307     */
6308    public boolean showContextMenu(float x, float y) {
6309        return getParent().showContextMenuForChild(this, x, y);
6310    }
6311
6312    /**
6313     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6314     *
6315     * @param callback Callback that will control the lifecycle of the action mode
6316     * @return The new action mode if it is started, null otherwise
6317     *
6318     * @see ActionMode
6319     * @see #startActionMode(android.view.ActionMode.Callback, int)
6320     */
6321    public ActionMode startActionMode(ActionMode.Callback callback) {
6322        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6323    }
6324
6325    /**
6326     * Start an action mode with the given type.
6327     *
6328     * @param callback Callback that will control the lifecycle of the action mode
6329     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6330     * @return The new action mode if it is started, null otherwise
6331     *
6332     * @see ActionMode
6333     */
6334    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6335        ViewParent parent = getParent();
6336        if (parent == null) return null;
6337        try {
6338            return parent.startActionModeForChild(this, callback, type);
6339        } catch (AbstractMethodError ame) {
6340            // Older implementations of custom views might not implement this.
6341            return parent.startActionModeForChild(this, callback);
6342        }
6343    }
6344
6345    /**
6346     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6347     * Context, creating a unique View identifier to retrieve the result.
6348     *
6349     * @param intent The Intent to be started.
6350     * @param requestCode The request code to use.
6351     * @hide
6352     */
6353    public void startActivityForResult(Intent intent, int requestCode) {
6354        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6355        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6356    }
6357
6358    /**
6359     * If this View corresponds to the calling who, dispatches the activity result.
6360     * @param who The identifier for the targeted View to receive the result.
6361     * @param requestCode The integer request code originally supplied to
6362     *                    startActivityForResult(), allowing you to identify who this
6363     *                    result came from.
6364     * @param resultCode The integer result code returned by the child activity
6365     *                   through its setResult().
6366     * @param data An Intent, which can return result data to the caller
6367     *               (various data can be attached to Intent "extras").
6368     * @return {@code true} if the activity result was dispatched.
6369     * @hide
6370     */
6371    public boolean dispatchActivityResult(
6372            String who, int requestCode, int resultCode, Intent data) {
6373        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6374            onActivityResult(requestCode, resultCode, data);
6375            mStartActivityRequestWho = null;
6376            return true;
6377        }
6378        return false;
6379    }
6380
6381    /**
6382     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6383     *
6384     * @param requestCode The integer request code originally supplied to
6385     *                    startActivityForResult(), allowing you to identify who this
6386     *                    result came from.
6387     * @param resultCode The integer result code returned by the child activity
6388     *                   through its setResult().
6389     * @param data An Intent, which can return result data to the caller
6390     *               (various data can be attached to Intent "extras").
6391     * @hide
6392     */
6393    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6394        // Do nothing.
6395    }
6396
6397    /**
6398     * Register a callback to be invoked when a hardware key is pressed in this view.
6399     * Key presses in software input methods will generally not trigger the methods of
6400     * this listener.
6401     * @param l the key listener to attach to this view
6402     */
6403    public void setOnKeyListener(OnKeyListener l) {
6404        getListenerInfo().mOnKeyListener = l;
6405    }
6406
6407    /**
6408     * Register a callback to be invoked when a touch event is sent to this view.
6409     * @param l the touch listener to attach to this view
6410     */
6411    public void setOnTouchListener(OnTouchListener l) {
6412        getListenerInfo().mOnTouchListener = l;
6413    }
6414
6415    /**
6416     * Register a callback to be invoked when a generic motion event is sent to this view.
6417     * @param l the generic motion listener to attach to this view
6418     */
6419    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6420        getListenerInfo().mOnGenericMotionListener = l;
6421    }
6422
6423    /**
6424     * Register a callback to be invoked when a hover event is sent to this view.
6425     * @param l the hover listener to attach to this view
6426     */
6427    public void setOnHoverListener(OnHoverListener l) {
6428        getListenerInfo().mOnHoverListener = l;
6429    }
6430
6431    /**
6432     * Register a drag event listener callback object for this View. The parameter is
6433     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6434     * View, the system calls the
6435     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6436     * @param l An implementation of {@link android.view.View.OnDragListener}.
6437     */
6438    public void setOnDragListener(OnDragListener l) {
6439        getListenerInfo().mOnDragListener = l;
6440    }
6441
6442    /**
6443     * Give this view focus. This will cause
6444     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6445     *
6446     * Note: this does not check whether this {@link View} should get focus, it just
6447     * gives it focus no matter what.  It should only be called internally by framework
6448     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6449     *
6450     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6451     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6452     *        focus moved when requestFocus() is called. It may not always
6453     *        apply, in which case use the default View.FOCUS_DOWN.
6454     * @param previouslyFocusedRect The rectangle of the view that had focus
6455     *        prior in this View's coordinate system.
6456     */
6457    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6458        if (DBG) {
6459            System.out.println(this + " requestFocus()");
6460        }
6461
6462        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6463            mPrivateFlags |= PFLAG_FOCUSED;
6464
6465            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6466
6467            if (mParent != null) {
6468                mParent.requestChildFocus(this, this);
6469                setFocusedInCluster();
6470            }
6471
6472            if (mAttachInfo != null) {
6473                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6474            }
6475
6476            onFocusChanged(true, direction, previouslyFocusedRect);
6477            refreshDrawableState();
6478        }
6479    }
6480
6481    /**
6482     * Sets this view's preference for reveal behavior when it gains focus.
6483     *
6484     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6485     * this view would prefer to be brought fully into view when it gains focus.
6486     * For example, a text field that a user is meant to type into. Other views such
6487     * as scrolling containers may prefer to opt-out of this behavior.</p>
6488     *
6489     * <p>The default value for views is true, though subclasses may change this
6490     * based on their preferred behavior.</p>
6491     *
6492     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6493     *
6494     * @see #getRevealOnFocusHint()
6495     */
6496    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6497        if (revealOnFocus) {
6498            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6499        } else {
6500            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6501        }
6502    }
6503
6504    /**
6505     * Returns this view's preference for reveal behavior when it gains focus.
6506     *
6507     * <p>When this method returns true for a child view requesting focus, ancestor
6508     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6509     * should make a best effort to make the newly focused child fully visible to the user.
6510     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6511     * other properties affecting visibility to the user as part of the focus change.</p>
6512     *
6513     * @return true if this view would prefer to become fully visible when it gains focus,
6514     *         false if it would prefer not to disrupt scroll positioning
6515     *
6516     * @see #setRevealOnFocusHint(boolean)
6517     */
6518    public final boolean getRevealOnFocusHint() {
6519        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6520    }
6521
6522    /**
6523     * Populates <code>outRect</code> with the hotspot bounds. By default,
6524     * the hotspot bounds are identical to the screen bounds.
6525     *
6526     * @param outRect rect to populate with hotspot bounds
6527     * @hide Only for internal use by views and widgets.
6528     */
6529    public void getHotspotBounds(Rect outRect) {
6530        final Drawable background = getBackground();
6531        if (background != null) {
6532            background.getHotspotBounds(outRect);
6533        } else {
6534            getBoundsOnScreen(outRect);
6535        }
6536    }
6537
6538    /**
6539     * Request that a rectangle of this view be visible on the screen,
6540     * scrolling if necessary just enough.
6541     *
6542     * <p>A View should call this if it maintains some notion of which part
6543     * of its content is interesting.  For example, a text editing view
6544     * should call this when its cursor moves.
6545     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6546     * It should not be affected by which part of the View is currently visible or its scroll
6547     * position.
6548     *
6549     * @param rectangle The rectangle in the View's content coordinate space
6550     * @return Whether any parent scrolled.
6551     */
6552    public boolean requestRectangleOnScreen(Rect rectangle) {
6553        return requestRectangleOnScreen(rectangle, false);
6554    }
6555
6556    /**
6557     * Request that a rectangle of this view be visible on the screen,
6558     * scrolling if necessary just enough.
6559     *
6560     * <p>A View should call this if it maintains some notion of which part
6561     * of its content is interesting.  For example, a text editing view
6562     * should call this when its cursor moves.
6563     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6564     * It should not be affected by which part of the View is currently visible or its scroll
6565     * position.
6566     * <p>When <code>immediate</code> is set to true, scrolling will not be
6567     * animated.
6568     *
6569     * @param rectangle The rectangle in the View's content coordinate space
6570     * @param immediate True to forbid animated scrolling, false otherwise
6571     * @return Whether any parent scrolled.
6572     */
6573    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6574        if (mParent == null) {
6575            return false;
6576        }
6577
6578        View child = this;
6579
6580        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6581        position.set(rectangle);
6582
6583        ViewParent parent = mParent;
6584        boolean scrolled = false;
6585        while (parent != null) {
6586            rectangle.set((int) position.left, (int) position.top,
6587                    (int) position.right, (int) position.bottom);
6588
6589            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6590
6591            if (!(parent instanceof View)) {
6592                break;
6593            }
6594
6595            // move it from child's content coordinate space to parent's content coordinate space
6596            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6597
6598            child = (View) parent;
6599            parent = child.getParent();
6600        }
6601
6602        return scrolled;
6603    }
6604
6605    /**
6606     * Called when this view wants to give up focus. If focus is cleared
6607     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6608     * <p>
6609     * <strong>Note:</strong> When a View clears focus the framework is trying
6610     * to give focus to the first focusable View from the top. Hence, if this
6611     * View is the first from the top that can take focus, then all callbacks
6612     * related to clearing focus will be invoked after which the framework will
6613     * give focus to this view.
6614     * </p>
6615     */
6616    public void clearFocus() {
6617        if (DBG) {
6618            System.out.println(this + " clearFocus()");
6619        }
6620
6621        clearFocusInternal(null, true, true);
6622    }
6623
6624    /**
6625     * Clears focus from the view, optionally propagating the change up through
6626     * the parent hierarchy and requesting that the root view place new focus.
6627     *
6628     * @param propagate whether to propagate the change up through the parent
6629     *            hierarchy
6630     * @param refocus when propagate is true, specifies whether to request the
6631     *            root view place new focus
6632     */
6633    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6634        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6635            mPrivateFlags &= ~PFLAG_FOCUSED;
6636
6637            if (propagate && mParent != null) {
6638                mParent.clearChildFocus(this);
6639            }
6640
6641            onFocusChanged(false, 0, null);
6642            refreshDrawableState();
6643
6644            if (propagate && (!refocus || !rootViewRequestFocus())) {
6645                notifyGlobalFocusCleared(this);
6646            }
6647        }
6648    }
6649
6650    void notifyGlobalFocusCleared(View oldFocus) {
6651        if (oldFocus != null && mAttachInfo != null) {
6652            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6653        }
6654    }
6655
6656    boolean rootViewRequestFocus() {
6657        final View root = getRootView();
6658        return root != null && root.requestFocus();
6659    }
6660
6661    /**
6662     * Called internally by the view system when a new view is getting focus.
6663     * This is what clears the old focus.
6664     * <p>
6665     * <b>NOTE:</b> The parent view's focused child must be updated manually
6666     * after calling this method. Otherwise, the view hierarchy may be left in
6667     * an inconstent state.
6668     */
6669    void unFocus(View focused) {
6670        if (DBG) {
6671            System.out.println(this + " unFocus()");
6672        }
6673
6674        clearFocusInternal(focused, false, false);
6675    }
6676
6677    /**
6678     * Returns true if this view has focus itself, or is the ancestor of the
6679     * view that has focus.
6680     *
6681     * @return True if this view has or contains focus, false otherwise.
6682     */
6683    @ViewDebug.ExportedProperty(category = "focus")
6684    public boolean hasFocus() {
6685        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6686    }
6687
6688    /**
6689     * Returns true if this view is focusable or if it contains a reachable View
6690     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6691     * is a view whose parents do not block descendants focus.
6692     * Only {@link #VISIBLE} views are considered focusable.
6693     *
6694     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6695     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6696     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6697     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6698     * {@code false} for views not explicitly marked as focusable.
6699     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6700     * behavior.</p>
6701     *
6702     * @return {@code true} if the view is focusable or if the view contains a focusable
6703     *         view, {@code false} otherwise
6704     *
6705     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6706     * @see ViewGroup#getTouchscreenBlocksFocus()
6707     * @see #hasExplicitFocusable()
6708     */
6709    public boolean hasFocusable() {
6710        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6711    }
6712
6713    /**
6714     * Returns true if this view is focusable or if it contains a reachable View
6715     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6716     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6717     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6718     * {@link #FOCUSABLE} are considered focusable.
6719     *
6720     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6721     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6722     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6723     * to focusable will not.</p>
6724     *
6725     * @return {@code true} if the view is focusable or if the view contains a focusable
6726     *         view, {@code false} otherwise
6727     *
6728     * @see #hasFocusable()
6729     */
6730    public boolean hasExplicitFocusable() {
6731        return hasFocusable(false, true);
6732    }
6733
6734    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6735        if (!isFocusableInTouchMode()) {
6736            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6737                final ViewGroup g = (ViewGroup) p;
6738                if (g.shouldBlockFocusForTouchscreen()) {
6739                    return false;
6740                }
6741            }
6742        }
6743
6744        // Invisible and gone views are never focusable.
6745        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6746            return false;
6747        }
6748
6749        // Only use effective focusable value when allowed.
6750        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6751            return true;
6752        }
6753
6754        return false;
6755    }
6756
6757    /**
6758     * Called by the view system when the focus state of this view changes.
6759     * When the focus change event is caused by directional navigation, direction
6760     * and previouslyFocusedRect provide insight into where the focus is coming from.
6761     * When overriding, be sure to call up through to the super class so that
6762     * the standard focus handling will occur.
6763     *
6764     * @param gainFocus True if the View has focus; false otherwise.
6765     * @param direction The direction focus has moved when requestFocus()
6766     *                  is called to give this view focus. Values are
6767     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6768     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6769     *                  It may not always apply, in which case use the default.
6770     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6771     *        system, of the previously focused view.  If applicable, this will be
6772     *        passed in as finer grained information about where the focus is coming
6773     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6774     */
6775    @CallSuper
6776    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6777            @Nullable Rect previouslyFocusedRect) {
6778        if (gainFocus) {
6779            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6780        } else {
6781            notifyViewAccessibilityStateChangedIfNeeded(
6782                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6783        }
6784
6785        InputMethodManager imm = InputMethodManager.peekInstance();
6786        if (!gainFocus) {
6787            if (isPressed()) {
6788                setPressed(false);
6789            }
6790            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6791                imm.focusOut(this);
6792            }
6793            onFocusLost();
6794        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6795            imm.focusIn(this);
6796        }
6797
6798        invalidate(true);
6799        ListenerInfo li = mListenerInfo;
6800        if (li != null && li.mOnFocusChangeListener != null) {
6801            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6802        }
6803
6804        if (mAttachInfo != null) {
6805            mAttachInfo.mKeyDispatchState.reset(this);
6806        }
6807
6808        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6809    }
6810
6811    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6812        if (isAutofillable() && isAttachedToWindow()
6813                && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
6814            AutofillManager afm = getAutofillManager();
6815            if (afm != null) {
6816                if (enter && hasWindowFocus() && isFocused()) {
6817                    afm.notifyViewEntered(this);
6818                } else if (!hasWindowFocus() || !isFocused()) {
6819                    afm.notifyViewExited(this);
6820                }
6821            }
6822        }
6823    }
6824
6825    /**
6826     * Sends an accessibility event of the given type. If accessibility is
6827     * not enabled this method has no effect. The default implementation calls
6828     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6829     * to populate information about the event source (this View), then calls
6830     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6831     * populate the text content of the event source including its descendants,
6832     * and last calls
6833     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6834     * on its parent to request sending of the event to interested parties.
6835     * <p>
6836     * If an {@link AccessibilityDelegate} has been specified via calling
6837     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6838     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6839     * responsible for handling this call.
6840     * </p>
6841     *
6842     * @param eventType The type of the event to send, as defined by several types from
6843     * {@link android.view.accessibility.AccessibilityEvent}, such as
6844     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6845     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6846     *
6847     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6848     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6849     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6850     * @see AccessibilityDelegate
6851     */
6852    public void sendAccessibilityEvent(int eventType) {
6853        if (mAccessibilityDelegate != null) {
6854            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6855        } else {
6856            sendAccessibilityEventInternal(eventType);
6857        }
6858    }
6859
6860    /**
6861     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6862     * {@link AccessibilityEvent} to make an announcement which is related to some
6863     * sort of a context change for which none of the events representing UI transitions
6864     * is a good fit. For example, announcing a new page in a book. If accessibility
6865     * is not enabled this method does nothing.
6866     *
6867     * @param text The announcement text.
6868     */
6869    public void announceForAccessibility(CharSequence text) {
6870        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6871            AccessibilityEvent event = AccessibilityEvent.obtain(
6872                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6873            onInitializeAccessibilityEvent(event);
6874            event.getText().add(text);
6875            event.setContentDescription(null);
6876            mParent.requestSendAccessibilityEvent(this, event);
6877        }
6878    }
6879
6880    /**
6881     * @see #sendAccessibilityEvent(int)
6882     *
6883     * Note: Called from the default {@link AccessibilityDelegate}.
6884     *
6885     * @hide
6886     */
6887    public void sendAccessibilityEventInternal(int eventType) {
6888        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6889            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6890        }
6891    }
6892
6893    /**
6894     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6895     * takes as an argument an empty {@link AccessibilityEvent} and does not
6896     * perform a check whether accessibility is enabled.
6897     * <p>
6898     * If an {@link AccessibilityDelegate} has been specified via calling
6899     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6900     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6901     * is responsible for handling this call.
6902     * </p>
6903     *
6904     * @param event The event to send.
6905     *
6906     * @see #sendAccessibilityEvent(int)
6907     */
6908    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6909        if (mAccessibilityDelegate != null) {
6910            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6911        } else {
6912            sendAccessibilityEventUncheckedInternal(event);
6913        }
6914    }
6915
6916    /**
6917     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6918     *
6919     * Note: Called from the default {@link AccessibilityDelegate}.
6920     *
6921     * @hide
6922     */
6923    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6924        if (!isShown()) {
6925            return;
6926        }
6927        onInitializeAccessibilityEvent(event);
6928        // Only a subset of accessibility events populates text content.
6929        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6930            dispatchPopulateAccessibilityEvent(event);
6931        }
6932        // In the beginning we called #isShown(), so we know that getParent() is not null.
6933        getParent().requestSendAccessibilityEvent(this, event);
6934    }
6935
6936    /**
6937     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6938     * to its children for adding their text content to the event. Note that the
6939     * event text is populated in a separate dispatch path since we add to the
6940     * event not only the text of the source but also the text of all its descendants.
6941     * A typical implementation will call
6942     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6943     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6944     * on each child. Override this method if custom population of the event text
6945     * content is required.
6946     * <p>
6947     * If an {@link AccessibilityDelegate} has been specified via calling
6948     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6949     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6950     * is responsible for handling this call.
6951     * </p>
6952     * <p>
6953     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6954     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6955     * </p>
6956     *
6957     * @param event The event.
6958     *
6959     * @return True if the event population was completed.
6960     */
6961    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6962        if (mAccessibilityDelegate != null) {
6963            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6964        } else {
6965            return dispatchPopulateAccessibilityEventInternal(event);
6966        }
6967    }
6968
6969    /**
6970     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6971     *
6972     * Note: Called from the default {@link AccessibilityDelegate}.
6973     *
6974     * @hide
6975     */
6976    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6977        onPopulateAccessibilityEvent(event);
6978        return false;
6979    }
6980
6981    /**
6982     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6983     * giving a chance to this View to populate the accessibility event with its
6984     * text content. While this method is free to modify event
6985     * attributes other than text content, doing so should normally be performed in
6986     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6987     * <p>
6988     * Example: Adding formatted date string to an accessibility event in addition
6989     *          to the text added by the super implementation:
6990     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6991     *     super.onPopulateAccessibilityEvent(event);
6992     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6993     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6994     *         mCurrentDate.getTimeInMillis(), flags);
6995     *     event.getText().add(selectedDateUtterance);
6996     * }</pre>
6997     * <p>
6998     * If an {@link AccessibilityDelegate} has been specified via calling
6999     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7000     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7001     * is responsible for handling this call.
7002     * </p>
7003     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7004     * information to the event, in case the default implementation has basic information to add.
7005     * </p>
7006     *
7007     * @param event The accessibility event which to populate.
7008     *
7009     * @see #sendAccessibilityEvent(int)
7010     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7011     */
7012    @CallSuper
7013    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7014        if (mAccessibilityDelegate != null) {
7015            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7016        } else {
7017            onPopulateAccessibilityEventInternal(event);
7018        }
7019    }
7020
7021    /**
7022     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7023     *
7024     * Note: Called from the default {@link AccessibilityDelegate}.
7025     *
7026     * @hide
7027     */
7028    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7029    }
7030
7031    /**
7032     * Initializes an {@link AccessibilityEvent} with information about
7033     * this View which is the event source. In other words, the source of
7034     * an accessibility event is the view whose state change triggered firing
7035     * the event.
7036     * <p>
7037     * Example: Setting the password property of an event in addition
7038     *          to properties set by the super implementation:
7039     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7040     *     super.onInitializeAccessibilityEvent(event);
7041     *     event.setPassword(true);
7042     * }</pre>
7043     * <p>
7044     * If an {@link AccessibilityDelegate} has been specified via calling
7045     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7046     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7047     * is responsible for handling this call.
7048     * </p>
7049     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7050     * information to the event, in case the default implementation has basic information to add.
7051     * </p>
7052     * @param event The event to initialize.
7053     *
7054     * @see #sendAccessibilityEvent(int)
7055     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7056     */
7057    @CallSuper
7058    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7059        if (mAccessibilityDelegate != null) {
7060            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7061        } else {
7062            onInitializeAccessibilityEventInternal(event);
7063        }
7064    }
7065
7066    /**
7067     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7068     *
7069     * Note: Called from the default {@link AccessibilityDelegate}.
7070     *
7071     * @hide
7072     */
7073    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7074        event.setSource(this);
7075        event.setClassName(getAccessibilityClassName());
7076        event.setPackageName(getContext().getPackageName());
7077        event.setEnabled(isEnabled());
7078        event.setContentDescription(mContentDescription);
7079
7080        switch (event.getEventType()) {
7081            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7082                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7083                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7084                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7085                event.setItemCount(focusablesTempList.size());
7086                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7087                if (mAttachInfo != null) {
7088                    focusablesTempList.clear();
7089                }
7090            } break;
7091            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7092                CharSequence text = getIterableTextForAccessibility();
7093                if (text != null && text.length() > 0) {
7094                    event.setFromIndex(getAccessibilitySelectionStart());
7095                    event.setToIndex(getAccessibilitySelectionEnd());
7096                    event.setItemCount(text.length());
7097                }
7098            } break;
7099        }
7100    }
7101
7102    /**
7103     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7104     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7105     * This method is responsible for obtaining an accessibility node info from a
7106     * pool of reusable instances and calling
7107     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7108     * initialize the former.
7109     * <p>
7110     * Note: The client is responsible for recycling the obtained instance by calling
7111     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7112     * </p>
7113     *
7114     * @return A populated {@link AccessibilityNodeInfo}.
7115     *
7116     * @see AccessibilityNodeInfo
7117     */
7118    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7119        if (mAccessibilityDelegate != null) {
7120            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7121        } else {
7122            return createAccessibilityNodeInfoInternal();
7123        }
7124    }
7125
7126    /**
7127     * @see #createAccessibilityNodeInfo()
7128     *
7129     * @hide
7130     */
7131    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7132        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7133        if (provider != null) {
7134            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7135        } else {
7136            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7137            onInitializeAccessibilityNodeInfo(info);
7138            return info;
7139        }
7140    }
7141
7142    /**
7143     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7144     * The base implementation sets:
7145     * <ul>
7146     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7147     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7148     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7149     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7150     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7151     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7152     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7153     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7154     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7155     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7156     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7157     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7158     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7159     * </ul>
7160     * <p>
7161     * Subclasses should override this method, call the super implementation,
7162     * and set additional attributes.
7163     * </p>
7164     * <p>
7165     * If an {@link AccessibilityDelegate} has been specified via calling
7166     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7167     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7168     * is responsible for handling this call.
7169     * </p>
7170     *
7171     * @param info The instance to initialize.
7172     */
7173    @CallSuper
7174    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7175        if (mAccessibilityDelegate != null) {
7176            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7177        } else {
7178            onInitializeAccessibilityNodeInfoInternal(info);
7179        }
7180    }
7181
7182    /**
7183     * Gets the location of this view in screen coordinates.
7184     *
7185     * @param outRect The output location
7186     * @hide
7187     */
7188    public void getBoundsOnScreen(Rect outRect) {
7189        getBoundsOnScreen(outRect, false);
7190    }
7191
7192    /**
7193     * Gets the location of this view in screen coordinates.
7194     *
7195     * @param outRect The output location
7196     * @param clipToParent Whether to clip child bounds to the parent ones.
7197     * @hide
7198     */
7199    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7200        if (mAttachInfo == null) {
7201            return;
7202        }
7203
7204        RectF position = mAttachInfo.mTmpTransformRect;
7205        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7206
7207        if (!hasIdentityMatrix()) {
7208            getMatrix().mapRect(position);
7209        }
7210
7211        position.offset(mLeft, mTop);
7212
7213        ViewParent parent = mParent;
7214        while (parent instanceof View) {
7215            View parentView = (View) parent;
7216
7217            position.offset(-parentView.mScrollX, -parentView.mScrollY);
7218
7219            if (clipToParent) {
7220                position.left = Math.max(position.left, 0);
7221                position.top = Math.max(position.top, 0);
7222                position.right = Math.min(position.right, parentView.getWidth());
7223                position.bottom = Math.min(position.bottom, parentView.getHeight());
7224            }
7225
7226            if (!parentView.hasIdentityMatrix()) {
7227                parentView.getMatrix().mapRect(position);
7228            }
7229
7230            position.offset(parentView.mLeft, parentView.mTop);
7231
7232            parent = parentView.mParent;
7233        }
7234
7235        if (parent instanceof ViewRootImpl) {
7236            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7237            position.offset(0, -viewRootImpl.mCurScrollY);
7238        }
7239
7240        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7241
7242        outRect.set(Math.round(position.left), Math.round(position.top),
7243                Math.round(position.right), Math.round(position.bottom));
7244    }
7245
7246    /**
7247     * Return the class name of this object to be used for accessibility purposes.
7248     * Subclasses should only override this if they are implementing something that
7249     * should be seen as a completely new class of view when used by accessibility,
7250     * unrelated to the class it is deriving from.  This is used to fill in
7251     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7252     */
7253    public CharSequence getAccessibilityClassName() {
7254        return View.class.getName();
7255    }
7256
7257    /**
7258     * Called when assist structure is being retrieved from a view as part of
7259     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7260     * @param structure Fill in with structured view data.  The default implementation
7261     * fills in all data that can be inferred from the view itself.
7262     */
7263    public void onProvideStructure(ViewStructure structure) {
7264        onProvideStructureForAssistOrAutofill(structure, false);
7265    }
7266
7267    /**
7268     * Called when assist structure is being retrieved from a view as part of an autofill request.
7269     *
7270     * <p>This method already provides most of what's needed for autofill, but should be overridden
7271     * when:
7272     * <ol>
7273     * <li>The view contents does not include PII (Personally Identifiable Information), so it
7274     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7275     * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7276     * {@link ViewStructure#setAutofillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
7277     * </ol>
7278     *
7279     * @param structure Fill in with structured view data. The default implementation
7280     * fills in all data that can be inferred from the view itself.
7281     * @param flags optional flags (currently {@code 0}).
7282     */
7283    @CallSuper
7284    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
7285        onProvideStructureForAssistOrAutofill(structure, true);
7286    }
7287
7288    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7289            boolean forAutofill) {
7290        final int id = mID;
7291        if (id != NO_ID && !isViewIdGenerated(id)) {
7292            String pkg, type, entry;
7293            try {
7294                final Resources res = getResources();
7295                entry = res.getResourceEntryName(id);
7296                type = res.getResourceTypeName(id);
7297                pkg = res.getResourcePackageName(id);
7298            } catch (Resources.NotFoundException e) {
7299                entry = type = pkg = null;
7300            }
7301            structure.setId(id, pkg, type, entry);
7302        } else {
7303            structure.setId(id, null, null, null);
7304        }
7305
7306        if (forAutofill) {
7307            final @AutofillType int autofillType = getAutofillType();
7308            // Don't need to fill autofill info if view does not support it.
7309            // For example, only TextViews that are editable support autofill
7310            if (autofillType != AUTOFILL_TYPE_NONE) {
7311                // The autofill id needs to be unique, but its value doesn't matter, so it's better
7312                // to reuse the accessibility id to save space.
7313                structure.setAutofillId(getAccessibilityViewId());
7314                structure.setAutofillType(autofillType);
7315                structure.setAutofillHint(getAutofillHint());
7316                structure.setAutofillValue(getAutofillValue());
7317            }
7318        }
7319
7320        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
7321        if (!hasIdentityMatrix()) {
7322            structure.setTransformation(getMatrix());
7323        }
7324        structure.setElevation(getZ());
7325        structure.setVisibility(getVisibility());
7326        structure.setEnabled(isEnabled());
7327        if (isClickable()) {
7328            structure.setClickable(true);
7329        }
7330        if (isFocusable()) {
7331            structure.setFocusable(true);
7332        }
7333        if (isFocused()) {
7334            structure.setFocused(true);
7335        }
7336        if (isAccessibilityFocused()) {
7337            structure.setAccessibilityFocused(true);
7338        }
7339        if (isSelected()) {
7340            structure.setSelected(true);
7341        }
7342        if (isActivated()) {
7343            structure.setActivated(true);
7344        }
7345        if (isLongClickable()) {
7346            structure.setLongClickable(true);
7347        }
7348        if (this instanceof Checkable) {
7349            structure.setCheckable(true);
7350            if (((Checkable)this).isChecked()) {
7351                structure.setChecked(true);
7352            }
7353        }
7354        if (isOpaque()) {
7355            structure.setOpaque(true);
7356        }
7357        if (isContextClickable()) {
7358            structure.setContextClickable(true);
7359        }
7360        structure.setClassName(getAccessibilityClassName().toString());
7361        structure.setContentDescription(getContentDescription());
7362    }
7363
7364    /**
7365     * Called when assist structure is being retrieved from a view as part of
7366     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7367     * generate additional virtual structure under this view.  The defaullt implementation
7368     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7369     * view's virtual accessibility nodes, if any.  You can override this for a more
7370     * optimal implementation providing this data.
7371     */
7372    public void onProvideVirtualStructure(ViewStructure structure) {
7373        onProvideVirtualStructureForAssistOrAutofill(structure, false);
7374    }
7375
7376    /**
7377     * Called when assist structure is being retrieved from a view as part of an autofill request
7378     * to generate additional virtual structure under this view.
7379     *
7380     * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
7381     * generate this from the view's virtual accessibility nodes, if any. You can override this
7382     * for a more optimal implementation providing this data.
7383     *
7384     * <p>When implementing this method, subclasses must follow the rules below:
7385     *
7386     * <ol>
7387     * <li>Also implement {@link #autofillVirtual(int, AutofillValue)} to autofill the virtual
7388     * children.
7389     * <li>Call
7390     * {@link android.view.autofill.AutofillManager#notifyVirtualViewEntered} and
7391     * {@link android.view.autofill.AutofillManager#notifyVirtualViewExited(View, int)}
7392     * when the focus inside the view changed.
7393     * <li>Call {@link android.view.autofill.AutofillManager#notifyVirtualValueChanged(View, int,
7394     * AutofillValue)} when the value of a child changed.
7395     * <li>Call {@link AutofillManager#commit()} when the autofill context
7396     * of the view structure changed and you want the current autofill interaction if such
7397     * to be commited.
7398     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7399     * of the view structure changed and you want the current autofill interaction if such
7400     * to be cancelled.
7401     * </ol>
7402     *
7403     * @param structure Fill in with structured view data.
7404     * @param flags optional flags (currently {@code 0}).
7405     */
7406    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7407        onProvideVirtualStructureForAssistOrAutofill(structure, true);
7408    }
7409
7410    private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure,
7411            boolean forAutofill) {
7412        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7413        // this method should take a boolean with the type of request.
7414        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7415        if (provider != null) {
7416            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7417            structure.setChildCount(1);
7418            ViewStructure root = structure.newChild(0);
7419            populateVirtualStructure(root, provider, info, forAutofill);
7420            info.recycle();
7421        }
7422    }
7423
7424    /**
7425     * Automatically fills the content of this view with the {@code value}.
7426     *
7427     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7428     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7429     * to support the Autofill Framework.
7430     *
7431     * <p>Typically, it is implemented by:
7432     *
7433     * <ol>
7434     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7435     * <li>Passing the actual value to the equivalent setter in the view.
7436     * <ol>
7437     *
7438     * <p>For example, a text-field view would call:
7439     *
7440     * <pre class="prettyprint">
7441     * CharSequence text = value.getTextValue();
7442     * if (text != null) {
7443     *     setText(text);
7444     * }
7445     * </pre>
7446     *
7447     * @param value value to be autofilled.
7448     */
7449    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7450    }
7451
7452    /**
7453     * Automatically fills the content of a virtual view with the {@code value}
7454     *
7455     * <p>See {@link #autofill(AutofillValue)} and
7456     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7457     *
7458     * @param value value to be autofilled.
7459     * @param virtualId id identifying the virtual child inside the custom view.
7460     */
7461    public void autofillVirtual(@SuppressWarnings("unused") int virtualId,
7462            @SuppressWarnings("unused") AutofillValue value) {
7463    }
7464
7465    /**
7466     * Describes the autofill type that should be used on calls to
7467     * {@link #autofill(AutofillValue)} and {@link #autofillVirtual(int, AutofillValue)}.
7468     *
7469     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7470     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7471     */
7472    public @AutofillType int getAutofillType() {
7473        return AUTOFILL_TYPE_NONE;
7474    }
7475
7476    /**
7477     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7478     *
7479     * @return The hint set via the attribute or {@code null} if no hint it set.
7480     *
7481     * @attr ref android.R.styleable#View_autofillHint
7482     */
7483    @ViewDebug.ExportedProperty()
7484    @Nullable public String[] getAutofillHint() {
7485        return mAutofillHint;
7486    }
7487
7488    /**
7489     * Gets the {@link View}'s current autofill value.
7490     *
7491     * <p>By default returns {@code null}, but views should override it (and
7492     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7493     * Framework.
7494     */
7495    @Nullable
7496    public AutofillValue getAutofillValue() {
7497        return null;
7498    }
7499
7500    /**
7501     * Gets the mode for determining whether this View is important for autofill.
7502     *
7503     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7504     *
7505     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7506     * {@link #setImportantForAutofill(int)}.
7507     *
7508     * @attr ref android.R.styleable#View_importantForAutofill
7509     */
7510    @ViewDebug.ExportedProperty(mapping = {
7511            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7512            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7513            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
7514    public @AutofillImportance int getImportantForAutofill() {
7515        return (mPrivateFlags3
7516                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7517    }
7518
7519    /**
7520     * Sets the mode for determining whether this View is important for autofill.
7521     *
7522     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7523     *
7524     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7525     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7526     *
7527     * @attr ref android.R.styleable#View_importantForAutofill
7528     */
7529    public void setImportantForAutofill(@AutofillImportance int mode) {
7530        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7531        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7532                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7533    }
7534
7535    /**
7536     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7537     * associated with this View should be included in a {@link ViewStructure} used for
7538     * autofill purposes.
7539     *
7540     * <p>Generally speaking, a view is important for autofill if:
7541     * <ol>
7542     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7543     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7544     * autofill other views.
7545     * <ol>
7546     *
7547     * <p>For example, view containers should typically return {@code false} for performance reasons
7548     * (since the important info is provided by their children), but if the container is actually
7549     * whose children are part of a compound view, it should return {@code true} (and then override
7550     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7551     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7552     * the structure). On the other hand, views representing labels or editable fields should
7553     * typically return {@code true}, but in some cases they could return {@code false} (for
7554     * example, if they're part of a "Captcha" mechanism).
7555     *
7556     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7557     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7558     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7559     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7560     * should use {@link #setImportantForAutofill(int)} instead.
7561     *
7562     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7563     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
7564     * View might be always included.
7565     *
7566     * <p>This decision applies just for the view, not its children - if the view children are not
7567     * important for autofill, the view should override
7568     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7569     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7570     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7571     *
7572     * @return whether the view is considered important for autofill.
7573     *
7574     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7575     * @see #IMPORTANT_FOR_AUTOFILL_YES
7576     * @see #IMPORTANT_FOR_AUTOFILL_NO
7577     */
7578    public final boolean isImportantForAutofill() {
7579        final int flag = getImportantForAutofill();
7580
7581        // First, check if view explicity set it to YES or NO
7582        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
7583            return true;
7584        }
7585        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
7586            return false;
7587        }
7588
7589        // Then use some heuristics to handle AUTO.
7590
7591        // Always include views that have a explicity resource id.
7592        final int id = mID;
7593        if (id != NO_ID && !isViewIdGenerated(id)) {
7594            final Resources res = getResources();
7595            String entry = null;
7596            String pkg = null;
7597            try {
7598                entry = res.getResourceEntryName(id);
7599                pkg = res.getResourcePackageName(id);
7600            } catch (Resources.NotFoundException e) {
7601                // ignore
7602            }
7603            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7604                return true;
7605            }
7606        }
7607
7608        // Otherwise, assume it's not important...
7609        return false;
7610    }
7611
7612    @Nullable
7613    private AutofillManager getAutofillManager() {
7614        return mContext.getSystemService(AutofillManager.class);
7615    }
7616
7617    private boolean isAutofillable() {
7618        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
7619    }
7620
7621    private void populateVirtualStructure(ViewStructure structure,
7622            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) {
7623        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7624                null, null, null);
7625        Rect rect = structure.getTempRect();
7626        info.getBoundsInParent(rect);
7627        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7628        structure.setVisibility(VISIBLE);
7629        structure.setEnabled(info.isEnabled());
7630        if (info.isClickable()) {
7631            structure.setClickable(true);
7632        }
7633        if (info.isFocusable()) {
7634            structure.setFocusable(true);
7635        }
7636        if (info.isFocused()) {
7637            structure.setFocused(true);
7638        }
7639        if (info.isAccessibilityFocused()) {
7640            structure.setAccessibilityFocused(true);
7641        }
7642        if (info.isSelected()) {
7643            structure.setSelected(true);
7644        }
7645        if (info.isLongClickable()) {
7646            structure.setLongClickable(true);
7647        }
7648        if (info.isCheckable()) {
7649            structure.setCheckable(true);
7650            if (info.isChecked()) {
7651                structure.setChecked(true);
7652            }
7653        }
7654        if (info.isContextClickable()) {
7655            structure.setContextClickable(true);
7656        }
7657        CharSequence cname = info.getClassName();
7658        structure.setClassName(cname != null ? cname.toString() : null);
7659        structure.setContentDescription(info.getContentDescription());
7660        if (!forAutofill && (info.getText() != null || info.getError() != null)) {
7661            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7662            // just set sanitized values (like text coming from resource files), rather than not
7663            // setting it at all.
7664            structure.setText(info.getText(), info.getTextSelectionStart(),
7665                    info.getTextSelectionEnd());
7666        }
7667        final int NCHILDREN = info.getChildCount();
7668        if (NCHILDREN > 0) {
7669            structure.setChildCount(NCHILDREN);
7670            for (int i=0; i<NCHILDREN; i++) {
7671                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7672                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7673                ViewStructure child = structure.newChild(i);
7674                populateVirtualStructure(child, provider, cinfo, forAutofill);
7675                cinfo.recycle();
7676            }
7677        }
7678    }
7679
7680    /**
7681     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7682     * implementation calls {@link #onProvideStructure} and
7683     * {@link #onProvideVirtualStructure}.
7684     */
7685    public void dispatchProvideStructure(ViewStructure structure) {
7686        dispatchProvideStructureForAssistOrAutofill(structure, false);
7687    }
7688
7689    /**
7690     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7691     *
7692     * <p>The structure must be filled according to the request type, which is set in the
7693     * {@code flags} parameter - see the documentation on each flag for more details.
7694     *
7695     * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
7696     * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7697     *
7698     * @param structure Fill in with structured view data.
7699     * @param flags optional flags (currently {@code 0}).
7700     */
7701    public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
7702        dispatchProvideStructureForAssistOrAutofill(structure, true);
7703    }
7704
7705    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7706            boolean forAutofill) {
7707        boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
7708        if (!blocked) {
7709            if (forAutofill) {
7710                // The autofill id needs to be unique, but its value doesn't matter,
7711                // so it's better to reuse the accessibility id to save space.
7712                structure.setAutofillId(getAccessibilityViewId());
7713                // NOTE: flags are not currently supported, hence 0
7714                onProvideAutofillStructure(structure, 0);
7715                onProvideAutofillVirtualStructure(structure, 0);
7716            } else {
7717                onProvideStructure(structure);
7718                onProvideVirtualStructure(structure);
7719            }
7720        } else {
7721            structure.setClassName(getAccessibilityClassName().toString());
7722            structure.setAssistBlocked(true);
7723        }
7724    }
7725
7726    /**
7727     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7728     *
7729     * Note: Called from the default {@link AccessibilityDelegate}.
7730     *
7731     * @hide
7732     */
7733    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7734        if (mAttachInfo == null) {
7735            return;
7736        }
7737
7738        Rect bounds = mAttachInfo.mTmpInvalRect;
7739
7740        getDrawingRect(bounds);
7741        info.setBoundsInParent(bounds);
7742
7743        getBoundsOnScreen(bounds, true);
7744        info.setBoundsInScreen(bounds);
7745
7746        ViewParent parent = getParentForAccessibility();
7747        if (parent instanceof View) {
7748            info.setParent((View) parent);
7749        }
7750
7751        if (mID != View.NO_ID) {
7752            View rootView = getRootView();
7753            if (rootView == null) {
7754                rootView = this;
7755            }
7756
7757            View label = rootView.findLabelForView(this, mID);
7758            if (label != null) {
7759                info.setLabeledBy(label);
7760            }
7761
7762            if ((mAttachInfo.mAccessibilityFetchFlags
7763                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7764                    && Resources.resourceHasPackage(mID)) {
7765                try {
7766                    String viewId = getResources().getResourceName(mID);
7767                    info.setViewIdResourceName(viewId);
7768                } catch (Resources.NotFoundException nfe) {
7769                    /* ignore */
7770                }
7771            }
7772        }
7773
7774        if (mLabelForId != View.NO_ID) {
7775            View rootView = getRootView();
7776            if (rootView == null) {
7777                rootView = this;
7778            }
7779            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7780            if (labeled != null) {
7781                info.setLabelFor(labeled);
7782            }
7783        }
7784
7785        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7786            View rootView = getRootView();
7787            if (rootView == null) {
7788                rootView = this;
7789            }
7790            View next = rootView.findViewInsideOutShouldExist(this,
7791                    mAccessibilityTraversalBeforeId);
7792            if (next != null && next.includeForAccessibility()) {
7793                info.setTraversalBefore(next);
7794            }
7795        }
7796
7797        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7798            View rootView = getRootView();
7799            if (rootView == null) {
7800                rootView = this;
7801            }
7802            View next = rootView.findViewInsideOutShouldExist(this,
7803                    mAccessibilityTraversalAfterId);
7804            if (next != null && next.includeForAccessibility()) {
7805                info.setTraversalAfter(next);
7806            }
7807        }
7808
7809        info.setVisibleToUser(isVisibleToUser());
7810
7811        info.setImportantForAccessibility(isImportantForAccessibility());
7812        info.setPackageName(mContext.getPackageName());
7813        info.setClassName(getAccessibilityClassName());
7814        info.setContentDescription(getContentDescription());
7815
7816        info.setEnabled(isEnabled());
7817        info.setClickable(isClickable());
7818        info.setFocusable(isFocusable());
7819        info.setFocused(isFocused());
7820        info.setAccessibilityFocused(isAccessibilityFocused());
7821        info.setSelected(isSelected());
7822        info.setLongClickable(isLongClickable());
7823        info.setContextClickable(isContextClickable());
7824        info.setLiveRegion(getAccessibilityLiveRegion());
7825
7826        // TODO: These make sense only if we are in an AdapterView but all
7827        // views can be selected. Maybe from accessibility perspective
7828        // we should report as selectable view in an AdapterView.
7829        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7830        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7831
7832        if (isFocusable()) {
7833            if (isFocused()) {
7834                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7835            } else {
7836                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7837            }
7838        }
7839
7840        if (!isAccessibilityFocused()) {
7841            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7842        } else {
7843            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7844        }
7845
7846        if (isClickable() && isEnabled()) {
7847            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7848        }
7849
7850        if (isLongClickable() && isEnabled()) {
7851            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7852        }
7853
7854        if (isContextClickable() && isEnabled()) {
7855            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7856        }
7857
7858        CharSequence text = getIterableTextForAccessibility();
7859        if (text != null && text.length() > 0) {
7860            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7861
7862            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7863            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7864            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7865            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7866                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7867                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7868        }
7869
7870        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7871        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7872    }
7873
7874    /**
7875     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7876     * additional data.
7877     * <p>
7878     * This method only needs overloading if the node is marked as having extra data available.
7879     * </p>
7880     *
7881     * @param info The info to which to add the extra data. Never {@code null}.
7882     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7883     *                     extra data should be added to the {@link Bundle} returned by
7884     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7885     *                     {@code null}.
7886     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7887     *                  {@code null} if the service provided no arguments.
7888     *
7889     * @see AccessibilityNodeInfo#setExtraAvailableData
7890     */
7891    public void addExtraDataToAccessibilityNodeInfo(
7892            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7893            @Nullable Bundle arguments) {
7894    }
7895
7896    /**
7897     * Determine the order in which this view will be drawn relative to its siblings for a11y
7898     *
7899     * @param info The info whose drawing order should be populated
7900     */
7901    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7902        /*
7903         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7904         * drawing order may not be well-defined, and some Views with custom drawing order may
7905         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7906         */
7907        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7908            info.setDrawingOrder(0);
7909            return;
7910        }
7911        int drawingOrderInParent = 1;
7912        // Iterate up the hierarchy if parents are not important for a11y
7913        View viewAtDrawingLevel = this;
7914        final ViewParent parent = getParentForAccessibility();
7915        while (viewAtDrawingLevel != parent) {
7916            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7917            if (!(currentParent instanceof ViewGroup)) {
7918                // Should only happen for the Decor
7919                drawingOrderInParent = 0;
7920                break;
7921            } else {
7922                final ViewGroup parentGroup = (ViewGroup) currentParent;
7923                final int childCount = parentGroup.getChildCount();
7924                if (childCount > 1) {
7925                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7926                    if (preorderedList != null) {
7927                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7928                        for (int i = 0; i < childDrawIndex; i++) {
7929                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7930                        }
7931                    } else {
7932                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7933                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7934                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7935                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7936                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7937                        if (childDrawIndex != 0) {
7938                            for (int i = 0; i < numChildrenToIterate; i++) {
7939                                final int otherDrawIndex = (customOrder ?
7940                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7941                                if (otherDrawIndex < childDrawIndex) {
7942                                    drawingOrderInParent +=
7943                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7944                                }
7945                            }
7946                        }
7947                    }
7948                }
7949            }
7950            viewAtDrawingLevel = (View) currentParent;
7951        }
7952        info.setDrawingOrder(drawingOrderInParent);
7953    }
7954
7955    private static int numViewsForAccessibility(View view) {
7956        if (view != null) {
7957            if (view.includeForAccessibility()) {
7958                return 1;
7959            } else if (view instanceof ViewGroup) {
7960                return ((ViewGroup) view).getNumChildrenForAccessibility();
7961            }
7962        }
7963        return 0;
7964    }
7965
7966    private View findLabelForView(View view, int labeledId) {
7967        if (mMatchLabelForPredicate == null) {
7968            mMatchLabelForPredicate = new MatchLabelForPredicate();
7969        }
7970        mMatchLabelForPredicate.mLabeledId = labeledId;
7971        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7972    }
7973
7974    /**
7975     * Computes whether this view is visible to the user. Such a view is
7976     * attached, visible, all its predecessors are visible, it is not clipped
7977     * entirely by its predecessors, and has an alpha greater than zero.
7978     *
7979     * @return Whether the view is visible on the screen.
7980     *
7981     * @hide
7982     */
7983    protected boolean isVisibleToUser() {
7984        return isVisibleToUser(null);
7985    }
7986
7987    /**
7988     * Computes whether the given portion of this view is visible to the user.
7989     * Such a view is attached, visible, all its predecessors are visible,
7990     * has an alpha greater than zero, and the specified portion is not
7991     * clipped entirely by its predecessors.
7992     *
7993     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7994     *                    <code>null</code>, and the entire view will be tested in this case.
7995     *                    When <code>true</code> is returned by the function, the actual visible
7996     *                    region will be stored in this parameter; that is, if boundInView is fully
7997     *                    contained within the view, no modification will be made, otherwise regions
7998     *                    outside of the visible area of the view will be clipped.
7999     *
8000     * @return Whether the specified portion of the view is visible on the screen.
8001     *
8002     * @hide
8003     */
8004    protected boolean isVisibleToUser(Rect boundInView) {
8005        if (mAttachInfo != null) {
8006            // Attached to invisible window means this view is not visible.
8007            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8008                return false;
8009            }
8010            // An invisible predecessor or one with alpha zero means
8011            // that this view is not visible to the user.
8012            Object current = this;
8013            while (current instanceof View) {
8014                View view = (View) current;
8015                // We have attach info so this view is attached and there is no
8016                // need to check whether we reach to ViewRootImpl on the way up.
8017                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8018                        view.getVisibility() != VISIBLE) {
8019                    return false;
8020                }
8021                current = view.mParent;
8022            }
8023            // Check if the view is entirely covered by its predecessors.
8024            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8025            Point offset = mAttachInfo.mPoint;
8026            if (!getGlobalVisibleRect(visibleRect, offset)) {
8027                return false;
8028            }
8029            // Check if the visible portion intersects the rectangle of interest.
8030            if (boundInView != null) {
8031                visibleRect.offset(-offset.x, -offset.y);
8032                return boundInView.intersect(visibleRect);
8033            }
8034            return true;
8035        }
8036        return false;
8037    }
8038
8039    /**
8040     * Returns the delegate for implementing accessibility support via
8041     * composition. For more details see {@link AccessibilityDelegate}.
8042     *
8043     * @return The delegate, or null if none set.
8044     *
8045     * @hide
8046     */
8047    public AccessibilityDelegate getAccessibilityDelegate() {
8048        return mAccessibilityDelegate;
8049    }
8050
8051    /**
8052     * Sets a delegate for implementing accessibility support via composition
8053     * (as opposed to inheritance). For more details, see
8054     * {@link AccessibilityDelegate}.
8055     * <p>
8056     * <strong>Note:</strong> On platform versions prior to
8057     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8058     * views in the {@code android.widget.*} package are called <i>before</i>
8059     * host methods. This prevents certain properties such as class name from
8060     * being modified by overriding
8061     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8062     * as any changes will be overwritten by the host class.
8063     * <p>
8064     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8065     * methods are called <i>after</i> host methods, which all properties to be
8066     * modified without being overwritten by the host class.
8067     *
8068     * @param delegate the object to which accessibility method calls should be
8069     *                 delegated
8070     * @see AccessibilityDelegate
8071     */
8072    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8073        mAccessibilityDelegate = delegate;
8074    }
8075
8076    /**
8077     * Gets the provider for managing a virtual view hierarchy rooted at this View
8078     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8079     * that explore the window content.
8080     * <p>
8081     * If this method returns an instance, this instance is responsible for managing
8082     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8083     * View including the one representing the View itself. Similarly the returned
8084     * instance is responsible for performing accessibility actions on any virtual
8085     * view or the root view itself.
8086     * </p>
8087     * <p>
8088     * If an {@link AccessibilityDelegate} has been specified via calling
8089     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8090     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8091     * is responsible for handling this call.
8092     * </p>
8093     *
8094     * @return The provider.
8095     *
8096     * @see AccessibilityNodeProvider
8097     */
8098    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8099        if (mAccessibilityDelegate != null) {
8100            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8101        } else {
8102            return null;
8103        }
8104    }
8105
8106    /**
8107     * Gets the unique identifier of this view on the screen for accessibility purposes.
8108     *
8109     * @return The view accessibility id.
8110     *
8111     * @hide
8112     */
8113    public int getAccessibilityViewId() {
8114        if (mAccessibilityViewId == NO_ID) {
8115            mAccessibilityViewId = sNextAccessibilityViewId++;
8116        }
8117        return mAccessibilityViewId;
8118    }
8119
8120    /**
8121     * Gets the unique identifier of the window in which this View reseides.
8122     *
8123     * @return The window accessibility id.
8124     *
8125     * @hide
8126     */
8127    public int getAccessibilityWindowId() {
8128        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8129                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8130    }
8131
8132    /**
8133     * Returns the {@link View}'s content description.
8134     * <p>
8135     * <strong>Note:</strong> Do not override this method, as it will have no
8136     * effect on the content description presented to accessibility services.
8137     * You must call {@link #setContentDescription(CharSequence)} to modify the
8138     * content description.
8139     *
8140     * @return the content description
8141     * @see #setContentDescription(CharSequence)
8142     * @attr ref android.R.styleable#View_contentDescription
8143     */
8144    @ViewDebug.ExportedProperty(category = "accessibility")
8145    public CharSequence getContentDescription() {
8146        return mContentDescription;
8147    }
8148
8149    /**
8150     * Sets the {@link View}'s content description.
8151     * <p>
8152     * A content description briefly describes the view and is primarily used
8153     * for accessibility support to determine how a view should be presented to
8154     * the user. In the case of a view with no textual representation, such as
8155     * {@link android.widget.ImageButton}, a useful content description
8156     * explains what the view does. For example, an image button with a phone
8157     * icon that is used to place a call may use "Call" as its content
8158     * description. An image of a floppy disk that is used to save a file may
8159     * use "Save".
8160     *
8161     * @param contentDescription The content description.
8162     * @see #getContentDescription()
8163     * @attr ref android.R.styleable#View_contentDescription
8164     */
8165    @RemotableViewMethod
8166    public void setContentDescription(CharSequence contentDescription) {
8167        if (mContentDescription == null) {
8168            if (contentDescription == null) {
8169                return;
8170            }
8171        } else if (mContentDescription.equals(contentDescription)) {
8172            return;
8173        }
8174        mContentDescription = contentDescription;
8175        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8176        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8177            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8178            notifySubtreeAccessibilityStateChangedIfNeeded();
8179        } else {
8180            notifyViewAccessibilityStateChangedIfNeeded(
8181                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8182        }
8183    }
8184
8185    /**
8186     * Sets the id of a view before which this one is visited in accessibility traversal.
8187     * A screen-reader must visit the content of this view before the content of the one
8188     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8189     * will traverse the entire content of B before traversing the entire content of A,
8190     * regardles of what traversal strategy it is using.
8191     * <p>
8192     * Views that do not have specified before/after relationships are traversed in order
8193     * determined by the screen-reader.
8194     * </p>
8195     * <p>
8196     * Setting that this view is before a view that is not important for accessibility
8197     * or if this view is not important for accessibility will have no effect as the
8198     * screen-reader is not aware of unimportant views.
8199     * </p>
8200     *
8201     * @param beforeId The id of a view this one precedes in accessibility traversal.
8202     *
8203     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8204     *
8205     * @see #setImportantForAccessibility(int)
8206     */
8207    @RemotableViewMethod
8208    public void setAccessibilityTraversalBefore(int beforeId) {
8209        if (mAccessibilityTraversalBeforeId == beforeId) {
8210            return;
8211        }
8212        mAccessibilityTraversalBeforeId = beforeId;
8213        notifyViewAccessibilityStateChangedIfNeeded(
8214                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8215    }
8216
8217    /**
8218     * Gets the id of a view before which this one is visited in accessibility traversal.
8219     *
8220     * @return The id of a view this one precedes in accessibility traversal if
8221     *         specified, otherwise {@link #NO_ID}.
8222     *
8223     * @see #setAccessibilityTraversalBefore(int)
8224     */
8225    public int getAccessibilityTraversalBefore() {
8226        return mAccessibilityTraversalBeforeId;
8227    }
8228
8229    /**
8230     * Sets the id of a view after which this one is visited in accessibility traversal.
8231     * A screen-reader must visit the content of the other view before the content of this
8232     * one. For example, if view B is set to be after view A, then a screen-reader
8233     * will traverse the entire content of A before traversing the entire content of B,
8234     * regardles of what traversal strategy it is using.
8235     * <p>
8236     * Views that do not have specified before/after relationships are traversed in order
8237     * determined by the screen-reader.
8238     * </p>
8239     * <p>
8240     * Setting that this view is after a view that is not important for accessibility
8241     * or if this view is not important for accessibility will have no effect as the
8242     * screen-reader is not aware of unimportant views.
8243     * </p>
8244     *
8245     * @param afterId The id of a view this one succedees in accessibility traversal.
8246     *
8247     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8248     *
8249     * @see #setImportantForAccessibility(int)
8250     */
8251    @RemotableViewMethod
8252    public void setAccessibilityTraversalAfter(int afterId) {
8253        if (mAccessibilityTraversalAfterId == afterId) {
8254            return;
8255        }
8256        mAccessibilityTraversalAfterId = afterId;
8257        notifyViewAccessibilityStateChangedIfNeeded(
8258                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8259    }
8260
8261    /**
8262     * Gets the id of a view after which this one is visited in accessibility traversal.
8263     *
8264     * @return The id of a view this one succeedes in accessibility traversal if
8265     *         specified, otherwise {@link #NO_ID}.
8266     *
8267     * @see #setAccessibilityTraversalAfter(int)
8268     */
8269    public int getAccessibilityTraversalAfter() {
8270        return mAccessibilityTraversalAfterId;
8271    }
8272
8273    /**
8274     * Gets the id of a view for which this view serves as a label for
8275     * accessibility purposes.
8276     *
8277     * @return The labeled view id.
8278     */
8279    @ViewDebug.ExportedProperty(category = "accessibility")
8280    public int getLabelFor() {
8281        return mLabelForId;
8282    }
8283
8284    /**
8285     * Sets the id of a view for which this view serves as a label for
8286     * accessibility purposes.
8287     *
8288     * @param id The labeled view id.
8289     */
8290    @RemotableViewMethod
8291    public void setLabelFor(@IdRes int id) {
8292        if (mLabelForId == id) {
8293            return;
8294        }
8295        mLabelForId = id;
8296        if (mLabelForId != View.NO_ID
8297                && mID == View.NO_ID) {
8298            mID = generateViewId();
8299        }
8300        notifyViewAccessibilityStateChangedIfNeeded(
8301                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8302    }
8303
8304    /**
8305     * Invoked whenever this view loses focus, either by losing window focus or by losing
8306     * focus within its window. This method can be used to clear any state tied to the
8307     * focus. For instance, if a button is held pressed with the trackball and the window
8308     * loses focus, this method can be used to cancel the press.
8309     *
8310     * Subclasses of View overriding this method should always call super.onFocusLost().
8311     *
8312     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8313     * @see #onWindowFocusChanged(boolean)
8314     *
8315     * @hide pending API council approval
8316     */
8317    @CallSuper
8318    protected void onFocusLost() {
8319        resetPressedState();
8320    }
8321
8322    private void resetPressedState() {
8323        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8324            return;
8325        }
8326
8327        if (isPressed()) {
8328            setPressed(false);
8329
8330            if (!mHasPerformedLongPress) {
8331                removeLongPressCallback();
8332            }
8333        }
8334    }
8335
8336    /**
8337     * Returns true if this view has focus
8338     *
8339     * @return True if this view has focus, false otherwise.
8340     */
8341    @ViewDebug.ExportedProperty(category = "focus")
8342    public boolean isFocused() {
8343        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8344    }
8345
8346    /**
8347     * Find the view in the hierarchy rooted at this view that currently has
8348     * focus.
8349     *
8350     * @return The view that currently has focus, or null if no focused view can
8351     *         be found.
8352     */
8353    public View findFocus() {
8354        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8355    }
8356
8357    /**
8358     * Indicates whether this view is one of the set of scrollable containers in
8359     * its window.
8360     *
8361     * @return whether this view is one of the set of scrollable containers in
8362     * its window
8363     *
8364     * @attr ref android.R.styleable#View_isScrollContainer
8365     */
8366    public boolean isScrollContainer() {
8367        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8368    }
8369
8370    /**
8371     * Change whether this view is one of the set of scrollable containers in
8372     * its window.  This will be used to determine whether the window can
8373     * resize or must pan when a soft input area is open -- scrollable
8374     * containers allow the window to use resize mode since the container
8375     * will appropriately shrink.
8376     *
8377     * @attr ref android.R.styleable#View_isScrollContainer
8378     */
8379    public void setScrollContainer(boolean isScrollContainer) {
8380        if (isScrollContainer) {
8381            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8382                mAttachInfo.mScrollContainers.add(this);
8383                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8384            }
8385            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8386        } else {
8387            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8388                mAttachInfo.mScrollContainers.remove(this);
8389            }
8390            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8391        }
8392    }
8393
8394    /**
8395     * Returns the quality of the drawing cache.
8396     *
8397     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8398     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8399     *
8400     * @see #setDrawingCacheQuality(int)
8401     * @see #setDrawingCacheEnabled(boolean)
8402     * @see #isDrawingCacheEnabled()
8403     *
8404     * @attr ref android.R.styleable#View_drawingCacheQuality
8405     */
8406    @DrawingCacheQuality
8407    public int getDrawingCacheQuality() {
8408        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8409    }
8410
8411    /**
8412     * Set the drawing cache quality of this view. This value is used only when the
8413     * drawing cache is enabled
8414     *
8415     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8416     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8417     *
8418     * @see #getDrawingCacheQuality()
8419     * @see #setDrawingCacheEnabled(boolean)
8420     * @see #isDrawingCacheEnabled()
8421     *
8422     * @attr ref android.R.styleable#View_drawingCacheQuality
8423     */
8424    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8425        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8426    }
8427
8428    /**
8429     * Returns whether the screen should remain on, corresponding to the current
8430     * value of {@link #KEEP_SCREEN_ON}.
8431     *
8432     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8433     *
8434     * @see #setKeepScreenOn(boolean)
8435     *
8436     * @attr ref android.R.styleable#View_keepScreenOn
8437     */
8438    public boolean getKeepScreenOn() {
8439        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8440    }
8441
8442    /**
8443     * Controls whether the screen should remain on, modifying the
8444     * value of {@link #KEEP_SCREEN_ON}.
8445     *
8446     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8447     *
8448     * @see #getKeepScreenOn()
8449     *
8450     * @attr ref android.R.styleable#View_keepScreenOn
8451     */
8452    public void setKeepScreenOn(boolean keepScreenOn) {
8453        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8454    }
8455
8456    /**
8457     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8458     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8459     *
8460     * @attr ref android.R.styleable#View_nextFocusLeft
8461     */
8462    public int getNextFocusLeftId() {
8463        return mNextFocusLeftId;
8464    }
8465
8466    /**
8467     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8468     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8469     * decide automatically.
8470     *
8471     * @attr ref android.R.styleable#View_nextFocusLeft
8472     */
8473    public void setNextFocusLeftId(int nextFocusLeftId) {
8474        mNextFocusLeftId = nextFocusLeftId;
8475    }
8476
8477    /**
8478     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8479     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8480     *
8481     * @attr ref android.R.styleable#View_nextFocusRight
8482     */
8483    public int getNextFocusRightId() {
8484        return mNextFocusRightId;
8485    }
8486
8487    /**
8488     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8489     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8490     * decide automatically.
8491     *
8492     * @attr ref android.R.styleable#View_nextFocusRight
8493     */
8494    public void setNextFocusRightId(int nextFocusRightId) {
8495        mNextFocusRightId = nextFocusRightId;
8496    }
8497
8498    /**
8499     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8500     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8501     *
8502     * @attr ref android.R.styleable#View_nextFocusUp
8503     */
8504    public int getNextFocusUpId() {
8505        return mNextFocusUpId;
8506    }
8507
8508    /**
8509     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8510     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8511     * decide automatically.
8512     *
8513     * @attr ref android.R.styleable#View_nextFocusUp
8514     */
8515    public void setNextFocusUpId(int nextFocusUpId) {
8516        mNextFocusUpId = nextFocusUpId;
8517    }
8518
8519    /**
8520     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8521     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8522     *
8523     * @attr ref android.R.styleable#View_nextFocusDown
8524     */
8525    public int getNextFocusDownId() {
8526        return mNextFocusDownId;
8527    }
8528
8529    /**
8530     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8531     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8532     * decide automatically.
8533     *
8534     * @attr ref android.R.styleable#View_nextFocusDown
8535     */
8536    public void setNextFocusDownId(int nextFocusDownId) {
8537        mNextFocusDownId = nextFocusDownId;
8538    }
8539
8540    /**
8541     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8542     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8543     *
8544     * @attr ref android.R.styleable#View_nextFocusForward
8545     */
8546    public int getNextFocusForwardId() {
8547        return mNextFocusForwardId;
8548    }
8549
8550    /**
8551     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8552     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8553     * decide automatically.
8554     *
8555     * @attr ref android.R.styleable#View_nextFocusForward
8556     */
8557    public void setNextFocusForwardId(int nextFocusForwardId) {
8558        mNextFocusForwardId = nextFocusForwardId;
8559    }
8560
8561    /**
8562     * Gets the id of the root of the next keyboard navigation cluster.
8563     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8564     * decide automatically.
8565     *
8566     * @attr ref android.R.styleable#View_nextClusterForward
8567     */
8568    public int getNextClusterForwardId() {
8569        return mNextClusterForwardId;
8570    }
8571
8572    /**
8573     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8574     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8575     * decide automatically.
8576     *
8577     * @attr ref android.R.styleable#View_nextClusterForward
8578     */
8579    public void setNextClusterForwardId(int nextClusterForwardId) {
8580        mNextClusterForwardId = nextClusterForwardId;
8581    }
8582
8583    /**
8584     * Returns the visibility of this view and all of its ancestors
8585     *
8586     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8587     */
8588    public boolean isShown() {
8589        View current = this;
8590        //noinspection ConstantConditions
8591        do {
8592            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8593                return false;
8594            }
8595            ViewParent parent = current.mParent;
8596            if (parent == null) {
8597                return false; // We are not attached to the view root
8598            }
8599            if (!(parent instanceof View)) {
8600                return true;
8601            }
8602            current = (View) parent;
8603        } while (current != null);
8604
8605        return false;
8606    }
8607
8608    /**
8609     * Called by the view hierarchy when the content insets for a window have
8610     * changed, to allow it to adjust its content to fit within those windows.
8611     * The content insets tell you the space that the status bar, input method,
8612     * and other system windows infringe on the application's window.
8613     *
8614     * <p>You do not normally need to deal with this function, since the default
8615     * window decoration given to applications takes care of applying it to the
8616     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8617     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8618     * and your content can be placed under those system elements.  You can then
8619     * use this method within your view hierarchy if you have parts of your UI
8620     * which you would like to ensure are not being covered.
8621     *
8622     * <p>The default implementation of this method simply applies the content
8623     * insets to the view's padding, consuming that content (modifying the
8624     * insets to be 0), and returning true.  This behavior is off by default, but can
8625     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8626     *
8627     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8628     * insets object is propagated down the hierarchy, so any changes made to it will
8629     * be seen by all following views (including potentially ones above in
8630     * the hierarchy since this is a depth-first traversal).  The first view
8631     * that returns true will abort the entire traversal.
8632     *
8633     * <p>The default implementation works well for a situation where it is
8634     * used with a container that covers the entire window, allowing it to
8635     * apply the appropriate insets to its content on all edges.  If you need
8636     * a more complicated layout (such as two different views fitting system
8637     * windows, one on the top of the window, and one on the bottom),
8638     * you can override the method and handle the insets however you would like.
8639     * Note that the insets provided by the framework are always relative to the
8640     * far edges of the window, not accounting for the location of the called view
8641     * within that window.  (In fact when this method is called you do not yet know
8642     * where the layout will place the view, as it is done before layout happens.)
8643     *
8644     * <p>Note: unlike many View methods, there is no dispatch phase to this
8645     * call.  If you are overriding it in a ViewGroup and want to allow the
8646     * call to continue to your children, you must be sure to call the super
8647     * implementation.
8648     *
8649     * <p>Here is a sample layout that makes use of fitting system windows
8650     * to have controls for a video view placed inside of the window decorations
8651     * that it hides and shows.  This can be used with code like the second
8652     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8653     *
8654     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8655     *
8656     * @param insets Current content insets of the window.  Prior to
8657     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8658     * the insets or else you and Android will be unhappy.
8659     *
8660     * @return {@code true} if this view applied the insets and it should not
8661     * continue propagating further down the hierarchy, {@code false} otherwise.
8662     * @see #getFitsSystemWindows()
8663     * @see #setFitsSystemWindows(boolean)
8664     * @see #setSystemUiVisibility(int)
8665     *
8666     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8667     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8668     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8669     * to implement handling their own insets.
8670     */
8671    @Deprecated
8672    protected boolean fitSystemWindows(Rect insets) {
8673        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8674            if (insets == null) {
8675                // Null insets by definition have already been consumed.
8676                // This call cannot apply insets since there are none to apply,
8677                // so return false.
8678                return false;
8679            }
8680            // If we're not in the process of dispatching the newer apply insets call,
8681            // that means we're not in the compatibility path. Dispatch into the newer
8682            // apply insets path and take things from there.
8683            try {
8684                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8685                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8686            } finally {
8687                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8688            }
8689        } else {
8690            // We're being called from the newer apply insets path.
8691            // Perform the standard fallback behavior.
8692            return fitSystemWindowsInt(insets);
8693        }
8694    }
8695
8696    private boolean fitSystemWindowsInt(Rect insets) {
8697        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8698            mUserPaddingStart = UNDEFINED_PADDING;
8699            mUserPaddingEnd = UNDEFINED_PADDING;
8700            Rect localInsets = sThreadLocal.get();
8701            if (localInsets == null) {
8702                localInsets = new Rect();
8703                sThreadLocal.set(localInsets);
8704            }
8705            boolean res = computeFitSystemWindows(insets, localInsets);
8706            mUserPaddingLeftInitial = localInsets.left;
8707            mUserPaddingRightInitial = localInsets.right;
8708            internalSetPadding(localInsets.left, localInsets.top,
8709                    localInsets.right, localInsets.bottom);
8710            return res;
8711        }
8712        return false;
8713    }
8714
8715    /**
8716     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8717     *
8718     * <p>This method should be overridden by views that wish to apply a policy different from or
8719     * in addition to the default behavior. Clients that wish to force a view subtree
8720     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8721     *
8722     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8723     * it will be called during dispatch instead of this method. The listener may optionally
8724     * call this method from its own implementation if it wishes to apply the view's default
8725     * insets policy in addition to its own.</p>
8726     *
8727     * <p>Implementations of this method should either return the insets parameter unchanged
8728     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8729     * that this view applied itself. This allows new inset types added in future platform
8730     * versions to pass through existing implementations unchanged without being erroneously
8731     * consumed.</p>
8732     *
8733     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8734     * property is set then the view will consume the system window insets and apply them
8735     * as padding for the view.</p>
8736     *
8737     * @param insets Insets to apply
8738     * @return The supplied insets with any applied insets consumed
8739     */
8740    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8741        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8742            // We weren't called from within a direct call to fitSystemWindows,
8743            // call into it as a fallback in case we're in a class that overrides it
8744            // and has logic to perform.
8745            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8746                return insets.consumeSystemWindowInsets();
8747            }
8748        } else {
8749            // We were called from within a direct call to fitSystemWindows.
8750            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8751                return insets.consumeSystemWindowInsets();
8752            }
8753        }
8754        return insets;
8755    }
8756
8757    /**
8758     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8759     * window insets to this view. The listener's
8760     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8761     * method will be called instead of the view's
8762     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8763     *
8764     * @param listener Listener to set
8765     *
8766     * @see #onApplyWindowInsets(WindowInsets)
8767     */
8768    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8769        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8770    }
8771
8772    /**
8773     * Request to apply the given window insets to this view or another view in its subtree.
8774     *
8775     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8776     * obscured by window decorations or overlays. This can include the status and navigation bars,
8777     * action bars, input methods and more. New inset categories may be added in the future.
8778     * The method returns the insets provided minus any that were applied by this view or its
8779     * children.</p>
8780     *
8781     * <p>Clients wishing to provide custom behavior should override the
8782     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8783     * {@link OnApplyWindowInsetsListener} via the
8784     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8785     * method.</p>
8786     *
8787     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8788     * </p>
8789     *
8790     * @param insets Insets to apply
8791     * @return The provided insets minus the insets that were consumed
8792     */
8793    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8794        try {
8795            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8796            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8797                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8798            } else {
8799                return onApplyWindowInsets(insets);
8800            }
8801        } finally {
8802            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8803        }
8804    }
8805
8806    /**
8807     * Compute the view's coordinate within the surface.
8808     *
8809     * <p>Computes the coordinates of this view in its surface. The argument
8810     * must be an array of two integers. After the method returns, the array
8811     * contains the x and y location in that order.</p>
8812     * @hide
8813     * @param location an array of two integers in which to hold the coordinates
8814     */
8815    public void getLocationInSurface(@Size(2) int[] location) {
8816        getLocationInWindow(location);
8817        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8818            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8819            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8820        }
8821    }
8822
8823    /**
8824     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8825     * only available if the view is attached.
8826     *
8827     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8828     */
8829    public WindowInsets getRootWindowInsets() {
8830        if (mAttachInfo != null) {
8831            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8832        }
8833        return null;
8834    }
8835
8836    /**
8837     * @hide Compute the insets that should be consumed by this view and the ones
8838     * that should propagate to those under it.
8839     */
8840    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8841        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8842                || mAttachInfo == null
8843                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8844                        && !mAttachInfo.mOverscanRequested)) {
8845            outLocalInsets.set(inoutInsets);
8846            inoutInsets.set(0, 0, 0, 0);
8847            return true;
8848        } else {
8849            // The application wants to take care of fitting system window for
8850            // the content...  however we still need to take care of any overscan here.
8851            final Rect overscan = mAttachInfo.mOverscanInsets;
8852            outLocalInsets.set(overscan);
8853            inoutInsets.left -= overscan.left;
8854            inoutInsets.top -= overscan.top;
8855            inoutInsets.right -= overscan.right;
8856            inoutInsets.bottom -= overscan.bottom;
8857            return false;
8858        }
8859    }
8860
8861    /**
8862     * Compute insets that should be consumed by this view and the ones that should propagate
8863     * to those under it.
8864     *
8865     * @param in Insets currently being processed by this View, likely received as a parameter
8866     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8867     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8868     *                       by this view
8869     * @return Insets that should be passed along to views under this one
8870     */
8871    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8872        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8873                || mAttachInfo == null
8874                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8875            outLocalInsets.set(in.getSystemWindowInsets());
8876            return in.consumeSystemWindowInsets();
8877        } else {
8878            outLocalInsets.set(0, 0, 0, 0);
8879            return in;
8880        }
8881    }
8882
8883    /**
8884     * Sets whether or not this view should account for system screen decorations
8885     * such as the status bar and inset its content; that is, controlling whether
8886     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8887     * executed.  See that method for more details.
8888     *
8889     * <p>Note that if you are providing your own implementation of
8890     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8891     * flag to true -- your implementation will be overriding the default
8892     * implementation that checks this flag.
8893     *
8894     * @param fitSystemWindows If true, then the default implementation of
8895     * {@link #fitSystemWindows(Rect)} will be executed.
8896     *
8897     * @attr ref android.R.styleable#View_fitsSystemWindows
8898     * @see #getFitsSystemWindows()
8899     * @see #fitSystemWindows(Rect)
8900     * @see #setSystemUiVisibility(int)
8901     */
8902    public void setFitsSystemWindows(boolean fitSystemWindows) {
8903        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8904    }
8905
8906    /**
8907     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8908     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8909     * will be executed.
8910     *
8911     * @return {@code true} if the default implementation of
8912     * {@link #fitSystemWindows(Rect)} will be executed.
8913     *
8914     * @attr ref android.R.styleable#View_fitsSystemWindows
8915     * @see #setFitsSystemWindows(boolean)
8916     * @see #fitSystemWindows(Rect)
8917     * @see #setSystemUiVisibility(int)
8918     */
8919    @ViewDebug.ExportedProperty
8920    public boolean getFitsSystemWindows() {
8921        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8922    }
8923
8924    /** @hide */
8925    public boolean fitsSystemWindows() {
8926        return getFitsSystemWindows();
8927    }
8928
8929    /**
8930     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8931     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8932     */
8933    @Deprecated
8934    public void requestFitSystemWindows() {
8935        if (mParent != null) {
8936            mParent.requestFitSystemWindows();
8937        }
8938    }
8939
8940    /**
8941     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8942     */
8943    public void requestApplyInsets() {
8944        requestFitSystemWindows();
8945    }
8946
8947    /**
8948     * For use by PhoneWindow to make its own system window fitting optional.
8949     * @hide
8950     */
8951    public void makeOptionalFitsSystemWindows() {
8952        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8953    }
8954
8955    /**
8956     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8957     * treat them as such.
8958     * @hide
8959     */
8960    public void getOutsets(Rect outOutsetRect) {
8961        if (mAttachInfo != null) {
8962            outOutsetRect.set(mAttachInfo.mOutsets);
8963        } else {
8964            outOutsetRect.setEmpty();
8965        }
8966    }
8967
8968    /**
8969     * Returns the visibility status for this view.
8970     *
8971     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8972     * @attr ref android.R.styleable#View_visibility
8973     */
8974    @ViewDebug.ExportedProperty(mapping = {
8975        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8976        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8977        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8978    })
8979    @Visibility
8980    public int getVisibility() {
8981        return mViewFlags & VISIBILITY_MASK;
8982    }
8983
8984    /**
8985     * Set the visibility state of this view.
8986     *
8987     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8988     * @attr ref android.R.styleable#View_visibility
8989     */
8990    @RemotableViewMethod
8991    public void setVisibility(@Visibility int visibility) {
8992        setFlags(visibility, VISIBILITY_MASK);
8993    }
8994
8995    /**
8996     * Returns the enabled status for this view. The interpretation of the
8997     * enabled state varies by subclass.
8998     *
8999     * @return True if this view is enabled, false otherwise.
9000     */
9001    @ViewDebug.ExportedProperty
9002    public boolean isEnabled() {
9003        return (mViewFlags & ENABLED_MASK) == ENABLED;
9004    }
9005
9006    /**
9007     * Set the enabled state of this view. The interpretation of the enabled
9008     * state varies by subclass.
9009     *
9010     * @param enabled True if this view is enabled, false otherwise.
9011     */
9012    @RemotableViewMethod
9013    public void setEnabled(boolean enabled) {
9014        if (enabled == isEnabled()) return;
9015
9016        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9017
9018        /*
9019         * The View most likely has to change its appearance, so refresh
9020         * the drawable state.
9021         */
9022        refreshDrawableState();
9023
9024        // Invalidate too, since the default behavior for views is to be
9025        // be drawn at 50% alpha rather than to change the drawable.
9026        invalidate(true);
9027
9028        if (!enabled) {
9029            cancelPendingInputEvents();
9030        }
9031    }
9032
9033    /**
9034     * Set whether this view can receive the focus.
9035     * <p>
9036     * Setting this to false will also ensure that this view is not focusable
9037     * in touch mode.
9038     *
9039     * @param focusable If true, this view can receive the focus.
9040     *
9041     * @see #setFocusableInTouchMode(boolean)
9042     * @see #setFocusable(int)
9043     * @attr ref android.R.styleable#View_focusable
9044     */
9045    public void setFocusable(boolean focusable) {
9046        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9047    }
9048
9049    /**
9050     * Sets whether this view can receive focus.
9051     * <p>
9052     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9053     * automatically based on the view's interactivity. This is the default.
9054     * <p>
9055     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9056     * in touch mode.
9057     *
9058     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9059     *                  or {@link #FOCUSABLE_AUTO}.
9060     * @see #setFocusableInTouchMode(boolean)
9061     * @attr ref android.R.styleable#View_focusable
9062     */
9063    public void setFocusable(@Focusable int focusable) {
9064        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9065            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9066        }
9067        setFlags(focusable, FOCUSABLE_MASK);
9068    }
9069
9070    /**
9071     * Set whether this view can receive focus while in touch mode.
9072     *
9073     * Setting this to true will also ensure that this view is focusable.
9074     *
9075     * @param focusableInTouchMode If true, this view can receive the focus while
9076     *   in touch mode.
9077     *
9078     * @see #setFocusable(boolean)
9079     * @attr ref android.R.styleable#View_focusableInTouchMode
9080     */
9081    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9082        // Focusable in touch mode should always be set before the focusable flag
9083        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9084        // which, in touch mode, will not successfully request focus on this view
9085        // because the focusable in touch mode flag is not set
9086        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9087
9088        // Clear FOCUSABLE_AUTO if set.
9089        if (focusableInTouchMode) {
9090            // Clears FOCUSABLE_AUTO if set.
9091            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9092        }
9093    }
9094
9095    /**
9096     * Set autofill mode for the view.
9097     *
9098     * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
9099     *                     or {@link #AUTOFILL_MODE_MANUAL}.
9100     * @attr ref android.R.styleable#View_autofillMode
9101     */
9102    public void setAutofillMode(@AutofillMode int autofillMode) {
9103        Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
9104                AUTOFILL_MODE_MANUAL, "autofillMode");
9105
9106        mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
9107        mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
9108    }
9109
9110    /**
9111     * Sets the a hint that helps the autofill service to select the appropriate data to fill the
9112     * view.
9113     *
9114     * @param autofillHint The autofill hint to set. If the array is emtpy, {@code null} is set.
9115     * @attr ref android.R.styleable#View_autofillHint
9116     */
9117    public void setAutofillHint(@Nullable String... autofillHint) {
9118        if (autofillHint == null || autofillHint.length == 0) {
9119            mAutofillHint = null;
9120        } else {
9121            mAutofillHint = autofillHint;
9122        }
9123    }
9124
9125    /**
9126     * Set whether this view should have sound effects enabled for events such as
9127     * clicking and touching.
9128     *
9129     * <p>You may wish to disable sound effects for a view if you already play sounds,
9130     * for instance, a dial key that plays dtmf tones.
9131     *
9132     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9133     * @see #isSoundEffectsEnabled()
9134     * @see #playSoundEffect(int)
9135     * @attr ref android.R.styleable#View_soundEffectsEnabled
9136     */
9137    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9138        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9139    }
9140
9141    /**
9142     * @return whether this view should have sound effects enabled for events such as
9143     *     clicking and touching.
9144     *
9145     * @see #setSoundEffectsEnabled(boolean)
9146     * @see #playSoundEffect(int)
9147     * @attr ref android.R.styleable#View_soundEffectsEnabled
9148     */
9149    @ViewDebug.ExportedProperty
9150    public boolean isSoundEffectsEnabled() {
9151        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9152    }
9153
9154    /**
9155     * Set whether this view should have haptic feedback for events such as
9156     * long presses.
9157     *
9158     * <p>You may wish to disable haptic feedback if your view already controls
9159     * its own haptic feedback.
9160     *
9161     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9162     * @see #isHapticFeedbackEnabled()
9163     * @see #performHapticFeedback(int)
9164     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9165     */
9166    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9167        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9168    }
9169
9170    /**
9171     * @return whether this view should have haptic feedback enabled for events
9172     * long presses.
9173     *
9174     * @see #setHapticFeedbackEnabled(boolean)
9175     * @see #performHapticFeedback(int)
9176     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9177     */
9178    @ViewDebug.ExportedProperty
9179    public boolean isHapticFeedbackEnabled() {
9180        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9181    }
9182
9183    /**
9184     * Returns the layout direction for this view.
9185     *
9186     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9187     *   {@link #LAYOUT_DIRECTION_RTL},
9188     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9189     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9190     *
9191     * @attr ref android.R.styleable#View_layoutDirection
9192     *
9193     * @hide
9194     */
9195    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9196        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9197        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9198        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9199        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9200    })
9201    @LayoutDir
9202    public int getRawLayoutDirection() {
9203        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9204    }
9205
9206    /**
9207     * Set the layout direction for this view. This will propagate a reset of layout direction
9208     * resolution to the view's children and resolve layout direction for this view.
9209     *
9210     * @param layoutDirection the layout direction to set. Should be one of:
9211     *
9212     * {@link #LAYOUT_DIRECTION_LTR},
9213     * {@link #LAYOUT_DIRECTION_RTL},
9214     * {@link #LAYOUT_DIRECTION_INHERIT},
9215     * {@link #LAYOUT_DIRECTION_LOCALE}.
9216     *
9217     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9218     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9219     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9220     *
9221     * @attr ref android.R.styleable#View_layoutDirection
9222     */
9223    @RemotableViewMethod
9224    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9225        if (getRawLayoutDirection() != layoutDirection) {
9226            // Reset the current layout direction and the resolved one
9227            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9228            resetRtlProperties();
9229            // Set the new layout direction (filtered)
9230            mPrivateFlags2 |=
9231                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9232            // We need to resolve all RTL properties as they all depend on layout direction
9233            resolveRtlPropertiesIfNeeded();
9234            requestLayout();
9235            invalidate(true);
9236        }
9237    }
9238
9239    /**
9240     * Returns the resolved layout direction for this view.
9241     *
9242     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9243     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9244     *
9245     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9246     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9247     *
9248     * @attr ref android.R.styleable#View_layoutDirection
9249     */
9250    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9251        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9252        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9253    })
9254    @ResolvedLayoutDir
9255    public int getLayoutDirection() {
9256        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9257        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9258            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9259            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9260        }
9261        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9262                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9263    }
9264
9265    /**
9266     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9267     * layout attribute and/or the inherited value from the parent
9268     *
9269     * @return true if the layout is right-to-left.
9270     *
9271     * @hide
9272     */
9273    @ViewDebug.ExportedProperty(category = "layout")
9274    public boolean isLayoutRtl() {
9275        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9276    }
9277
9278    /**
9279     * Indicates whether the view is currently tracking transient state that the
9280     * app should not need to concern itself with saving and restoring, but that
9281     * the framework should take special note to preserve when possible.
9282     *
9283     * <p>A view with transient state cannot be trivially rebound from an external
9284     * data source, such as an adapter binding item views in a list. This may be
9285     * because the view is performing an animation, tracking user selection
9286     * of content, or similar.</p>
9287     *
9288     * @return true if the view has transient state
9289     */
9290    @ViewDebug.ExportedProperty(category = "layout")
9291    public boolean hasTransientState() {
9292        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9293    }
9294
9295    /**
9296     * Set whether this view is currently tracking transient state that the
9297     * framework should attempt to preserve when possible. This flag is reference counted,
9298     * so every call to setHasTransientState(true) should be paired with a later call
9299     * to setHasTransientState(false).
9300     *
9301     * <p>A view with transient state cannot be trivially rebound from an external
9302     * data source, such as an adapter binding item views in a list. This may be
9303     * because the view is performing an animation, tracking user selection
9304     * of content, or similar.</p>
9305     *
9306     * @param hasTransientState true if this view has transient state
9307     */
9308    public void setHasTransientState(boolean hasTransientState) {
9309        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9310                mTransientStateCount - 1;
9311        if (mTransientStateCount < 0) {
9312            mTransientStateCount = 0;
9313            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9314                    "unmatched pair of setHasTransientState calls");
9315        } else if ((hasTransientState && mTransientStateCount == 1) ||
9316                (!hasTransientState && mTransientStateCount == 0)) {
9317            // update flag if we've just incremented up from 0 or decremented down to 0
9318            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9319                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9320            if (mParent != null) {
9321                try {
9322                    mParent.childHasTransientStateChanged(this, hasTransientState);
9323                } catch (AbstractMethodError e) {
9324                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9325                            " does not fully implement ViewParent", e);
9326                }
9327            }
9328        }
9329    }
9330
9331    /**
9332     * Returns true if this view is currently attached to a window.
9333     */
9334    public boolean isAttachedToWindow() {
9335        return mAttachInfo != null;
9336    }
9337
9338    /**
9339     * Returns true if this view has been through at least one layout since it
9340     * was last attached to or detached from a window.
9341     */
9342    public boolean isLaidOut() {
9343        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9344    }
9345
9346    /**
9347     * If this view doesn't do any drawing on its own, set this flag to
9348     * allow further optimizations. By default, this flag is not set on
9349     * View, but could be set on some View subclasses such as ViewGroup.
9350     *
9351     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9352     * you should clear this flag.
9353     *
9354     * @param willNotDraw whether or not this View draw on its own
9355     */
9356    public void setWillNotDraw(boolean willNotDraw) {
9357        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9358    }
9359
9360    /**
9361     * Returns whether or not this View draws on its own.
9362     *
9363     * @return true if this view has nothing to draw, false otherwise
9364     */
9365    @ViewDebug.ExportedProperty(category = "drawing")
9366    public boolean willNotDraw() {
9367        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9368    }
9369
9370    /**
9371     * When a View's drawing cache is enabled, drawing is redirected to an
9372     * offscreen bitmap. Some views, like an ImageView, must be able to
9373     * bypass this mechanism if they already draw a single bitmap, to avoid
9374     * unnecessary usage of the memory.
9375     *
9376     * @param willNotCacheDrawing true if this view does not cache its
9377     *        drawing, false otherwise
9378     */
9379    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9380        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9381    }
9382
9383    /**
9384     * Returns whether or not this View can cache its drawing or not.
9385     *
9386     * @return true if this view does not cache its drawing, false otherwise
9387     */
9388    @ViewDebug.ExportedProperty(category = "drawing")
9389    public boolean willNotCacheDrawing() {
9390        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9391    }
9392
9393    /**
9394     * Indicates whether this view reacts to click events or not.
9395     *
9396     * @return true if the view is clickable, false otherwise
9397     *
9398     * @see #setClickable(boolean)
9399     * @attr ref android.R.styleable#View_clickable
9400     */
9401    @ViewDebug.ExportedProperty
9402    public boolean isClickable() {
9403        return (mViewFlags & CLICKABLE) == CLICKABLE;
9404    }
9405
9406    /**
9407     * Enables or disables click events for this view. When a view
9408     * is clickable it will change its state to "pressed" on every click.
9409     * Subclasses should set the view clickable to visually react to
9410     * user's clicks.
9411     *
9412     * @param clickable true to make the view clickable, false otherwise
9413     *
9414     * @see #isClickable()
9415     * @attr ref android.R.styleable#View_clickable
9416     */
9417    public void setClickable(boolean clickable) {
9418        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9419    }
9420
9421    /**
9422     * Indicates whether this view reacts to long click events or not.
9423     *
9424     * @return true if the view is long clickable, false otherwise
9425     *
9426     * @see #setLongClickable(boolean)
9427     * @attr ref android.R.styleable#View_longClickable
9428     */
9429    public boolean isLongClickable() {
9430        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9431    }
9432
9433    /**
9434     * Enables or disables long click events for this view. When a view is long
9435     * clickable it reacts to the user holding down the button for a longer
9436     * duration than a tap. This event can either launch the listener or a
9437     * context menu.
9438     *
9439     * @param longClickable true to make the view long clickable, false otherwise
9440     * @see #isLongClickable()
9441     * @attr ref android.R.styleable#View_longClickable
9442     */
9443    public void setLongClickable(boolean longClickable) {
9444        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9445    }
9446
9447    /**
9448     * Indicates whether this view reacts to context clicks or not.
9449     *
9450     * @return true if the view is context clickable, false otherwise
9451     * @see #setContextClickable(boolean)
9452     * @attr ref android.R.styleable#View_contextClickable
9453     */
9454    public boolean isContextClickable() {
9455        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9456    }
9457
9458    /**
9459     * Enables or disables context clicking for this view. This event can launch the listener.
9460     *
9461     * @param contextClickable true to make the view react to a context click, false otherwise
9462     * @see #isContextClickable()
9463     * @attr ref android.R.styleable#View_contextClickable
9464     */
9465    public void setContextClickable(boolean contextClickable) {
9466        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9467    }
9468
9469    /**
9470     * Sets the pressed state for this view and provides a touch coordinate for
9471     * animation hinting.
9472     *
9473     * @param pressed Pass true to set the View's internal state to "pressed",
9474     *            or false to reverts the View's internal state from a
9475     *            previously set "pressed" state.
9476     * @param x The x coordinate of the touch that caused the press
9477     * @param y The y coordinate of the touch that caused the press
9478     */
9479    private void setPressed(boolean pressed, float x, float y) {
9480        if (pressed) {
9481            drawableHotspotChanged(x, y);
9482        }
9483
9484        setPressed(pressed);
9485    }
9486
9487    /**
9488     * Sets the pressed state for this view.
9489     *
9490     * @see #isClickable()
9491     * @see #setClickable(boolean)
9492     *
9493     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9494     *        the View's internal state from a previously set "pressed" state.
9495     */
9496    public void setPressed(boolean pressed) {
9497        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9498
9499        if (pressed) {
9500            mPrivateFlags |= PFLAG_PRESSED;
9501        } else {
9502            mPrivateFlags &= ~PFLAG_PRESSED;
9503        }
9504
9505        if (needsRefresh) {
9506            refreshDrawableState();
9507        }
9508        dispatchSetPressed(pressed);
9509    }
9510
9511    /**
9512     * Dispatch setPressed to all of this View's children.
9513     *
9514     * @see #setPressed(boolean)
9515     *
9516     * @param pressed The new pressed state
9517     */
9518    protected void dispatchSetPressed(boolean pressed) {
9519    }
9520
9521    /**
9522     * Indicates whether the view is currently in pressed state. Unless
9523     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9524     * the pressed state.
9525     *
9526     * @see #setPressed(boolean)
9527     * @see #isClickable()
9528     * @see #setClickable(boolean)
9529     *
9530     * @return true if the view is currently pressed, false otherwise
9531     */
9532    @ViewDebug.ExportedProperty
9533    public boolean isPressed() {
9534        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9535    }
9536
9537    /**
9538     * @hide
9539     * Indicates whether this view will participate in data collection through
9540     * {@link ViewStructure}.  If true, it will not provide any data
9541     * for itself or its children.  If false, the normal data collection will be allowed.
9542     *
9543     * @return Returns false if assist data collection is not blocked, else true.
9544     *
9545     * @see #setAssistBlocked(boolean)
9546     * @attr ref android.R.styleable#View_assistBlocked
9547     */
9548    public boolean isAssistBlocked() {
9549        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9550    }
9551
9552    /**
9553     * @hide
9554     * Indicates whether this view will participate in data collection through
9555     * {@link ViewStructure} for autofill purposes.
9556     *
9557     * <p>If {@code true}, it will not provide any data for itself or its children.
9558     * <p>If {@code false}, the normal data collection will be allowed.
9559     *
9560     * @return Returns {@code false} if assist data collection for autofill is not blocked,
9561     * else {@code true}.
9562     *
9563     * TODO(b/33197203): update / remove javadoc tags below
9564     * @see #setAssistBlocked(boolean)
9565     * @attr ref android.R.styleable#View_assistBlocked
9566     */
9567    public boolean isAutofillBlocked() {
9568        return false; // TODO(b/33197203): properly implement it
9569    }
9570
9571    /**
9572     * @hide
9573     * Controls whether assist data collection from this view and its children is enabled
9574     * (that is, whether {@link #onProvideStructure} and
9575     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9576     * allowing normal assist collection.  Setting this to false will disable assist collection.
9577     *
9578     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9579     * (the default) to allow it.
9580     *
9581     * @see #isAssistBlocked()
9582     * @see #onProvideStructure
9583     * @see #onProvideVirtualStructure
9584     * @attr ref android.R.styleable#View_assistBlocked
9585     */
9586    public void setAssistBlocked(boolean enabled) {
9587        if (enabled) {
9588            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9589        } else {
9590            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9591        }
9592    }
9593
9594    /**
9595     * Indicates whether this view will save its state (that is,
9596     * whether its {@link #onSaveInstanceState} method will be called).
9597     *
9598     * @return Returns true if the view state saving is enabled, else false.
9599     *
9600     * @see #setSaveEnabled(boolean)
9601     * @attr ref android.R.styleable#View_saveEnabled
9602     */
9603    public boolean isSaveEnabled() {
9604        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9605    }
9606
9607    /**
9608     * Controls whether the saving of this view's state is
9609     * enabled (that is, whether its {@link #onSaveInstanceState} method
9610     * will be called).  Note that even if freezing is enabled, the
9611     * view still must have an id assigned to it (via {@link #setId(int)})
9612     * for its state to be saved.  This flag can only disable the
9613     * saving of this view; any child views may still have their state saved.
9614     *
9615     * @param enabled Set to false to <em>disable</em> state saving, or true
9616     * (the default) to allow it.
9617     *
9618     * @see #isSaveEnabled()
9619     * @see #setId(int)
9620     * @see #onSaveInstanceState()
9621     * @attr ref android.R.styleable#View_saveEnabled
9622     */
9623    public void setSaveEnabled(boolean enabled) {
9624        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9625    }
9626
9627    /**
9628     * Gets whether the framework should discard touches when the view's
9629     * window is obscured by another visible window.
9630     * Refer to the {@link View} security documentation for more details.
9631     *
9632     * @return True if touch filtering is enabled.
9633     *
9634     * @see #setFilterTouchesWhenObscured(boolean)
9635     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9636     */
9637    @ViewDebug.ExportedProperty
9638    public boolean getFilterTouchesWhenObscured() {
9639        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9640    }
9641
9642    /**
9643     * Sets whether the framework should discard touches when the view's
9644     * window is obscured by another visible window.
9645     * Refer to the {@link View} security documentation for more details.
9646     *
9647     * @param enabled True if touch filtering should be enabled.
9648     *
9649     * @see #getFilterTouchesWhenObscured
9650     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9651     */
9652    public void setFilterTouchesWhenObscured(boolean enabled) {
9653        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9654                FILTER_TOUCHES_WHEN_OBSCURED);
9655    }
9656
9657    /**
9658     * Indicates whether the entire hierarchy under this view will save its
9659     * state when a state saving traversal occurs from its parent.  The default
9660     * is true; if false, these views will not be saved unless
9661     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9662     *
9663     * @return Returns true if the view state saving from parent is enabled, else false.
9664     *
9665     * @see #setSaveFromParentEnabled(boolean)
9666     */
9667    public boolean isSaveFromParentEnabled() {
9668        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9669    }
9670
9671    /**
9672     * Controls whether the entire hierarchy under this view will save its
9673     * state when a state saving traversal occurs from its parent.  The default
9674     * is true; if false, these views will not be saved unless
9675     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9676     *
9677     * @param enabled Set to false to <em>disable</em> state saving, or true
9678     * (the default) to allow it.
9679     *
9680     * @see #isSaveFromParentEnabled()
9681     * @see #setId(int)
9682     * @see #onSaveInstanceState()
9683     */
9684    public void setSaveFromParentEnabled(boolean enabled) {
9685        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9686    }
9687
9688
9689    /**
9690     * Returns whether this View is currently able to take focus.
9691     *
9692     * @return True if this view can take focus, or false otherwise.
9693     */
9694    @ViewDebug.ExportedProperty(category = "focus")
9695    public final boolean isFocusable() {
9696        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9697    }
9698
9699    /**
9700     * Returns the focusable setting for this view.
9701     *
9702     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9703     * @attr ref android.R.styleable#View_focusable
9704     */
9705    @ViewDebug.ExportedProperty(mapping = {
9706            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9707            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9708            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9709            })
9710    @Focusable
9711    public int getFocusable() {
9712        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9713    }
9714
9715    /**
9716     * When a view is focusable, it may not want to take focus when in touch mode.
9717     * For example, a button would like focus when the user is navigating via a D-pad
9718     * so that the user can click on it, but once the user starts touching the screen,
9719     * the button shouldn't take focus
9720     * @return Whether the view is focusable in touch mode.
9721     * @attr ref android.R.styleable#View_focusableInTouchMode
9722     */
9723    @ViewDebug.ExportedProperty
9724    public final boolean isFocusableInTouchMode() {
9725        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9726    }
9727
9728    /**
9729     * Returns the autofill mode for this view.
9730     *
9731     * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
9732     * {@link #AUTOFILL_MODE_MANUAL}.
9733     * @attr ref android.R.styleable#View_autofillMode
9734     */
9735    @ViewDebug.ExportedProperty(mapping = {
9736            @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
9737            @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
9738            @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
9739            })
9740    @AutofillMode
9741    public int getAutofillMode() {
9742        return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
9743    }
9744
9745    /**
9746     * Returns the resolved autofill mode for this view.
9747     *
9748     * This is the same as {@link #getAutofillMode()} but if the mode is
9749     * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
9750     *
9751     * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
9752     *         fill mode can not be resolved e.g. {@link #getAutofillMode()} is
9753     *         {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
9754     *         {@link #AUTOFILL_MODE_AUTO} is returned.
9755     */
9756    public @AutofillMode int getResolvedAutofillMode() {
9757        @AutofillMode int autofillMode = getAutofillMode();
9758
9759        if (autofillMode == AUTOFILL_MODE_INHERIT) {
9760            if (mParent == null) {
9761                return AUTOFILL_MODE_AUTO;
9762            } else {
9763                return mParent.getResolvedAutofillMode();
9764            }
9765        } else {
9766            return autofillMode;
9767        }
9768    }
9769
9770    /**
9771     * Find the nearest view in the specified direction that can take focus.
9772     * This does not actually give focus to that view.
9773     *
9774     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9775     *
9776     * @return The nearest focusable in the specified direction, or null if none
9777     *         can be found.
9778     */
9779    public View focusSearch(@FocusRealDirection int direction) {
9780        if (mParent != null) {
9781            return mParent.focusSearch(this, direction);
9782        } else {
9783            return null;
9784        }
9785    }
9786
9787    /**
9788     * Returns whether this View is a root of a keyboard navigation cluster.
9789     *
9790     * @return True if this view is a root of a cluster, or false otherwise.
9791     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9792     */
9793    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9794    public final boolean isKeyboardNavigationCluster() {
9795        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9796    }
9797
9798    /**
9799     * Set whether this view is a root of a keyboard navigation cluster.
9800     *
9801     * @param isCluster If true, this view is a root of a cluster.
9802     *
9803     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9804     */
9805    public void setKeyboardNavigationCluster(boolean isCluster) {
9806        if (isCluster) {
9807            mPrivateFlags3 |= PFLAG3_CLUSTER;
9808        } else {
9809            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9810        }
9811    }
9812
9813    /**
9814     * Sets this View as the one which receives focus the next time cluster navigation jumps
9815     * to the cluster containing this View. This does NOT change focus even if the cluster
9816     * containing this view is current.
9817     *
9818     * @hide
9819     */
9820    public void setFocusedInCluster() {
9821        if (mParent instanceof ViewGroup) {
9822            ((ViewGroup) mParent).setFocusInCluster(this);
9823        }
9824    }
9825
9826    /**
9827     * Returns whether this View should receive focus when the focus is restored for the view
9828     * hierarchy containing this view.
9829     * <p>
9830     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9831     * window or serves as a target of cluster navigation.
9832     *
9833     * @see #restoreDefaultFocus(int)
9834     *
9835     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9836     * @attr ref android.R.styleable#View_focusedByDefault
9837     */
9838    @ViewDebug.ExportedProperty(category = "focusedByDefault")
9839    public final boolean isFocusedByDefault() {
9840        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9841    }
9842
9843    /**
9844     * Sets whether this View should receive focus when the focus is restored for the view
9845     * hierarchy containing this view.
9846     * <p>
9847     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9848     * window or serves as a target of cluster navigation.
9849     *
9850     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9851     *                           {@code false} otherwise.
9852     *
9853     * @see #restoreDefaultFocus(int)
9854     *
9855     * @attr ref android.R.styleable#View_focusedByDefault
9856     */
9857    public void setFocusedByDefault(boolean isFocusedByDefault) {
9858        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9859            return;
9860        }
9861
9862        if (isFocusedByDefault) {
9863            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9864        } else {
9865            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9866        }
9867
9868        if (mParent instanceof ViewGroup) {
9869            if (isFocusedByDefault) {
9870                ((ViewGroup) mParent).setDefaultFocus(this);
9871            } else {
9872                ((ViewGroup) mParent).clearDefaultFocus(this);
9873            }
9874        }
9875    }
9876
9877    /**
9878     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9879     *
9880     * @return {@code true} if this view has default focus, {@code false} otherwise
9881     */
9882    boolean hasDefaultFocus() {
9883        return isFocusedByDefault();
9884    }
9885
9886    /**
9887     * Find the nearest keyboard navigation cluster in the specified direction.
9888     * This does not actually give focus to that cluster.
9889     *
9890     * @param currentCluster The starting point of the search. Null means the current cluster is not
9891     *                       found yet
9892     * @param direction Direction to look
9893     *
9894     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9895     *         can be found
9896     */
9897    public View keyboardNavigationClusterSearch(View currentCluster,
9898            @FocusDirection int direction) {
9899        if (isKeyboardNavigationCluster()) {
9900            currentCluster = this;
9901        }
9902        if (isRootNamespace()) {
9903            // Root namespace means we should consider ourselves the top of the
9904            // tree for group searching; otherwise we could be group searching
9905            // into other tabs.  see LocalActivityManager and TabHost for more info.
9906            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9907                    this, currentCluster, direction);
9908        } else if (mParent != null) {
9909            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9910        }
9911        return null;
9912    }
9913
9914    /**
9915     * This method is the last chance for the focused view and its ancestors to
9916     * respond to an arrow key. This is called when the focused view did not
9917     * consume the key internally, nor could the view system find a new view in
9918     * the requested direction to give focus to.
9919     *
9920     * @param focused The currently focused view.
9921     * @param direction The direction focus wants to move. One of FOCUS_UP,
9922     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9923     * @return True if the this view consumed this unhandled move.
9924     */
9925    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9926        return false;
9927    }
9928
9929    /**
9930     * If a user manually specified the next view id for a particular direction,
9931     * use the root to look up the view.
9932     * @param root The root view of the hierarchy containing this view.
9933     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9934     * or FOCUS_BACKWARD.
9935     * @return The user specified next view, or null if there is none.
9936     */
9937    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9938        switch (direction) {
9939            case FOCUS_LEFT:
9940                if (mNextFocusLeftId == View.NO_ID) return null;
9941                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9942            case FOCUS_RIGHT:
9943                if (mNextFocusRightId == View.NO_ID) return null;
9944                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9945            case FOCUS_UP:
9946                if (mNextFocusUpId == View.NO_ID) return null;
9947                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9948            case FOCUS_DOWN:
9949                if (mNextFocusDownId == View.NO_ID) return null;
9950                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9951            case FOCUS_FORWARD:
9952                if (mNextFocusForwardId == View.NO_ID) return null;
9953                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9954            case FOCUS_BACKWARD: {
9955                if (mID == View.NO_ID) return null;
9956                final int id = mID;
9957                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9958                    @Override
9959                    public boolean test(View t) {
9960                        return t.mNextFocusForwardId == id;
9961                    }
9962                });
9963            }
9964        }
9965        return null;
9966    }
9967
9968    private View findViewInsideOutShouldExist(View root, int id) {
9969        if (mMatchIdPredicate == null) {
9970            mMatchIdPredicate = new MatchIdPredicate();
9971        }
9972        mMatchIdPredicate.mId = id;
9973        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
9974        if (result == null) {
9975            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
9976        }
9977        return result;
9978    }
9979
9980    /**
9981     * Find and return all focusable views that are descendants of this view,
9982     * possibly including this view if it is focusable itself.
9983     *
9984     * @param direction The direction of the focus
9985     * @return A list of focusable views
9986     */
9987    public ArrayList<View> getFocusables(@FocusDirection int direction) {
9988        ArrayList<View> result = new ArrayList<View>(24);
9989        addFocusables(result, direction);
9990        return result;
9991    }
9992
9993    /**
9994     * Add any focusable views that are descendants of this view (possibly
9995     * including this view if it is focusable itself) to views.  If we are in touch mode,
9996     * only add views that are also focusable in touch mode.
9997     *
9998     * @param views Focusable views found so far
9999     * @param direction The direction of the focus
10000     */
10001    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10002        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10003    }
10004
10005    /**
10006     * Adds any focusable views that are descendants of this view (possibly
10007     * including this view if it is focusable itself) to views. This method
10008     * adds all focusable views regardless if we are in touch mode or
10009     * only views focusable in touch mode if we are in touch mode or
10010     * only views that can take accessibility focus if accessibility is enabled
10011     * depending on the focusable mode parameter.
10012     *
10013     * @param views Focusable views found so far or null if all we are interested is
10014     *        the number of focusables.
10015     * @param direction The direction of the focus.
10016     * @param focusableMode The type of focusables to be added.
10017     *
10018     * @see #FOCUSABLES_ALL
10019     * @see #FOCUSABLES_TOUCH_MODE
10020     */
10021    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10022            @FocusableMode int focusableMode) {
10023        if (views == null) {
10024            return;
10025        }
10026        if (!isFocusable()) {
10027            return;
10028        }
10029        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10030                && !isFocusableInTouchMode()) {
10031            return;
10032        }
10033        views.add(this);
10034    }
10035
10036    /**
10037     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10038     * including this view if it is a cluster root itself) to views.
10039     *
10040     * @param views Keyboard navigation cluster roots found so far
10041     * @param direction Direction to look
10042     */
10043    public void addKeyboardNavigationClusters(
10044            @NonNull Collection<View> views,
10045            int direction) {
10046        if (!isKeyboardNavigationCluster()) {
10047            return;
10048        }
10049        if (!hasFocusable()) {
10050            return;
10051        }
10052        views.add(this);
10053    }
10054
10055    /**
10056     * Finds the Views that contain given text. The containment is case insensitive.
10057     * The search is performed by either the text that the View renders or the content
10058     * description that describes the view for accessibility purposes and the view does
10059     * not render or both. Clients can specify how the search is to be performed via
10060     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10061     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10062     *
10063     * @param outViews The output list of matching Views.
10064     * @param searched The text to match against.
10065     *
10066     * @see #FIND_VIEWS_WITH_TEXT
10067     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10068     * @see #setContentDescription(CharSequence)
10069     */
10070    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10071            @FindViewFlags int flags) {
10072        if (getAccessibilityNodeProvider() != null) {
10073            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10074                outViews.add(this);
10075            }
10076        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10077                && (searched != null && searched.length() > 0)
10078                && (mContentDescription != null && mContentDescription.length() > 0)) {
10079            String searchedLowerCase = searched.toString().toLowerCase();
10080            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10081            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10082                outViews.add(this);
10083            }
10084        }
10085    }
10086
10087    /**
10088     * Find and return all touchable views that are descendants of this view,
10089     * possibly including this view if it is touchable itself.
10090     *
10091     * @return A list of touchable views
10092     */
10093    public ArrayList<View> getTouchables() {
10094        ArrayList<View> result = new ArrayList<View>();
10095        addTouchables(result);
10096        return result;
10097    }
10098
10099    /**
10100     * Add any touchable views that are descendants of this view (possibly
10101     * including this view if it is touchable itself) to views.
10102     *
10103     * @param views Touchable views found so far
10104     */
10105    public void addTouchables(ArrayList<View> views) {
10106        final int viewFlags = mViewFlags;
10107
10108        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10109                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10110                && (viewFlags & ENABLED_MASK) == ENABLED) {
10111            views.add(this);
10112        }
10113    }
10114
10115    /**
10116     * Returns whether this View is accessibility focused.
10117     *
10118     * @return True if this View is accessibility focused.
10119     */
10120    public boolean isAccessibilityFocused() {
10121        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10122    }
10123
10124    /**
10125     * Call this to try to give accessibility focus to this view.
10126     *
10127     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10128     * returns false or the view is no visible or the view already has accessibility
10129     * focus.
10130     *
10131     * See also {@link #focusSearch(int)}, which is what you call to say that you
10132     * have focus, and you want your parent to look for the next one.
10133     *
10134     * @return Whether this view actually took accessibility focus.
10135     *
10136     * @hide
10137     */
10138    public boolean requestAccessibilityFocus() {
10139        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10140        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10141            return false;
10142        }
10143        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10144            return false;
10145        }
10146        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10147            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10148            ViewRootImpl viewRootImpl = getViewRootImpl();
10149            if (viewRootImpl != null) {
10150                viewRootImpl.setAccessibilityFocus(this, null);
10151            }
10152            invalidate();
10153            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10154            return true;
10155        }
10156        return false;
10157    }
10158
10159    /**
10160     * Call this to try to clear accessibility focus of this view.
10161     *
10162     * See also {@link #focusSearch(int)}, which is what you call to say that you
10163     * have focus, and you want your parent to look for the next one.
10164     *
10165     * @hide
10166     */
10167    public void clearAccessibilityFocus() {
10168        clearAccessibilityFocusNoCallbacks(0);
10169
10170        // Clear the global reference of accessibility focus if this view or
10171        // any of its descendants had accessibility focus. This will NOT send
10172        // an event or update internal state if focus is cleared from a
10173        // descendant view, which may leave views in inconsistent states.
10174        final ViewRootImpl viewRootImpl = getViewRootImpl();
10175        if (viewRootImpl != null) {
10176            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10177            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10178                viewRootImpl.setAccessibilityFocus(null, null);
10179            }
10180        }
10181    }
10182
10183    private void sendAccessibilityHoverEvent(int eventType) {
10184        // Since we are not delivering to a client accessibility events from not
10185        // important views (unless the clinet request that) we need to fire the
10186        // event from the deepest view exposed to the client. As a consequence if
10187        // the user crosses a not exposed view the client will see enter and exit
10188        // of the exposed predecessor followed by and enter and exit of that same
10189        // predecessor when entering and exiting the not exposed descendant. This
10190        // is fine since the client has a clear idea which view is hovered at the
10191        // price of a couple more events being sent. This is a simple and
10192        // working solution.
10193        View source = this;
10194        while (true) {
10195            if (source.includeForAccessibility()) {
10196                source.sendAccessibilityEvent(eventType);
10197                return;
10198            }
10199            ViewParent parent = source.getParent();
10200            if (parent instanceof View) {
10201                source = (View) parent;
10202            } else {
10203                return;
10204            }
10205        }
10206    }
10207
10208    /**
10209     * Clears accessibility focus without calling any callback methods
10210     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10211     * is used separately from that one for clearing accessibility focus when
10212     * giving this focus to another view.
10213     *
10214     * @param action The action, if any, that led to focus being cleared. Set to
10215     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10216     * the window.
10217     */
10218    void clearAccessibilityFocusNoCallbacks(int action) {
10219        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10220            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10221            invalidate();
10222            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10223                AccessibilityEvent event = AccessibilityEvent.obtain(
10224                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10225                event.setAction(action);
10226                if (mAccessibilityDelegate != null) {
10227                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10228                } else {
10229                    sendAccessibilityEventUnchecked(event);
10230                }
10231            }
10232        }
10233    }
10234
10235    /**
10236     * Call this to try to give focus to a specific view or to one of its
10237     * descendants.
10238     *
10239     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10240     * false), or if it is focusable and it is not focusable in touch mode
10241     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10242     *
10243     * See also {@link #focusSearch(int)}, which is what you call to say that you
10244     * have focus, and you want your parent to look for the next one.
10245     *
10246     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10247     * {@link #FOCUS_DOWN} and <code>null</code>.
10248     *
10249     * @return Whether this view or one of its descendants actually took focus.
10250     */
10251    public final boolean requestFocus() {
10252        return requestFocus(View.FOCUS_DOWN);
10253    }
10254
10255    /**
10256     * This will request focus for whichever View was last focused within this
10257     * cluster before a focus-jump out of it.
10258     *
10259     * @hide
10260     */
10261    @TestApi
10262    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10263        // Prioritize focusableByDefault over algorithmic focus selection.
10264        if (restoreDefaultFocus()) {
10265            return true;
10266        }
10267        return requestFocus(direction);
10268    }
10269
10270    /**
10271     * This will request focus for whichever View not in a cluster was last focused before a
10272     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10273     * the "first" focusable view it finds.
10274     *
10275     * @hide
10276     */
10277    @TestApi
10278    public boolean restoreFocusNotInCluster() {
10279        return requestFocus(View.FOCUS_DOWN);
10280    }
10281
10282    /**
10283     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10284     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10285     *
10286     * @return Whether this view or one of its descendants actually took focus
10287     */
10288    public boolean restoreDefaultFocus() {
10289        return requestFocus(View.FOCUS_DOWN);
10290    }
10291
10292    /**
10293     * Call this to try to give focus to a specific view or to one of its
10294     * descendants and give it a hint about what direction focus is heading.
10295     *
10296     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10297     * false), or if it is focusable and it is not focusable in touch mode
10298     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10299     *
10300     * See also {@link #focusSearch(int)}, which is what you call to say that you
10301     * have focus, and you want your parent to look for the next one.
10302     *
10303     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10304     * <code>null</code> set for the previously focused rectangle.
10305     *
10306     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10307     * @return Whether this view or one of its descendants actually took focus.
10308     */
10309    public final boolean requestFocus(int direction) {
10310        return requestFocus(direction, null);
10311    }
10312
10313    /**
10314     * Call this to try to give focus to a specific view or to one of its descendants
10315     * and give it hints about the direction and a specific rectangle that the focus
10316     * is coming from.  The rectangle can help give larger views a finer grained hint
10317     * about where focus is coming from, and therefore, where to show selection, or
10318     * forward focus change internally.
10319     *
10320     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10321     * false), or if it is focusable and it is not focusable in touch mode
10322     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10323     *
10324     * A View will not take focus if it is not visible.
10325     *
10326     * A View will not take focus if one of its parents has
10327     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10328     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10329     *
10330     * See also {@link #focusSearch(int)}, which is what you call to say that you
10331     * have focus, and you want your parent to look for the next one.
10332     *
10333     * You may wish to override this method if your custom {@link View} has an internal
10334     * {@link View} that it wishes to forward the request to.
10335     *
10336     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10337     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10338     *        to give a finer grained hint about where focus is coming from.  May be null
10339     *        if there is no hint.
10340     * @return Whether this view or one of its descendants actually took focus.
10341     */
10342    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10343        return requestFocusNoSearch(direction, previouslyFocusedRect);
10344    }
10345
10346    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10347        // need to be focusable
10348        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10349                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10350            return false;
10351        }
10352
10353        // need to be focusable in touch mode if in touch mode
10354        if (isInTouchMode() &&
10355            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10356               return false;
10357        }
10358
10359        // need to not have any parents blocking us
10360        if (hasAncestorThatBlocksDescendantFocus()) {
10361            return false;
10362        }
10363
10364        handleFocusGainInternal(direction, previouslyFocusedRect);
10365        return true;
10366    }
10367
10368    /**
10369     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10370     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10371     * touch mode to request focus when they are touched.
10372     *
10373     * @return Whether this view or one of its descendants actually took focus.
10374     *
10375     * @see #isInTouchMode()
10376     *
10377     */
10378    public final boolean requestFocusFromTouch() {
10379        // Leave touch mode if we need to
10380        if (isInTouchMode()) {
10381            ViewRootImpl viewRoot = getViewRootImpl();
10382            if (viewRoot != null) {
10383                viewRoot.ensureTouchMode(false);
10384            }
10385        }
10386        return requestFocus(View.FOCUS_DOWN);
10387    }
10388
10389    /**
10390     * @return Whether any ancestor of this view blocks descendant focus.
10391     */
10392    private boolean hasAncestorThatBlocksDescendantFocus() {
10393        final boolean focusableInTouchMode = isFocusableInTouchMode();
10394        ViewParent ancestor = mParent;
10395        while (ancestor instanceof ViewGroup) {
10396            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10397            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10398                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10399                return true;
10400            } else {
10401                ancestor = vgAncestor.getParent();
10402            }
10403        }
10404        return false;
10405    }
10406
10407    /**
10408     * Gets the mode for determining whether this View is important for accessibility.
10409     * A view is important for accessibility if it fires accessibility events and if it
10410     * is reported to accessibility services that query the screen.
10411     *
10412     * @return The mode for determining whether a view is important for accessibility, one
10413     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10414     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10415     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10416     *
10417     * @attr ref android.R.styleable#View_importantForAccessibility
10418     *
10419     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10420     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10421     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10422     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10423     */
10424    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10425            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10426            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10427            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10428            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10429                    to = "noHideDescendants")
10430        })
10431    public int getImportantForAccessibility() {
10432        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10433                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10434    }
10435
10436    /**
10437     * Sets the live region mode for this view. This indicates to accessibility
10438     * services whether they should automatically notify the user about changes
10439     * to the view's content description or text, or to the content descriptions
10440     * or text of the view's children (where applicable).
10441     * <p>
10442     * For example, in a login screen with a TextView that displays an "incorrect
10443     * password" notification, that view should be marked as a live region with
10444     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10445     * <p>
10446     * To disable change notifications for this view, use
10447     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10448     * mode for most views.
10449     * <p>
10450     * To indicate that the user should be notified of changes, use
10451     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10452     * <p>
10453     * If the view's changes should interrupt ongoing speech and notify the user
10454     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10455     *
10456     * @param mode The live region mode for this view, one of:
10457     *        <ul>
10458     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10459     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10460     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10461     *        </ul>
10462     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10463     */
10464    public void setAccessibilityLiveRegion(int mode) {
10465        if (mode != getAccessibilityLiveRegion()) {
10466            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10467            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10468                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10469            notifyViewAccessibilityStateChangedIfNeeded(
10470                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10471        }
10472    }
10473
10474    /**
10475     * Gets the live region mode for this View.
10476     *
10477     * @return The live region mode for the view.
10478     *
10479     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10480     *
10481     * @see #setAccessibilityLiveRegion(int)
10482     */
10483    public int getAccessibilityLiveRegion() {
10484        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10485                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10486    }
10487
10488    /**
10489     * Sets how to determine whether this view is important for accessibility
10490     * which is if it fires accessibility events and if it is reported to
10491     * accessibility services that query the screen.
10492     *
10493     * @param mode How to determine whether this view is important for accessibility.
10494     *
10495     * @attr ref android.R.styleable#View_importantForAccessibility
10496     *
10497     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10498     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10499     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10500     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10501     */
10502    public void setImportantForAccessibility(int mode) {
10503        final int oldMode = getImportantForAccessibility();
10504        if (mode != oldMode) {
10505            final boolean hideDescendants =
10506                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10507
10508            // If this node or its descendants are no longer important, try to
10509            // clear accessibility focus.
10510            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10511                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10512                if (focusHost != null) {
10513                    focusHost.clearAccessibilityFocus();
10514                }
10515            }
10516
10517            // If we're moving between AUTO and another state, we might not need
10518            // to send a subtree changed notification. We'll store the computed
10519            // importance, since we'll need to check it later to make sure.
10520            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10521                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10522            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10523            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10524            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10525                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10526            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10527                notifySubtreeAccessibilityStateChangedIfNeeded();
10528            } else {
10529                notifyViewAccessibilityStateChangedIfNeeded(
10530                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10531            }
10532        }
10533    }
10534
10535    /**
10536     * Returns the view within this view's hierarchy that is hosting
10537     * accessibility focus.
10538     *
10539     * @param searchDescendants whether to search for focus in descendant views
10540     * @return the view hosting accessibility focus, or {@code null}
10541     */
10542    private View findAccessibilityFocusHost(boolean searchDescendants) {
10543        if (isAccessibilityFocusedViewOrHost()) {
10544            return this;
10545        }
10546
10547        if (searchDescendants) {
10548            final ViewRootImpl viewRoot = getViewRootImpl();
10549            if (viewRoot != null) {
10550                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10551                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10552                    return focusHost;
10553                }
10554            }
10555        }
10556
10557        return null;
10558    }
10559
10560    /**
10561     * Computes whether this view should be exposed for accessibility. In
10562     * general, views that are interactive or provide information are exposed
10563     * while views that serve only as containers are hidden.
10564     * <p>
10565     * If an ancestor of this view has importance
10566     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10567     * returns <code>false</code>.
10568     * <p>
10569     * Otherwise, the value is computed according to the view's
10570     * {@link #getImportantForAccessibility()} value:
10571     * <ol>
10572     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10573     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10574     * </code>
10575     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10576     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10577     * view satisfies any of the following:
10578     * <ul>
10579     * <li>Is actionable, e.g. {@link #isClickable()},
10580     * {@link #isLongClickable()}, or {@link #isFocusable()}
10581     * <li>Has an {@link AccessibilityDelegate}
10582     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10583     * {@link OnKeyListener}, etc.
10584     * <li>Is an accessibility live region, e.g.
10585     * {@link #getAccessibilityLiveRegion()} is not
10586     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10587     * </ul>
10588     * </ol>
10589     *
10590     * @return Whether the view is exposed for accessibility.
10591     * @see #setImportantForAccessibility(int)
10592     * @see #getImportantForAccessibility()
10593     */
10594    public boolean isImportantForAccessibility() {
10595        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10596                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10597        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10598                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10599            return false;
10600        }
10601
10602        // Check parent mode to ensure we're not hidden.
10603        ViewParent parent = mParent;
10604        while (parent instanceof View) {
10605            if (((View) parent).getImportantForAccessibility()
10606                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10607                return false;
10608            }
10609            parent = parent.getParent();
10610        }
10611
10612        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10613                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10614                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10615    }
10616
10617    /**
10618     * Gets the parent for accessibility purposes. Note that the parent for
10619     * accessibility is not necessary the immediate parent. It is the first
10620     * predecessor that is important for accessibility.
10621     *
10622     * @return The parent for accessibility purposes.
10623     */
10624    public ViewParent getParentForAccessibility() {
10625        if (mParent instanceof View) {
10626            View parentView = (View) mParent;
10627            if (parentView.includeForAccessibility()) {
10628                return mParent;
10629            } else {
10630                return mParent.getParentForAccessibility();
10631            }
10632        }
10633        return null;
10634    }
10635
10636    /**
10637     * Adds the children of this View relevant for accessibility to the given list
10638     * as output. Since some Views are not important for accessibility the added
10639     * child views are not necessarily direct children of this view, rather they are
10640     * the first level of descendants important for accessibility.
10641     *
10642     * @param outChildren The output list that will receive children for accessibility.
10643     */
10644    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10645
10646    }
10647
10648    /**
10649     * Whether to regard this view for accessibility. A view is regarded for
10650     * accessibility if it is important for accessibility or the querying
10651     * accessibility service has explicitly requested that view not
10652     * important for accessibility are regarded.
10653     *
10654     * @return Whether to regard the view for accessibility.
10655     *
10656     * @hide
10657     */
10658    public boolean includeForAccessibility() {
10659        if (mAttachInfo != null) {
10660            return (mAttachInfo.mAccessibilityFetchFlags
10661                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10662                    || isImportantForAccessibility();
10663        }
10664        return false;
10665    }
10666
10667    /**
10668     * Returns whether the View is considered actionable from
10669     * accessibility perspective. Such view are important for
10670     * accessibility.
10671     *
10672     * @return True if the view is actionable for accessibility.
10673     *
10674     * @hide
10675     */
10676    public boolean isActionableForAccessibility() {
10677        return (isClickable() || isLongClickable() || isFocusable());
10678    }
10679
10680    /**
10681     * Returns whether the View has registered callbacks which makes it
10682     * important for accessibility.
10683     *
10684     * @return True if the view is actionable for accessibility.
10685     */
10686    private boolean hasListenersForAccessibility() {
10687        ListenerInfo info = getListenerInfo();
10688        return mTouchDelegate != null || info.mOnKeyListener != null
10689                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10690                || info.mOnHoverListener != null || info.mOnDragListener != null;
10691    }
10692
10693    /**
10694     * Notifies that the accessibility state of this view changed. The change
10695     * is local to this view and does not represent structural changes such
10696     * as children and parent. For example, the view became focusable. The
10697     * notification is at at most once every
10698     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10699     * to avoid unnecessary load to the system. Also once a view has a pending
10700     * notification this method is a NOP until the notification has been sent.
10701     *
10702     * @hide
10703     */
10704    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10705        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10706            return;
10707        }
10708        if (mSendViewStateChangedAccessibilityEvent == null) {
10709            mSendViewStateChangedAccessibilityEvent =
10710                    new SendViewStateChangedAccessibilityEvent();
10711        }
10712        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10713    }
10714
10715    /**
10716     * Notifies that the accessibility state of this view changed. The change
10717     * is *not* local to this view and does represent structural changes such
10718     * as children and parent. For example, the view size changed. The
10719     * notification is at at most once every
10720     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10721     * to avoid unnecessary load to the system. Also once a view has a pending
10722     * notification this method is a NOP until the notification has been sent.
10723     *
10724     * @hide
10725     */
10726    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10727        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10728            return;
10729        }
10730        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10731            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10732            if (mParent != null) {
10733                try {
10734                    mParent.notifySubtreeAccessibilityStateChanged(
10735                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10736                } catch (AbstractMethodError e) {
10737                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10738                            " does not fully implement ViewParent", e);
10739                }
10740            }
10741        }
10742    }
10743
10744    /**
10745     * Change the visibility of the View without triggering any other changes. This is
10746     * important for transitions, where visibility changes should not adjust focus or
10747     * trigger a new layout. This is only used when the visibility has already been changed
10748     * and we need a transient value during an animation. When the animation completes,
10749     * the original visibility value is always restored.
10750     *
10751     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10752     * @hide
10753     */
10754    public void setTransitionVisibility(@Visibility int visibility) {
10755        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10756    }
10757
10758    /**
10759     * Reset the flag indicating the accessibility state of the subtree rooted
10760     * at this view changed.
10761     */
10762    void resetSubtreeAccessibilityStateChanged() {
10763        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10764    }
10765
10766    /**
10767     * Report an accessibility action to this view's parents for delegated processing.
10768     *
10769     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10770     * call this method to delegate an accessibility action to a supporting parent. If the parent
10771     * returns true from its
10772     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10773     * method this method will return true to signify that the action was consumed.</p>
10774     *
10775     * <p>This method is useful for implementing nested scrolling child views. If
10776     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10777     * a custom view implementation may invoke this method to allow a parent to consume the
10778     * scroll first. If this method returns true the custom view should skip its own scrolling
10779     * behavior.</p>
10780     *
10781     * @param action Accessibility action to delegate
10782     * @param arguments Optional action arguments
10783     * @return true if the action was consumed by a parent
10784     */
10785    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10786        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10787            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10788                return true;
10789            }
10790        }
10791        return false;
10792    }
10793
10794    /**
10795     * Performs the specified accessibility action on the view. For
10796     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10797     * <p>
10798     * If an {@link AccessibilityDelegate} has been specified via calling
10799     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10800     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10801     * is responsible for handling this call.
10802     * </p>
10803     *
10804     * <p>The default implementation will delegate
10805     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10806     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10807     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10808     *
10809     * @param action The action to perform.
10810     * @param arguments Optional action arguments.
10811     * @return Whether the action was performed.
10812     */
10813    public boolean performAccessibilityAction(int action, Bundle arguments) {
10814      if (mAccessibilityDelegate != null) {
10815          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10816      } else {
10817          return performAccessibilityActionInternal(action, arguments);
10818      }
10819    }
10820
10821   /**
10822    * @see #performAccessibilityAction(int, Bundle)
10823    *
10824    * Note: Called from the default {@link AccessibilityDelegate}.
10825    *
10826    * @hide
10827    */
10828    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10829        if (isNestedScrollingEnabled()
10830                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10831                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10832                || action == R.id.accessibilityActionScrollUp
10833                || action == R.id.accessibilityActionScrollLeft
10834                || action == R.id.accessibilityActionScrollDown
10835                || action == R.id.accessibilityActionScrollRight)) {
10836            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10837                return true;
10838            }
10839        }
10840
10841        switch (action) {
10842            case AccessibilityNodeInfo.ACTION_CLICK: {
10843                if (isClickable()) {
10844                    performClick();
10845                    return true;
10846                }
10847            } break;
10848            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10849                if (isLongClickable()) {
10850                    performLongClick();
10851                    return true;
10852                }
10853            } break;
10854            case AccessibilityNodeInfo.ACTION_FOCUS: {
10855                if (!hasFocus()) {
10856                    // Get out of touch mode since accessibility
10857                    // wants to move focus around.
10858                    getViewRootImpl().ensureTouchMode(false);
10859                    return requestFocus();
10860                }
10861            } break;
10862            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10863                if (hasFocus()) {
10864                    clearFocus();
10865                    return !isFocused();
10866                }
10867            } break;
10868            case AccessibilityNodeInfo.ACTION_SELECT: {
10869                if (!isSelected()) {
10870                    setSelected(true);
10871                    return isSelected();
10872                }
10873            } break;
10874            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10875                if (isSelected()) {
10876                    setSelected(false);
10877                    return !isSelected();
10878                }
10879            } break;
10880            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10881                if (!isAccessibilityFocused()) {
10882                    return requestAccessibilityFocus();
10883                }
10884            } break;
10885            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10886                if (isAccessibilityFocused()) {
10887                    clearAccessibilityFocus();
10888                    return true;
10889                }
10890            } break;
10891            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10892                if (arguments != null) {
10893                    final int granularity = arguments.getInt(
10894                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10895                    final boolean extendSelection = arguments.getBoolean(
10896                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10897                    return traverseAtGranularity(granularity, true, extendSelection);
10898                }
10899            } break;
10900            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10901                if (arguments != null) {
10902                    final int granularity = arguments.getInt(
10903                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10904                    final boolean extendSelection = arguments.getBoolean(
10905                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10906                    return traverseAtGranularity(granularity, false, extendSelection);
10907                }
10908            } break;
10909            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10910                CharSequence text = getIterableTextForAccessibility();
10911                if (text == null) {
10912                    return false;
10913                }
10914                final int start = (arguments != null) ? arguments.getInt(
10915                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10916                final int end = (arguments != null) ? arguments.getInt(
10917                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10918                // Only cursor position can be specified (selection length == 0)
10919                if ((getAccessibilitySelectionStart() != start
10920                        || getAccessibilitySelectionEnd() != end)
10921                        && (start == end)) {
10922                    setAccessibilitySelection(start, end);
10923                    notifyViewAccessibilityStateChangedIfNeeded(
10924                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10925                    return true;
10926                }
10927            } break;
10928            case R.id.accessibilityActionShowOnScreen: {
10929                if (mAttachInfo != null) {
10930                    final Rect r = mAttachInfo.mTmpInvalRect;
10931                    getDrawingRect(r);
10932                    return requestRectangleOnScreen(r, true);
10933                }
10934            } break;
10935            case R.id.accessibilityActionContextClick: {
10936                if (isContextClickable()) {
10937                    performContextClick();
10938                    return true;
10939                }
10940            } break;
10941        }
10942        return false;
10943    }
10944
10945    private boolean traverseAtGranularity(int granularity, boolean forward,
10946            boolean extendSelection) {
10947        CharSequence text = getIterableTextForAccessibility();
10948        if (text == null || text.length() == 0) {
10949            return false;
10950        }
10951        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
10952        if (iterator == null) {
10953            return false;
10954        }
10955        int current = getAccessibilitySelectionEnd();
10956        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10957            current = forward ? 0 : text.length();
10958        }
10959        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
10960        if (range == null) {
10961            return false;
10962        }
10963        final int segmentStart = range[0];
10964        final int segmentEnd = range[1];
10965        int selectionStart;
10966        int selectionEnd;
10967        if (extendSelection && isAccessibilitySelectionExtendable()) {
10968            selectionStart = getAccessibilitySelectionStart();
10969            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10970                selectionStart = forward ? segmentStart : segmentEnd;
10971            }
10972            selectionEnd = forward ? segmentEnd : segmentStart;
10973        } else {
10974            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
10975        }
10976        setAccessibilitySelection(selectionStart, selectionEnd);
10977        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
10978                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
10979        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
10980        return true;
10981    }
10982
10983    /**
10984     * Gets the text reported for accessibility purposes.
10985     *
10986     * @return The accessibility text.
10987     *
10988     * @hide
10989     */
10990    public CharSequence getIterableTextForAccessibility() {
10991        return getContentDescription();
10992    }
10993
10994    /**
10995     * Gets whether accessibility selection can be extended.
10996     *
10997     * @return If selection is extensible.
10998     *
10999     * @hide
11000     */
11001    public boolean isAccessibilitySelectionExtendable() {
11002        return false;
11003    }
11004
11005    /**
11006     * @hide
11007     */
11008    public int getAccessibilitySelectionStart() {
11009        return mAccessibilityCursorPosition;
11010    }
11011
11012    /**
11013     * @hide
11014     */
11015    public int getAccessibilitySelectionEnd() {
11016        return getAccessibilitySelectionStart();
11017    }
11018
11019    /**
11020     * @hide
11021     */
11022    public void setAccessibilitySelection(int start, int end) {
11023        if (start ==  end && end == mAccessibilityCursorPosition) {
11024            return;
11025        }
11026        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11027            mAccessibilityCursorPosition = start;
11028        } else {
11029            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11030        }
11031        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11032    }
11033
11034    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11035            int fromIndex, int toIndex) {
11036        if (mParent == null) {
11037            return;
11038        }
11039        AccessibilityEvent event = AccessibilityEvent.obtain(
11040                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11041        onInitializeAccessibilityEvent(event);
11042        onPopulateAccessibilityEvent(event);
11043        event.setFromIndex(fromIndex);
11044        event.setToIndex(toIndex);
11045        event.setAction(action);
11046        event.setMovementGranularity(granularity);
11047        mParent.requestSendAccessibilityEvent(this, event);
11048    }
11049
11050    /**
11051     * @hide
11052     */
11053    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11054        switch (granularity) {
11055            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11056                CharSequence text = getIterableTextForAccessibility();
11057                if (text != null && text.length() > 0) {
11058                    CharacterTextSegmentIterator iterator =
11059                        CharacterTextSegmentIterator.getInstance(
11060                                mContext.getResources().getConfiguration().locale);
11061                    iterator.initialize(text.toString());
11062                    return iterator;
11063                }
11064            } break;
11065            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11066                CharSequence text = getIterableTextForAccessibility();
11067                if (text != null && text.length() > 0) {
11068                    WordTextSegmentIterator iterator =
11069                        WordTextSegmentIterator.getInstance(
11070                                mContext.getResources().getConfiguration().locale);
11071                    iterator.initialize(text.toString());
11072                    return iterator;
11073                }
11074            } break;
11075            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11076                CharSequence text = getIterableTextForAccessibility();
11077                if (text != null && text.length() > 0) {
11078                    ParagraphTextSegmentIterator iterator =
11079                        ParagraphTextSegmentIterator.getInstance();
11080                    iterator.initialize(text.toString());
11081                    return iterator;
11082                }
11083            } break;
11084        }
11085        return null;
11086    }
11087
11088    /**
11089     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11090     * and {@link #onFinishTemporaryDetach()}.
11091     *
11092     * <p>This method always returns {@code true} when called directly or indirectly from
11093     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11094     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11095     * <ul>
11096     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11097     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11098     * </ul>
11099     * </p>
11100     *
11101     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11102     * and {@link #onFinishTemporaryDetach()}.
11103     */
11104    public final boolean isTemporarilyDetached() {
11105        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11106    }
11107
11108    /**
11109     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11110     * a container View.
11111     */
11112    @CallSuper
11113    public void dispatchStartTemporaryDetach() {
11114        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11115        notifyEnterOrExitForAutoFillIfNeeded(false);
11116        onStartTemporaryDetach();
11117    }
11118
11119    /**
11120     * This is called when a container is going to temporarily detach a child, with
11121     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11122     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11123     * {@link #onDetachedFromWindow()} when the container is done.
11124     */
11125    public void onStartTemporaryDetach() {
11126        removeUnsetPressCallback();
11127        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11128    }
11129
11130    /**
11131     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11132     * a container View.
11133     */
11134    @CallSuper
11135    public void dispatchFinishTemporaryDetach() {
11136        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11137        onFinishTemporaryDetach();
11138        if (hasWindowFocus() && hasFocus()) {
11139            InputMethodManager.getInstance().focusIn(this);
11140        }
11141        notifyEnterOrExitForAutoFillIfNeeded(true);
11142    }
11143
11144    /**
11145     * Called after {@link #onStartTemporaryDetach} when the container is done
11146     * changing the view.
11147     */
11148    public void onFinishTemporaryDetach() {
11149    }
11150
11151    /**
11152     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11153     * for this view's window.  Returns null if the view is not currently attached
11154     * to the window.  Normally you will not need to use this directly, but
11155     * just use the standard high-level event callbacks like
11156     * {@link #onKeyDown(int, KeyEvent)}.
11157     */
11158    public KeyEvent.DispatcherState getKeyDispatcherState() {
11159        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11160    }
11161
11162    /**
11163     * Dispatch a key event before it is processed by any input method
11164     * associated with the view hierarchy.  This can be used to intercept
11165     * key events in special situations before the IME consumes them; a
11166     * typical example would be handling the BACK key to update the application's
11167     * UI instead of allowing the IME to see it and close itself.
11168     *
11169     * @param event The key event to be dispatched.
11170     * @return True if the event was handled, false otherwise.
11171     */
11172    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11173        return onKeyPreIme(event.getKeyCode(), event);
11174    }
11175
11176    /**
11177     * Dispatch a key event to the next view on the focus path. This path runs
11178     * from the top of the view tree down to the currently focused view. If this
11179     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11180     * the next node down the focus path. This method also fires any key
11181     * listeners.
11182     *
11183     * @param event The key event to be dispatched.
11184     * @return True if the event was handled, false otherwise.
11185     */
11186    public boolean dispatchKeyEvent(KeyEvent event) {
11187        if (mInputEventConsistencyVerifier != null) {
11188            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11189        }
11190
11191        // Give any attached key listener a first crack at the event.
11192        //noinspection SimplifiableIfStatement
11193        ListenerInfo li = mListenerInfo;
11194        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11195                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11196            return true;
11197        }
11198
11199        if (event.dispatch(this, mAttachInfo != null
11200                ? mAttachInfo.mKeyDispatchState : null, this)) {
11201            return true;
11202        }
11203
11204        if (mInputEventConsistencyVerifier != null) {
11205            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11206        }
11207        return false;
11208    }
11209
11210    /**
11211     * Dispatches a key shortcut event.
11212     *
11213     * @param event The key event to be dispatched.
11214     * @return True if the event was handled by the view, false otherwise.
11215     */
11216    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11217        return onKeyShortcut(event.getKeyCode(), event);
11218    }
11219
11220    /**
11221     * Pass the touch screen motion event down to the target view, or this
11222     * view if it is the target.
11223     *
11224     * @param event The motion event to be dispatched.
11225     * @return True if the event was handled by the view, false otherwise.
11226     */
11227    public boolean dispatchTouchEvent(MotionEvent event) {
11228        // If the event should be handled by accessibility focus first.
11229        if (event.isTargetAccessibilityFocus()) {
11230            // We don't have focus or no virtual descendant has it, do not handle the event.
11231            if (!isAccessibilityFocusedViewOrHost()) {
11232                return false;
11233            }
11234            // We have focus and got the event, then use normal event dispatch.
11235            event.setTargetAccessibilityFocus(false);
11236        }
11237
11238        boolean result = false;
11239
11240        if (mInputEventConsistencyVerifier != null) {
11241            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11242        }
11243
11244        final int actionMasked = event.getActionMasked();
11245        if (actionMasked == MotionEvent.ACTION_DOWN) {
11246            // Defensive cleanup for new gesture
11247            stopNestedScroll();
11248        }
11249
11250        if (onFilterTouchEventForSecurity(event)) {
11251            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11252                result = true;
11253            }
11254            //noinspection SimplifiableIfStatement
11255            ListenerInfo li = mListenerInfo;
11256            if (li != null && li.mOnTouchListener != null
11257                    && (mViewFlags & ENABLED_MASK) == ENABLED
11258                    && li.mOnTouchListener.onTouch(this, event)) {
11259                result = true;
11260            }
11261
11262            if (!result && onTouchEvent(event)) {
11263                result = true;
11264            }
11265        }
11266
11267        if (!result && mInputEventConsistencyVerifier != null) {
11268            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11269        }
11270
11271        // Clean up after nested scrolls if this is the end of a gesture;
11272        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11273        // of the gesture.
11274        if (actionMasked == MotionEvent.ACTION_UP ||
11275                actionMasked == MotionEvent.ACTION_CANCEL ||
11276                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11277            stopNestedScroll();
11278        }
11279
11280        return result;
11281    }
11282
11283    boolean isAccessibilityFocusedViewOrHost() {
11284        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11285                .getAccessibilityFocusedHost() == this);
11286    }
11287
11288    /**
11289     * Filter the touch event to apply security policies.
11290     *
11291     * @param event The motion event to be filtered.
11292     * @return True if the event should be dispatched, false if the event should be dropped.
11293     *
11294     * @see #getFilterTouchesWhenObscured
11295     */
11296    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11297        //noinspection RedundantIfStatement
11298        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11299                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11300            // Window is obscured, drop this touch.
11301            return false;
11302        }
11303        return true;
11304    }
11305
11306    /**
11307     * Pass a trackball motion event down to the focused view.
11308     *
11309     * @param event The motion event to be dispatched.
11310     * @return True if the event was handled by the view, false otherwise.
11311     */
11312    public boolean dispatchTrackballEvent(MotionEvent event) {
11313        if (mInputEventConsistencyVerifier != null) {
11314            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11315        }
11316
11317        return onTrackballEvent(event);
11318    }
11319
11320    /**
11321     * Pass a captured pointer event down to the focused view.
11322     *
11323     * @param event The motion event to be dispatched.
11324     * @return True if the event was handled by the view, false otherwise.
11325     */
11326    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11327        if (!hasPointerCapture()) {
11328            return false;
11329        }
11330        //noinspection SimplifiableIfStatement
11331        ListenerInfo li = mListenerInfo;
11332        if (li != null && li.mOnCapturedPointerListener != null
11333                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11334            return true;
11335        }
11336        return onCapturedPointerEvent(event);
11337    }
11338
11339    /**
11340     * Dispatch a generic motion event.
11341     * <p>
11342     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11343     * are delivered to the view under the pointer.  All other generic motion events are
11344     * delivered to the focused view.  Hover events are handled specially and are delivered
11345     * to {@link #onHoverEvent(MotionEvent)}.
11346     * </p>
11347     *
11348     * @param event The motion event to be dispatched.
11349     * @return True if the event was handled by the view, false otherwise.
11350     */
11351    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11352        if (mInputEventConsistencyVerifier != null) {
11353            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11354        }
11355
11356        final int source = event.getSource();
11357        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11358            final int action = event.getAction();
11359            if (action == MotionEvent.ACTION_HOVER_ENTER
11360                    || action == MotionEvent.ACTION_HOVER_MOVE
11361                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11362                if (dispatchHoverEvent(event)) {
11363                    return true;
11364                }
11365            } else if (dispatchGenericPointerEvent(event)) {
11366                return true;
11367            }
11368        } else if (dispatchGenericFocusedEvent(event)) {
11369            return true;
11370        }
11371
11372        if (dispatchGenericMotionEventInternal(event)) {
11373            return true;
11374        }
11375
11376        if (mInputEventConsistencyVerifier != null) {
11377            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11378        }
11379        return false;
11380    }
11381
11382    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11383        //noinspection SimplifiableIfStatement
11384        ListenerInfo li = mListenerInfo;
11385        if (li != null && li.mOnGenericMotionListener != null
11386                && (mViewFlags & ENABLED_MASK) == ENABLED
11387                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11388            return true;
11389        }
11390
11391        if (onGenericMotionEvent(event)) {
11392            return true;
11393        }
11394
11395        final int actionButton = event.getActionButton();
11396        switch (event.getActionMasked()) {
11397            case MotionEvent.ACTION_BUTTON_PRESS:
11398                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11399                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11400                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11401                    if (performContextClick(event.getX(), event.getY())) {
11402                        mInContextButtonPress = true;
11403                        setPressed(true, event.getX(), event.getY());
11404                        removeTapCallback();
11405                        removeLongPressCallback();
11406                        return true;
11407                    }
11408                }
11409                break;
11410
11411            case MotionEvent.ACTION_BUTTON_RELEASE:
11412                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11413                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11414                    mInContextButtonPress = false;
11415                    mIgnoreNextUpEvent = true;
11416                }
11417                break;
11418        }
11419
11420        if (mInputEventConsistencyVerifier != null) {
11421            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11422        }
11423        return false;
11424    }
11425
11426    /**
11427     * Dispatch a hover event.
11428     * <p>
11429     * Do not call this method directly.
11430     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11431     * </p>
11432     *
11433     * @param event The motion event to be dispatched.
11434     * @return True if the event was handled by the view, false otherwise.
11435     */
11436    protected boolean dispatchHoverEvent(MotionEvent event) {
11437        ListenerInfo li = mListenerInfo;
11438        //noinspection SimplifiableIfStatement
11439        if (li != null && li.mOnHoverListener != null
11440                && (mViewFlags & ENABLED_MASK) == ENABLED
11441                && li.mOnHoverListener.onHover(this, event)) {
11442            return true;
11443        }
11444
11445        return onHoverEvent(event);
11446    }
11447
11448    /**
11449     * Returns true if the view has a child to which it has recently sent
11450     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11451     * it does not have a hovered child, then it must be the innermost hovered view.
11452     * @hide
11453     */
11454    protected boolean hasHoveredChild() {
11455        return false;
11456    }
11457
11458    /**
11459     * Dispatch a generic motion event to the view under the first pointer.
11460     * <p>
11461     * Do not call this method directly.
11462     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11463     * </p>
11464     *
11465     * @param event The motion event to be dispatched.
11466     * @return True if the event was handled by the view, false otherwise.
11467     */
11468    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11469        return false;
11470    }
11471
11472    /**
11473     * Dispatch a generic motion event to the currently focused view.
11474     * <p>
11475     * Do not call this method directly.
11476     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11477     * </p>
11478     *
11479     * @param event The motion event to be dispatched.
11480     * @return True if the event was handled by the view, false otherwise.
11481     */
11482    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11483        return false;
11484    }
11485
11486    /**
11487     * Dispatch a pointer event.
11488     * <p>
11489     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11490     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11491     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11492     * and should not be expected to handle other pointing device features.
11493     * </p>
11494     *
11495     * @param event The motion event to be dispatched.
11496     * @return True if the event was handled by the view, false otherwise.
11497     * @hide
11498     */
11499    public final boolean dispatchPointerEvent(MotionEvent event) {
11500        if (event.isTouchEvent()) {
11501            return dispatchTouchEvent(event);
11502        } else {
11503            return dispatchGenericMotionEvent(event);
11504        }
11505    }
11506
11507    /**
11508     * Called when the window containing this view gains or loses window focus.
11509     * ViewGroups should override to route to their children.
11510     *
11511     * @param hasFocus True if the window containing this view now has focus,
11512     *        false otherwise.
11513     */
11514    public void dispatchWindowFocusChanged(boolean hasFocus) {
11515        onWindowFocusChanged(hasFocus);
11516    }
11517
11518    /**
11519     * Called when the window containing this view gains or loses focus.  Note
11520     * that this is separate from view focus: to receive key events, both
11521     * your view and its window must have focus.  If a window is displayed
11522     * on top of yours that takes input focus, then your own window will lose
11523     * focus but the view focus will remain unchanged.
11524     *
11525     * @param hasWindowFocus True if the window containing this view now has
11526     *        focus, false otherwise.
11527     */
11528    public void onWindowFocusChanged(boolean hasWindowFocus) {
11529        InputMethodManager imm = InputMethodManager.peekInstance();
11530        if (!hasWindowFocus) {
11531            if (isPressed()) {
11532                setPressed(false);
11533            }
11534            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11535            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11536                imm.focusOut(this);
11537            }
11538            removeLongPressCallback();
11539            removeTapCallback();
11540            onFocusLost();
11541        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11542            imm.focusIn(this);
11543        }
11544
11545        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11546
11547        refreshDrawableState();
11548    }
11549
11550    /**
11551     * Returns true if this view is in a window that currently has window focus.
11552     * Note that this is not the same as the view itself having focus.
11553     *
11554     * @return True if this view is in a window that currently has window focus.
11555     */
11556    public boolean hasWindowFocus() {
11557        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11558    }
11559
11560    /**
11561     * Dispatch a view visibility change down the view hierarchy.
11562     * ViewGroups should override to route to their children.
11563     * @param changedView The view whose visibility changed. Could be 'this' or
11564     * an ancestor view.
11565     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11566     * {@link #INVISIBLE} or {@link #GONE}.
11567     */
11568    protected void dispatchVisibilityChanged(@NonNull View changedView,
11569            @Visibility int visibility) {
11570        onVisibilityChanged(changedView, visibility);
11571    }
11572
11573    /**
11574     * Called when the visibility of the view or an ancestor of the view has
11575     * changed.
11576     *
11577     * @param changedView The view whose visibility changed. May be
11578     *                    {@code this} or an ancestor view.
11579     * @param visibility The new visibility, one of {@link #VISIBLE},
11580     *                   {@link #INVISIBLE} or {@link #GONE}.
11581     */
11582    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11583    }
11584
11585    /**
11586     * Dispatch a hint about whether this view is displayed. For instance, when
11587     * a View moves out of the screen, it might receives a display hint indicating
11588     * the view is not displayed. Applications should not <em>rely</em> on this hint
11589     * as there is no guarantee that they will receive one.
11590     *
11591     * @param hint A hint about whether or not this view is displayed:
11592     * {@link #VISIBLE} or {@link #INVISIBLE}.
11593     */
11594    public void dispatchDisplayHint(@Visibility int hint) {
11595        onDisplayHint(hint);
11596    }
11597
11598    /**
11599     * Gives this view a hint about whether is displayed or not. For instance, when
11600     * a View moves out of the screen, it might receives a display hint indicating
11601     * the view is not displayed. Applications should not <em>rely</em> on this hint
11602     * as there is no guarantee that they will receive one.
11603     *
11604     * @param hint A hint about whether or not this view is displayed:
11605     * {@link #VISIBLE} or {@link #INVISIBLE}.
11606     */
11607    protected void onDisplayHint(@Visibility int hint) {
11608    }
11609
11610    /**
11611     * Dispatch a window visibility change down the view hierarchy.
11612     * ViewGroups should override to route to their children.
11613     *
11614     * @param visibility The new visibility of the window.
11615     *
11616     * @see #onWindowVisibilityChanged(int)
11617     */
11618    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11619        onWindowVisibilityChanged(visibility);
11620    }
11621
11622    /**
11623     * Called when the window containing has change its visibility
11624     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11625     * that this tells you whether or not your window is being made visible
11626     * to the window manager; this does <em>not</em> tell you whether or not
11627     * your window is obscured by other windows on the screen, even if it
11628     * is itself visible.
11629     *
11630     * @param visibility The new visibility of the window.
11631     */
11632    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11633        if (visibility == VISIBLE) {
11634            initialAwakenScrollBars();
11635        }
11636    }
11637
11638    /**
11639     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11640     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11641     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11642     *
11643     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11644     *                  ancestors or by window visibility
11645     * @return true if this view is visible to the user, not counting clipping or overlapping
11646     */
11647    boolean dispatchVisibilityAggregated(boolean isVisible) {
11648        final boolean thisVisible = getVisibility() == VISIBLE;
11649        // If we're not visible but something is telling us we are, ignore it.
11650        if (thisVisible || !isVisible) {
11651            onVisibilityAggregated(isVisible);
11652        }
11653        return thisVisible && isVisible;
11654    }
11655
11656    /**
11657     * Called when the user-visibility of this View is potentially affected by a change
11658     * to this view itself, an ancestor view or the window this view is attached to.
11659     *
11660     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11661     *                  and this view's window is also visible
11662     */
11663    @CallSuper
11664    public void onVisibilityAggregated(boolean isVisible) {
11665        if (isVisible && mAttachInfo != null) {
11666            initialAwakenScrollBars();
11667        }
11668
11669        final Drawable dr = mBackground;
11670        if (dr != null && isVisible != dr.isVisible()) {
11671            dr.setVisible(isVisible, false);
11672        }
11673        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11674        if (fg != null && isVisible != fg.isVisible()) {
11675            fg.setVisible(isVisible, false);
11676        }
11677    }
11678
11679    /**
11680     * Returns the current visibility of the window this view is attached to
11681     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11682     *
11683     * @return Returns the current visibility of the view's window.
11684     */
11685    @Visibility
11686    public int getWindowVisibility() {
11687        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11688    }
11689
11690    /**
11691     * Retrieve the overall visible display size in which the window this view is
11692     * attached to has been positioned in.  This takes into account screen
11693     * decorations above the window, for both cases where the window itself
11694     * is being position inside of them or the window is being placed under
11695     * then and covered insets are used for the window to position its content
11696     * inside.  In effect, this tells you the available area where content can
11697     * be placed and remain visible to users.
11698     *
11699     * <p>This function requires an IPC back to the window manager to retrieve
11700     * the requested information, so should not be used in performance critical
11701     * code like drawing.
11702     *
11703     * @param outRect Filled in with the visible display frame.  If the view
11704     * is not attached to a window, this is simply the raw display size.
11705     */
11706    public void getWindowVisibleDisplayFrame(Rect outRect) {
11707        if (mAttachInfo != null) {
11708            try {
11709                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11710            } catch (RemoteException e) {
11711                return;
11712            }
11713            // XXX This is really broken, and probably all needs to be done
11714            // in the window manager, and we need to know more about whether
11715            // we want the area behind or in front of the IME.
11716            final Rect insets = mAttachInfo.mVisibleInsets;
11717            outRect.left += insets.left;
11718            outRect.top += insets.top;
11719            outRect.right -= insets.right;
11720            outRect.bottom -= insets.bottom;
11721            return;
11722        }
11723        // The view is not attached to a display so we don't have a context.
11724        // Make a best guess about the display size.
11725        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11726        d.getRectSize(outRect);
11727    }
11728
11729    /**
11730     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11731     * is currently in without any insets.
11732     *
11733     * @hide
11734     */
11735    public void getWindowDisplayFrame(Rect outRect) {
11736        if (mAttachInfo != null) {
11737            try {
11738                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11739            } catch (RemoteException e) {
11740                return;
11741            }
11742            return;
11743        }
11744        // The view is not attached to a display so we don't have a context.
11745        // Make a best guess about the display size.
11746        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11747        d.getRectSize(outRect);
11748    }
11749
11750    /**
11751     * Dispatch a notification about a resource configuration change down
11752     * the view hierarchy.
11753     * ViewGroups should override to route to their children.
11754     *
11755     * @param newConfig The new resource configuration.
11756     *
11757     * @see #onConfigurationChanged(android.content.res.Configuration)
11758     */
11759    public void dispatchConfigurationChanged(Configuration newConfig) {
11760        onConfigurationChanged(newConfig);
11761    }
11762
11763    /**
11764     * Called when the current configuration of the resources being used
11765     * by the application have changed.  You can use this to decide when
11766     * to reload resources that can changed based on orientation and other
11767     * configuration characteristics.  You only need to use this if you are
11768     * not relying on the normal {@link android.app.Activity} mechanism of
11769     * recreating the activity instance upon a configuration change.
11770     *
11771     * @param newConfig The new resource configuration.
11772     */
11773    protected void onConfigurationChanged(Configuration newConfig) {
11774    }
11775
11776    /**
11777     * Private function to aggregate all per-view attributes in to the view
11778     * root.
11779     */
11780    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11781        performCollectViewAttributes(attachInfo, visibility);
11782    }
11783
11784    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11785        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11786            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11787                attachInfo.mKeepScreenOn = true;
11788            }
11789            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11790            ListenerInfo li = mListenerInfo;
11791            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11792                attachInfo.mHasSystemUiListeners = true;
11793            }
11794        }
11795    }
11796
11797    void needGlobalAttributesUpdate(boolean force) {
11798        final AttachInfo ai = mAttachInfo;
11799        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11800            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11801                    || ai.mHasSystemUiListeners) {
11802                ai.mRecomputeGlobalAttributes = true;
11803            }
11804        }
11805    }
11806
11807    /**
11808     * Returns whether the device is currently in touch mode.  Touch mode is entered
11809     * once the user begins interacting with the device by touch, and affects various
11810     * things like whether focus is always visible to the user.
11811     *
11812     * @return Whether the device is in touch mode.
11813     */
11814    @ViewDebug.ExportedProperty
11815    public boolean isInTouchMode() {
11816        if (mAttachInfo != null) {
11817            return mAttachInfo.mInTouchMode;
11818        } else {
11819            return ViewRootImpl.isInTouchMode();
11820        }
11821    }
11822
11823    /**
11824     * Returns the context the view is running in, through which it can
11825     * access the current theme, resources, etc.
11826     *
11827     * @return The view's Context.
11828     */
11829    @ViewDebug.CapturedViewProperty
11830    public final Context getContext() {
11831        return mContext;
11832    }
11833
11834    /**
11835     * Handle a key event before it is processed by any input method
11836     * associated with the view hierarchy.  This can be used to intercept
11837     * key events in special situations before the IME consumes them; a
11838     * typical example would be handling the BACK key to update the application's
11839     * UI instead of allowing the IME to see it and close itself.
11840     *
11841     * @param keyCode The value in event.getKeyCode().
11842     * @param event Description of the key event.
11843     * @return If you handled the event, return true. If you want to allow the
11844     *         event to be handled by the next receiver, return false.
11845     */
11846    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11847        return false;
11848    }
11849
11850    /**
11851     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11852     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11853     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11854     * is released, if the view is enabled and clickable.
11855     * <p>
11856     * Key presses in software keyboards will generally NOT trigger this
11857     * listener, although some may elect to do so in some situations. Do not
11858     * rely on this to catch software key presses.
11859     *
11860     * @param keyCode a key code that represents the button pressed, from
11861     *                {@link android.view.KeyEvent}
11862     * @param event the KeyEvent object that defines the button action
11863     */
11864    public boolean onKeyDown(int keyCode, KeyEvent event) {
11865        if (KeyEvent.isConfirmKey(keyCode)) {
11866            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11867                return true;
11868            }
11869
11870            if (event.getRepeatCount() == 0) {
11871                // Long clickable items don't necessarily have to be clickable.
11872                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11873                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11874                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11875                    // For the purposes of menu anchoring and drawable hotspots,
11876                    // key events are considered to be at the center of the view.
11877                    final float x = getWidth() / 2f;
11878                    final float y = getHeight() / 2f;
11879                    if (clickable) {
11880                        setPressed(true, x, y);
11881                    }
11882                    checkForLongClick(0, x, y);
11883                    return true;
11884                }
11885            }
11886        }
11887
11888        return false;
11889    }
11890
11891    /**
11892     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11893     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11894     * the event).
11895     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11896     * although some may elect to do so in some situations. Do not rely on this to
11897     * catch software key presses.
11898     */
11899    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11900        return false;
11901    }
11902
11903    /**
11904     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11905     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11906     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11907     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11908     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11909     * although some may elect to do so in some situations. Do not rely on this to
11910     * catch software key presses.
11911     *
11912     * @param keyCode A key code that represents the button pressed, from
11913     *                {@link android.view.KeyEvent}.
11914     * @param event   The KeyEvent object that defines the button action.
11915     */
11916    public boolean onKeyUp(int keyCode, KeyEvent event) {
11917        if (KeyEvent.isConfirmKey(keyCode)) {
11918            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11919                return true;
11920            }
11921            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
11922                setPressed(false);
11923
11924                if (!mHasPerformedLongPress) {
11925                    // This is a tap, so remove the longpress check
11926                    removeLongPressCallback();
11927                    if (!event.isCanceled()) {
11928                        return performClick();
11929                    }
11930                }
11931            }
11932        }
11933        return false;
11934    }
11935
11936    /**
11937     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
11938     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
11939     * the event).
11940     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11941     * although some may elect to do so in some situations. Do not rely on this to
11942     * catch software key presses.
11943     *
11944     * @param keyCode     A key code that represents the button pressed, from
11945     *                    {@link android.view.KeyEvent}.
11946     * @param repeatCount The number of times the action was made.
11947     * @param event       The KeyEvent object that defines the button action.
11948     */
11949    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
11950        return false;
11951    }
11952
11953    /**
11954     * Called on the focused view when a key shortcut event is not handled.
11955     * Override this method to implement local key shortcuts for the View.
11956     * Key shortcuts can also be implemented by setting the
11957     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
11958     *
11959     * @param keyCode The value in event.getKeyCode().
11960     * @param event Description of the key event.
11961     * @return If you handled the event, return true. If you want to allow the
11962     *         event to be handled by the next receiver, return false.
11963     */
11964    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
11965        return false;
11966    }
11967
11968    /**
11969     * Check whether the called view is a text editor, in which case it
11970     * would make sense to automatically display a soft input window for
11971     * it.  Subclasses should override this if they implement
11972     * {@link #onCreateInputConnection(EditorInfo)} to return true if
11973     * a call on that method would return a non-null InputConnection, and
11974     * they are really a first-class editor that the user would normally
11975     * start typing on when the go into a window containing your view.
11976     *
11977     * <p>The default implementation always returns false.  This does
11978     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
11979     * will not be called or the user can not otherwise perform edits on your
11980     * view; it is just a hint to the system that this is not the primary
11981     * purpose of this view.
11982     *
11983     * @return Returns true if this view is a text editor, else false.
11984     */
11985    public boolean onCheckIsTextEditor() {
11986        return false;
11987    }
11988
11989    /**
11990     * Create a new InputConnection for an InputMethod to interact
11991     * with the view.  The default implementation returns null, since it doesn't
11992     * support input methods.  You can override this to implement such support.
11993     * This is only needed for views that take focus and text input.
11994     *
11995     * <p>When implementing this, you probably also want to implement
11996     * {@link #onCheckIsTextEditor()} to indicate you will return a
11997     * non-null InputConnection.</p>
11998     *
11999     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12000     * object correctly and in its entirety, so that the connected IME can rely
12001     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12002     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12003     * must be filled in with the correct cursor position for IMEs to work correctly
12004     * with your application.</p>
12005     *
12006     * @param outAttrs Fill in with attribute information about the connection.
12007     */
12008    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12009        return null;
12010    }
12011
12012    /**
12013     * Called by the {@link android.view.inputmethod.InputMethodManager}
12014     * when a view who is not the current
12015     * input connection target is trying to make a call on the manager.  The
12016     * default implementation returns false; you can override this to return
12017     * true for certain views if you are performing InputConnection proxying
12018     * to them.
12019     * @param view The View that is making the InputMethodManager call.
12020     * @return Return true to allow the call, false to reject.
12021     */
12022    public boolean checkInputConnectionProxy(View view) {
12023        return false;
12024    }
12025
12026    /**
12027     * Show the context menu for this view. It is not safe to hold on to the
12028     * menu after returning from this method.
12029     *
12030     * You should normally not overload this method. Overload
12031     * {@link #onCreateContextMenu(ContextMenu)} or define an
12032     * {@link OnCreateContextMenuListener} to add items to the context menu.
12033     *
12034     * @param menu The context menu to populate
12035     */
12036    public void createContextMenu(ContextMenu menu) {
12037        ContextMenuInfo menuInfo = getContextMenuInfo();
12038
12039        // Sets the current menu info so all items added to menu will have
12040        // my extra info set.
12041        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12042
12043        onCreateContextMenu(menu);
12044        ListenerInfo li = mListenerInfo;
12045        if (li != null && li.mOnCreateContextMenuListener != null) {
12046            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12047        }
12048
12049        // Clear the extra information so subsequent items that aren't mine don't
12050        // have my extra info.
12051        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12052
12053        if (mParent != null) {
12054            mParent.createContextMenu(menu);
12055        }
12056    }
12057
12058    /**
12059     * Views should implement this if they have extra information to associate
12060     * with the context menu. The return result is supplied as a parameter to
12061     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12062     * callback.
12063     *
12064     * @return Extra information about the item for which the context menu
12065     *         should be shown. This information will vary across different
12066     *         subclasses of View.
12067     */
12068    protected ContextMenuInfo getContextMenuInfo() {
12069        return null;
12070    }
12071
12072    /**
12073     * Views should implement this if the view itself is going to add items to
12074     * the context menu.
12075     *
12076     * @param menu the context menu to populate
12077     */
12078    protected void onCreateContextMenu(ContextMenu menu) {
12079    }
12080
12081    /**
12082     * Implement this method to handle trackball motion events.  The
12083     * <em>relative</em> movement of the trackball since the last event
12084     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12085     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12086     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12087     * they will often be fractional values, representing the more fine-grained
12088     * movement information available from a trackball).
12089     *
12090     * @param event The motion event.
12091     * @return True if the event was handled, false otherwise.
12092     */
12093    public boolean onTrackballEvent(MotionEvent event) {
12094        return false;
12095    }
12096
12097    /**
12098     * Implement this method to handle generic motion events.
12099     * <p>
12100     * Generic motion events describe joystick movements, mouse hovers, track pad
12101     * touches, scroll wheel movements and other input events.  The
12102     * {@link MotionEvent#getSource() source} of the motion event specifies
12103     * the class of input that was received.  Implementations of this method
12104     * must examine the bits in the source before processing the event.
12105     * The following code example shows how this is done.
12106     * </p><p>
12107     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12108     * are delivered to the view under the pointer.  All other generic motion events are
12109     * delivered to the focused view.
12110     * </p>
12111     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12112     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12113     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12114     *             // process the joystick movement...
12115     *             return true;
12116     *         }
12117     *     }
12118     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12119     *         switch (event.getAction()) {
12120     *             case MotionEvent.ACTION_HOVER_MOVE:
12121     *                 // process the mouse hover movement...
12122     *                 return true;
12123     *             case MotionEvent.ACTION_SCROLL:
12124     *                 // process the scroll wheel movement...
12125     *                 return true;
12126     *         }
12127     *     }
12128     *     return super.onGenericMotionEvent(event);
12129     * }</pre>
12130     *
12131     * @param event The generic motion event being processed.
12132     * @return True if the event was handled, false otherwise.
12133     */
12134    public boolean onGenericMotionEvent(MotionEvent event) {
12135        return false;
12136    }
12137
12138    /**
12139     * Implement this method to handle hover events.
12140     * <p>
12141     * This method is called whenever a pointer is hovering into, over, or out of the
12142     * bounds of a view and the view is not currently being touched.
12143     * Hover events are represented as pointer events with action
12144     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12145     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12146     * </p>
12147     * <ul>
12148     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12149     * when the pointer enters the bounds of the view.</li>
12150     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12151     * when the pointer has already entered the bounds of the view and has moved.</li>
12152     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12153     * when the pointer has exited the bounds of the view or when the pointer is
12154     * about to go down due to a button click, tap, or similar user action that
12155     * causes the view to be touched.</li>
12156     * </ul>
12157     * <p>
12158     * The view should implement this method to return true to indicate that it is
12159     * handling the hover event, such as by changing its drawable state.
12160     * </p><p>
12161     * The default implementation calls {@link #setHovered} to update the hovered state
12162     * of the view when a hover enter or hover exit event is received, if the view
12163     * is enabled and is clickable.  The default implementation also sends hover
12164     * accessibility events.
12165     * </p>
12166     *
12167     * @param event The motion event that describes the hover.
12168     * @return True if the view handled the hover event.
12169     *
12170     * @see #isHovered
12171     * @see #setHovered
12172     * @see #onHoverChanged
12173     */
12174    public boolean onHoverEvent(MotionEvent event) {
12175        // The root view may receive hover (or touch) events that are outside the bounds of
12176        // the window.  This code ensures that we only send accessibility events for
12177        // hovers that are actually within the bounds of the root view.
12178        final int action = event.getActionMasked();
12179        if (!mSendingHoverAccessibilityEvents) {
12180            if ((action == MotionEvent.ACTION_HOVER_ENTER
12181                    || action == MotionEvent.ACTION_HOVER_MOVE)
12182                    && !hasHoveredChild()
12183                    && pointInView(event.getX(), event.getY())) {
12184                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12185                mSendingHoverAccessibilityEvents = true;
12186            }
12187        } else {
12188            if (action == MotionEvent.ACTION_HOVER_EXIT
12189                    || (action == MotionEvent.ACTION_MOVE
12190                            && !pointInView(event.getX(), event.getY()))) {
12191                mSendingHoverAccessibilityEvents = false;
12192                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12193            }
12194        }
12195
12196        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12197                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12198                && isOnScrollbar(event.getX(), event.getY())) {
12199            awakenScrollBars();
12200        }
12201
12202        // If we consider ourself hoverable, or if we we're already hovered,
12203        // handle changing state in response to ENTER and EXIT events.
12204        if (isHoverable() || isHovered()) {
12205            switch (action) {
12206                case MotionEvent.ACTION_HOVER_ENTER:
12207                    setHovered(true);
12208                    break;
12209                case MotionEvent.ACTION_HOVER_EXIT:
12210                    setHovered(false);
12211                    break;
12212            }
12213
12214            // Dispatch the event to onGenericMotionEvent before returning true.
12215            // This is to provide compatibility with existing applications that
12216            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12217            // break because of the new default handling for hoverable views
12218            // in onHoverEvent.
12219            // Note that onGenericMotionEvent will be called by default when
12220            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12221            dispatchGenericMotionEventInternal(event);
12222            // The event was already handled by calling setHovered(), so always
12223            // return true.
12224            return true;
12225        }
12226
12227        return false;
12228    }
12229
12230    /**
12231     * Returns true if the view should handle {@link #onHoverEvent}
12232     * by calling {@link #setHovered} to change its hovered state.
12233     *
12234     * @return True if the view is hoverable.
12235     */
12236    private boolean isHoverable() {
12237        final int viewFlags = mViewFlags;
12238        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12239            return false;
12240        }
12241
12242        return (viewFlags & CLICKABLE) == CLICKABLE
12243                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12244                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12245    }
12246
12247    /**
12248     * Returns true if the view is currently hovered.
12249     *
12250     * @return True if the view is currently hovered.
12251     *
12252     * @see #setHovered
12253     * @see #onHoverChanged
12254     */
12255    @ViewDebug.ExportedProperty
12256    public boolean isHovered() {
12257        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12258    }
12259
12260    /**
12261     * Sets whether the view is currently hovered.
12262     * <p>
12263     * Calling this method also changes the drawable state of the view.  This
12264     * enables the view to react to hover by using different drawable resources
12265     * to change its appearance.
12266     * </p><p>
12267     * The {@link #onHoverChanged} method is called when the hovered state changes.
12268     * </p>
12269     *
12270     * @param hovered True if the view is hovered.
12271     *
12272     * @see #isHovered
12273     * @see #onHoverChanged
12274     */
12275    public void setHovered(boolean hovered) {
12276        if (hovered) {
12277            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12278                mPrivateFlags |= PFLAG_HOVERED;
12279                refreshDrawableState();
12280                onHoverChanged(true);
12281            }
12282        } else {
12283            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12284                mPrivateFlags &= ~PFLAG_HOVERED;
12285                refreshDrawableState();
12286                onHoverChanged(false);
12287            }
12288        }
12289    }
12290
12291    /**
12292     * Implement this method to handle hover state changes.
12293     * <p>
12294     * This method is called whenever the hover state changes as a result of a
12295     * call to {@link #setHovered}.
12296     * </p>
12297     *
12298     * @param hovered The current hover state, as returned by {@link #isHovered}.
12299     *
12300     * @see #isHovered
12301     * @see #setHovered
12302     */
12303    public void onHoverChanged(boolean hovered) {
12304    }
12305
12306    /**
12307     * Handles scroll bar dragging by mouse input.
12308     *
12309     * @hide
12310     * @param event The motion event.
12311     *
12312     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12313     */
12314    protected boolean handleScrollBarDragging(MotionEvent event) {
12315        if (mScrollCache == null) {
12316            return false;
12317        }
12318        final float x = event.getX();
12319        final float y = event.getY();
12320        final int action = event.getAction();
12321        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12322                && action != MotionEvent.ACTION_DOWN)
12323                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12324                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12325            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12326            return false;
12327        }
12328
12329        switch (action) {
12330            case MotionEvent.ACTION_MOVE:
12331                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12332                    return false;
12333                }
12334                if (mScrollCache.mScrollBarDraggingState
12335                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12336                    final Rect bounds = mScrollCache.mScrollBarBounds;
12337                    getVerticalScrollBarBounds(bounds, null);
12338                    final int range = computeVerticalScrollRange();
12339                    final int offset = computeVerticalScrollOffset();
12340                    final int extent = computeVerticalScrollExtent();
12341
12342                    final int thumbLength = ScrollBarUtils.getThumbLength(
12343                            bounds.height(), bounds.width(), extent, range);
12344                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12345                            bounds.height(), thumbLength, extent, range, offset);
12346
12347                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12348                    final float maxThumbOffset = bounds.height() - thumbLength;
12349                    final float newThumbOffset =
12350                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12351                    final int height = getHeight();
12352                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12353                            && height > 0 && extent > 0) {
12354                        final int newY = Math.round((range - extent)
12355                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12356                        if (newY != getScrollY()) {
12357                            mScrollCache.mScrollBarDraggingPos = y;
12358                            setScrollY(newY);
12359                        }
12360                    }
12361                    return true;
12362                }
12363                if (mScrollCache.mScrollBarDraggingState
12364                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12365                    final Rect bounds = mScrollCache.mScrollBarBounds;
12366                    getHorizontalScrollBarBounds(bounds, null);
12367                    final int range = computeHorizontalScrollRange();
12368                    final int offset = computeHorizontalScrollOffset();
12369                    final int extent = computeHorizontalScrollExtent();
12370
12371                    final int thumbLength = ScrollBarUtils.getThumbLength(
12372                            bounds.width(), bounds.height(), extent, range);
12373                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12374                            bounds.width(), thumbLength, extent, range, offset);
12375
12376                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12377                    final float maxThumbOffset = bounds.width() - thumbLength;
12378                    final float newThumbOffset =
12379                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12380                    final int width = getWidth();
12381                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12382                            && width > 0 && extent > 0) {
12383                        final int newX = Math.round((range - extent)
12384                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12385                        if (newX != getScrollX()) {
12386                            mScrollCache.mScrollBarDraggingPos = x;
12387                            setScrollX(newX);
12388                        }
12389                    }
12390                    return true;
12391                }
12392            case MotionEvent.ACTION_DOWN:
12393                if (mScrollCache.state == ScrollabilityCache.OFF) {
12394                    return false;
12395                }
12396                if (isOnVerticalScrollbarThumb(x, y)) {
12397                    mScrollCache.mScrollBarDraggingState =
12398                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12399                    mScrollCache.mScrollBarDraggingPos = y;
12400                    return true;
12401                }
12402                if (isOnHorizontalScrollbarThumb(x, y)) {
12403                    mScrollCache.mScrollBarDraggingState =
12404                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12405                    mScrollCache.mScrollBarDraggingPos = x;
12406                    return true;
12407                }
12408        }
12409        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12410        return false;
12411    }
12412
12413    /**
12414     * Implement this method to handle touch screen motion events.
12415     * <p>
12416     * If this method is used to detect click actions, it is recommended that
12417     * the actions be performed by implementing and calling
12418     * {@link #performClick()}. This will ensure consistent system behavior,
12419     * including:
12420     * <ul>
12421     * <li>obeying click sound preferences
12422     * <li>dispatching OnClickListener calls
12423     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12424     * accessibility features are enabled
12425     * </ul>
12426     *
12427     * @param event The motion event.
12428     * @return True if the event was handled, false otherwise.
12429     */
12430    public boolean onTouchEvent(MotionEvent event) {
12431        final float x = event.getX();
12432        final float y = event.getY();
12433        final int viewFlags = mViewFlags;
12434        final int action = event.getAction();
12435
12436        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12437                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12438                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12439
12440        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12441            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12442                setPressed(false);
12443            }
12444            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12445            // A disabled view that is clickable still consumes the touch
12446            // events, it just doesn't respond to them.
12447            return clickable;
12448        }
12449        if (mTouchDelegate != null) {
12450            if (mTouchDelegate.onTouchEvent(event)) {
12451                return true;
12452            }
12453        }
12454
12455        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12456            switch (action) {
12457                case MotionEvent.ACTION_UP:
12458                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12459                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12460                        handleTooltipUp();
12461                    }
12462                    if (!clickable) {
12463                        removeTapCallback();
12464                        removeLongPressCallback();
12465                        mInContextButtonPress = false;
12466                        mHasPerformedLongPress = false;
12467                        mIgnoreNextUpEvent = false;
12468                        break;
12469                    }
12470                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12471                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12472                        // take focus if we don't have it already and we should in
12473                        // touch mode.
12474                        boolean focusTaken = false;
12475                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12476                            focusTaken = requestFocus();
12477                        }
12478
12479                        if (prepressed) {
12480                            // The button is being released before we actually
12481                            // showed it as pressed.  Make it show the pressed
12482                            // state now (before scheduling the click) to ensure
12483                            // the user sees it.
12484                            setPressed(true, x, y);
12485                        }
12486
12487                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12488                            // This is a tap, so remove the longpress check
12489                            removeLongPressCallback();
12490
12491                            // Only perform take click actions if we were in the pressed state
12492                            if (!focusTaken) {
12493                                // Use a Runnable and post this rather than calling
12494                                // performClick directly. This lets other visual state
12495                                // of the view update before click actions start.
12496                                if (mPerformClick == null) {
12497                                    mPerformClick = new PerformClick();
12498                                }
12499                                if (!post(mPerformClick)) {
12500                                    performClick();
12501                                }
12502                            }
12503                        }
12504
12505                        if (mUnsetPressedState == null) {
12506                            mUnsetPressedState = new UnsetPressedState();
12507                        }
12508
12509                        if (prepressed) {
12510                            postDelayed(mUnsetPressedState,
12511                                    ViewConfiguration.getPressedStateDuration());
12512                        } else if (!post(mUnsetPressedState)) {
12513                            // If the post failed, unpress right now
12514                            mUnsetPressedState.run();
12515                        }
12516
12517                        removeTapCallback();
12518                    }
12519                    mIgnoreNextUpEvent = false;
12520                    break;
12521
12522                case MotionEvent.ACTION_DOWN:
12523                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12524                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12525                    }
12526                    mHasPerformedLongPress = false;
12527
12528                    if (!clickable) {
12529                        checkForLongClick(0, x, y);
12530                        break;
12531                    }
12532
12533                    if (performButtonActionOnTouchDown(event)) {
12534                        break;
12535                    }
12536
12537                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12538                    boolean isInScrollingContainer = isInScrollingContainer();
12539
12540                    // For views inside a scrolling container, delay the pressed feedback for
12541                    // a short period in case this is a scroll.
12542                    if (isInScrollingContainer) {
12543                        mPrivateFlags |= PFLAG_PREPRESSED;
12544                        if (mPendingCheckForTap == null) {
12545                            mPendingCheckForTap = new CheckForTap();
12546                        }
12547                        mPendingCheckForTap.x = event.getX();
12548                        mPendingCheckForTap.y = event.getY();
12549                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12550                    } else {
12551                        // Not inside a scrolling container, so show the feedback right away
12552                        setPressed(true, x, y);
12553                        checkForLongClick(0, x, y);
12554                    }
12555                    break;
12556
12557                case MotionEvent.ACTION_CANCEL:
12558                    if (clickable) {
12559                        setPressed(false);
12560                    }
12561                    removeTapCallback();
12562                    removeLongPressCallback();
12563                    mInContextButtonPress = false;
12564                    mHasPerformedLongPress = false;
12565                    mIgnoreNextUpEvent = false;
12566                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12567                    break;
12568
12569                case MotionEvent.ACTION_MOVE:
12570                    if (clickable) {
12571                        drawableHotspotChanged(x, y);
12572                    }
12573
12574                    // Be lenient about moving outside of buttons
12575                    if (!pointInView(x, y, mTouchSlop)) {
12576                        // Outside button
12577                        // Remove any future long press/tap checks
12578                        removeTapCallback();
12579                        removeLongPressCallback();
12580                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12581                            setPressed(false);
12582                        }
12583                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12584                    }
12585                    break;
12586            }
12587
12588            return true;
12589        }
12590
12591        return false;
12592    }
12593
12594    /**
12595     * @hide
12596     */
12597    public boolean isInScrollingContainer() {
12598        ViewParent p = getParent();
12599        while (p != null && p instanceof ViewGroup) {
12600            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12601                return true;
12602            }
12603            p = p.getParent();
12604        }
12605        return false;
12606    }
12607
12608    /**
12609     * Remove the longpress detection timer.
12610     */
12611    private void removeLongPressCallback() {
12612        if (mPendingCheckForLongPress != null) {
12613            removeCallbacks(mPendingCheckForLongPress);
12614        }
12615    }
12616
12617    /**
12618     * Remove the pending click action
12619     */
12620    private void removePerformClickCallback() {
12621        if (mPerformClick != null) {
12622            removeCallbacks(mPerformClick);
12623        }
12624    }
12625
12626    /**
12627     * Remove the prepress detection timer.
12628     */
12629    private void removeUnsetPressCallback() {
12630        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12631            setPressed(false);
12632            removeCallbacks(mUnsetPressedState);
12633        }
12634    }
12635
12636    /**
12637     * Remove the tap detection timer.
12638     */
12639    private void removeTapCallback() {
12640        if (mPendingCheckForTap != null) {
12641            mPrivateFlags &= ~PFLAG_PREPRESSED;
12642            removeCallbacks(mPendingCheckForTap);
12643        }
12644    }
12645
12646    /**
12647     * Cancels a pending long press.  Your subclass can use this if you
12648     * want the context menu to come up if the user presses and holds
12649     * at the same place, but you don't want it to come up if they press
12650     * and then move around enough to cause scrolling.
12651     */
12652    public void cancelLongPress() {
12653        removeLongPressCallback();
12654
12655        /*
12656         * The prepressed state handled by the tap callback is a display
12657         * construct, but the tap callback will post a long press callback
12658         * less its own timeout. Remove it here.
12659         */
12660        removeTapCallback();
12661    }
12662
12663    /**
12664     * Remove the pending callback for sending a
12665     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12666     */
12667    private void removeSendViewScrolledAccessibilityEventCallback() {
12668        if (mSendViewScrolledAccessibilityEvent != null) {
12669            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12670            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12671        }
12672    }
12673
12674    /**
12675     * Sets the TouchDelegate for this View.
12676     */
12677    public void setTouchDelegate(TouchDelegate delegate) {
12678        mTouchDelegate = delegate;
12679    }
12680
12681    /**
12682     * Gets the TouchDelegate for this View.
12683     */
12684    public TouchDelegate getTouchDelegate() {
12685        return mTouchDelegate;
12686    }
12687
12688    /**
12689     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12690     *
12691     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12692     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12693     * available. This method should only be called for touch events.
12694     *
12695     * <p class="note">This api is not intended for most applications. Buffered dispatch
12696     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12697     * streams will not improve your input latency. Side effects include: increased latency,
12698     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12699     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12700     * you.</p>
12701     */
12702    public final void requestUnbufferedDispatch(MotionEvent event) {
12703        final int action = event.getAction();
12704        if (mAttachInfo == null
12705                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12706                || !event.isTouchEvent()) {
12707            return;
12708        }
12709        mAttachInfo.mUnbufferedDispatchRequested = true;
12710    }
12711
12712    /**
12713     * Set flags controlling behavior of this view.
12714     *
12715     * @param flags Constant indicating the value which should be set
12716     * @param mask Constant indicating the bit range that should be changed
12717     */
12718    void setFlags(int flags, int mask) {
12719        final boolean accessibilityEnabled =
12720                AccessibilityManager.getInstance(mContext).isEnabled();
12721        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12722
12723        int old = mViewFlags;
12724        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12725
12726        int changed = mViewFlags ^ old;
12727        if (changed == 0) {
12728            return;
12729        }
12730        int privateFlags = mPrivateFlags;
12731
12732        // If focusable is auto, update the FOCUSABLE bit.
12733        int focusableChangedByAuto = 0;
12734        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12735                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12736            // Heuristic only takes into account whether view is clickable.
12737            final int newFocus;
12738            if ((mViewFlags & CLICKABLE) != 0) {
12739                newFocus = FOCUSABLE;
12740            } else {
12741                newFocus = NOT_FOCUSABLE;
12742            }
12743            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12744            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12745            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12746        }
12747
12748        /* Check if the FOCUSABLE bit has changed */
12749        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12750            if (((old & FOCUSABLE) == FOCUSABLE)
12751                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12752                /* Give up focus if we are no longer focusable */
12753                clearFocus();
12754            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12755                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12756                /*
12757                 * Tell the view system that we are now available to take focus
12758                 * if no one else already has it.
12759                 */
12760                if (mParent != null) {
12761                    ViewRootImpl viewRootImpl = getViewRootImpl();
12762                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12763                            || focusableChangedByAuto == 0
12764                            || viewRootImpl == null
12765                            || viewRootImpl.mThread == Thread.currentThread()) {
12766                        mParent.focusableViewAvailable(this);
12767                    }
12768                }
12769            }
12770        }
12771
12772        final int newVisibility = flags & VISIBILITY_MASK;
12773        if (newVisibility == VISIBLE) {
12774            if ((changed & VISIBILITY_MASK) != 0) {
12775                /*
12776                 * If this view is becoming visible, invalidate it in case it changed while
12777                 * it was not visible. Marking it drawn ensures that the invalidation will
12778                 * go through.
12779                 */
12780                mPrivateFlags |= PFLAG_DRAWN;
12781                invalidate(true);
12782
12783                needGlobalAttributesUpdate(true);
12784
12785                // a view becoming visible is worth notifying the parent
12786                // about in case nothing has focus.  even if this specific view
12787                // isn't focusable, it may contain something that is, so let
12788                // the root view try to give this focus if nothing else does.
12789                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12790                    mParent.focusableViewAvailable(this);
12791                }
12792            }
12793        }
12794
12795        /* Check if the GONE bit has changed */
12796        if ((changed & GONE) != 0) {
12797            needGlobalAttributesUpdate(false);
12798            requestLayout();
12799
12800            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12801                if (hasFocus()) clearFocus();
12802                clearAccessibilityFocus();
12803                destroyDrawingCache();
12804                if (mParent instanceof View) {
12805                    // GONE views noop invalidation, so invalidate the parent
12806                    ((View) mParent).invalidate(true);
12807                }
12808                // Mark the view drawn to ensure that it gets invalidated properly the next
12809                // time it is visible and gets invalidated
12810                mPrivateFlags |= PFLAG_DRAWN;
12811            }
12812            if (mAttachInfo != null) {
12813                mAttachInfo.mViewVisibilityChanged = true;
12814            }
12815        }
12816
12817        /* Check if the VISIBLE bit has changed */
12818        if ((changed & INVISIBLE) != 0) {
12819            needGlobalAttributesUpdate(false);
12820            /*
12821             * If this view is becoming invisible, set the DRAWN flag so that
12822             * the next invalidate() will not be skipped.
12823             */
12824            mPrivateFlags |= PFLAG_DRAWN;
12825
12826            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12827                // root view becoming invisible shouldn't clear focus and accessibility focus
12828                if (getRootView() != this) {
12829                    if (hasFocus()) clearFocus();
12830                    clearAccessibilityFocus();
12831                }
12832            }
12833            if (mAttachInfo != null) {
12834                mAttachInfo.mViewVisibilityChanged = true;
12835            }
12836        }
12837
12838        if ((changed & VISIBILITY_MASK) != 0) {
12839            // If the view is invisible, cleanup its display list to free up resources
12840            if (newVisibility != VISIBLE && mAttachInfo != null) {
12841                cleanupDraw();
12842            }
12843
12844            if (mParent instanceof ViewGroup) {
12845                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12846                        (changed & VISIBILITY_MASK), newVisibility);
12847                ((View) mParent).invalidate(true);
12848            } else if (mParent != null) {
12849                mParent.invalidateChild(this, null);
12850            }
12851
12852            if (mAttachInfo != null) {
12853                dispatchVisibilityChanged(this, newVisibility);
12854
12855                // Aggregated visibility changes are dispatched to attached views
12856                // in visible windows where the parent is currently shown/drawn
12857                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12858                // discounting clipping or overlapping. This makes it a good place
12859                // to change animation states.
12860                if (mParent != null && getWindowVisibility() == VISIBLE &&
12861                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12862                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12863                }
12864                notifySubtreeAccessibilityStateChangedIfNeeded();
12865            }
12866        }
12867
12868        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12869            destroyDrawingCache();
12870        }
12871
12872        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12873            destroyDrawingCache();
12874            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12875            invalidateParentCaches();
12876        }
12877
12878        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12879            destroyDrawingCache();
12880            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12881        }
12882
12883        if ((changed & DRAW_MASK) != 0) {
12884            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12885                if (mBackground != null
12886                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12887                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12888                } else {
12889                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12890                }
12891            } else {
12892                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12893            }
12894            requestLayout();
12895            invalidate(true);
12896        }
12897
12898        if ((changed & KEEP_SCREEN_ON) != 0) {
12899            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12900                mParent.recomputeViewAttributes(this);
12901            }
12902        }
12903
12904        if (accessibilityEnabled) {
12905            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
12906                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
12907                    || (changed & CONTEXT_CLICKABLE) != 0) {
12908                if (oldIncludeForAccessibility != includeForAccessibility()) {
12909                    notifySubtreeAccessibilityStateChangedIfNeeded();
12910                } else {
12911                    notifyViewAccessibilityStateChangedIfNeeded(
12912                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12913                }
12914            } else if ((changed & ENABLED_MASK) != 0) {
12915                notifyViewAccessibilityStateChangedIfNeeded(
12916                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12917            }
12918        }
12919    }
12920
12921    /**
12922     * Change the view's z order in the tree, so it's on top of other sibling
12923     * views. This ordering change may affect layout, if the parent container
12924     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
12925     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
12926     * method should be followed by calls to {@link #requestLayout()} and
12927     * {@link View#invalidate()} on the view's parent to force the parent to redraw
12928     * with the new child ordering.
12929     *
12930     * @see ViewGroup#bringChildToFront(View)
12931     */
12932    public void bringToFront() {
12933        if (mParent != null) {
12934            mParent.bringChildToFront(this);
12935        }
12936    }
12937
12938    /**
12939     * This is called in response to an internal scroll in this view (i.e., the
12940     * view scrolled its own contents). This is typically as a result of
12941     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
12942     * called.
12943     *
12944     * @param l Current horizontal scroll origin.
12945     * @param t Current vertical scroll origin.
12946     * @param oldl Previous horizontal scroll origin.
12947     * @param oldt Previous vertical scroll origin.
12948     */
12949    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
12950        notifySubtreeAccessibilityStateChangedIfNeeded();
12951
12952        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12953            postSendViewScrolledAccessibilityEventCallback();
12954        }
12955
12956        mBackgroundSizeChanged = true;
12957        if (mForegroundInfo != null) {
12958            mForegroundInfo.mBoundsChanged = true;
12959        }
12960
12961        final AttachInfo ai = mAttachInfo;
12962        if (ai != null) {
12963            ai.mViewScrollChanged = true;
12964        }
12965
12966        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
12967            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
12968        }
12969    }
12970
12971    /**
12972     * Interface definition for a callback to be invoked when the scroll
12973     * X or Y positions of a view change.
12974     * <p>
12975     * <b>Note:</b> Some views handle scrolling independently from View and may
12976     * have their own separate listeners for scroll-type events. For example,
12977     * {@link android.widget.ListView ListView} allows clients to register an
12978     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
12979     * to listen for changes in list scroll position.
12980     *
12981     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
12982     */
12983    public interface OnScrollChangeListener {
12984        /**
12985         * Called when the scroll position of a view changes.
12986         *
12987         * @param v The view whose scroll position has changed.
12988         * @param scrollX Current horizontal scroll origin.
12989         * @param scrollY Current vertical scroll origin.
12990         * @param oldScrollX Previous horizontal scroll origin.
12991         * @param oldScrollY Previous vertical scroll origin.
12992         */
12993        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
12994    }
12995
12996    /**
12997     * Interface definition for a callback to be invoked when the layout bounds of a view
12998     * changes due to layout processing.
12999     */
13000    public interface OnLayoutChangeListener {
13001        /**
13002         * Called when the layout bounds of a view changes due to layout processing.
13003         *
13004         * @param v The view whose bounds have changed.
13005         * @param left The new value of the view's left property.
13006         * @param top The new value of the view's top property.
13007         * @param right The new value of the view's right property.
13008         * @param bottom The new value of the view's bottom property.
13009         * @param oldLeft The previous value of the view's left property.
13010         * @param oldTop The previous value of the view's top property.
13011         * @param oldRight The previous value of the view's right property.
13012         * @param oldBottom The previous value of the view's bottom property.
13013         */
13014        void onLayoutChange(View v, int left, int top, int right, int bottom,
13015            int oldLeft, int oldTop, int oldRight, int oldBottom);
13016    }
13017
13018    /**
13019     * This is called during layout when the size of this view has changed. If
13020     * you were just added to the view hierarchy, you're called with the old
13021     * values of 0.
13022     *
13023     * @param w Current width of this view.
13024     * @param h Current height of this view.
13025     * @param oldw Old width of this view.
13026     * @param oldh Old height of this view.
13027     */
13028    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13029    }
13030
13031    /**
13032     * Called by draw to draw the child views. This may be overridden
13033     * by derived classes to gain control just before its children are drawn
13034     * (but after its own view has been drawn).
13035     * @param canvas the canvas on which to draw the view
13036     */
13037    protected void dispatchDraw(Canvas canvas) {
13038
13039    }
13040
13041    /**
13042     * Gets the parent of this view. Note that the parent is a
13043     * ViewParent and not necessarily a View.
13044     *
13045     * @return Parent of this view.
13046     */
13047    public final ViewParent getParent() {
13048        return mParent;
13049    }
13050
13051    /**
13052     * Set the horizontal scrolled position of your view. This will cause a call to
13053     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13054     * invalidated.
13055     * @param value the x position to scroll to
13056     */
13057    public void setScrollX(int value) {
13058        scrollTo(value, mScrollY);
13059    }
13060
13061    /**
13062     * Set the vertical scrolled position of your view. This will cause a call to
13063     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13064     * invalidated.
13065     * @param value the y position to scroll to
13066     */
13067    public void setScrollY(int value) {
13068        scrollTo(mScrollX, value);
13069    }
13070
13071    /**
13072     * Return the scrolled left position of this view. This is the left edge of
13073     * the displayed part of your view. You do not need to draw any pixels
13074     * farther left, since those are outside of the frame of your view on
13075     * screen.
13076     *
13077     * @return The left edge of the displayed part of your view, in pixels.
13078     */
13079    public final int getScrollX() {
13080        return mScrollX;
13081    }
13082
13083    /**
13084     * Return the scrolled top position of this view. This is the top edge of
13085     * the displayed part of your view. You do not need to draw any pixels above
13086     * it, since those are outside of the frame of your view on screen.
13087     *
13088     * @return The top edge of the displayed part of your view, in pixels.
13089     */
13090    public final int getScrollY() {
13091        return mScrollY;
13092    }
13093
13094    /**
13095     * Return the width of the your view.
13096     *
13097     * @return The width of your view, in pixels.
13098     */
13099    @ViewDebug.ExportedProperty(category = "layout")
13100    public final int getWidth() {
13101        return mRight - mLeft;
13102    }
13103
13104    /**
13105     * Return the height of your view.
13106     *
13107     * @return The height of your view, in pixels.
13108     */
13109    @ViewDebug.ExportedProperty(category = "layout")
13110    public final int getHeight() {
13111        return mBottom - mTop;
13112    }
13113
13114    /**
13115     * Return the visible drawing bounds of your view. Fills in the output
13116     * rectangle with the values from getScrollX(), getScrollY(),
13117     * getWidth(), and getHeight(). These bounds do not account for any
13118     * transformation properties currently set on the view, such as
13119     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13120     *
13121     * @param outRect The (scrolled) drawing bounds of the view.
13122     */
13123    public void getDrawingRect(Rect outRect) {
13124        outRect.left = mScrollX;
13125        outRect.top = mScrollY;
13126        outRect.right = mScrollX + (mRight - mLeft);
13127        outRect.bottom = mScrollY + (mBottom - mTop);
13128    }
13129
13130    /**
13131     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13132     * raw width component (that is the result is masked by
13133     * {@link #MEASURED_SIZE_MASK}).
13134     *
13135     * @return The raw measured width of this view.
13136     */
13137    public final int getMeasuredWidth() {
13138        return mMeasuredWidth & MEASURED_SIZE_MASK;
13139    }
13140
13141    /**
13142     * Return the full width measurement information for this view as computed
13143     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13144     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13145     * This should be used during measurement and layout calculations only. Use
13146     * {@link #getWidth()} to see how wide a view is after layout.
13147     *
13148     * @return The measured width of this view as a bit mask.
13149     */
13150    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13151            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13152                    name = "MEASURED_STATE_TOO_SMALL"),
13153    })
13154    public final int getMeasuredWidthAndState() {
13155        return mMeasuredWidth;
13156    }
13157
13158    /**
13159     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13160     * raw height component (that is the result is masked by
13161     * {@link #MEASURED_SIZE_MASK}).
13162     *
13163     * @return The raw measured height of this view.
13164     */
13165    public final int getMeasuredHeight() {
13166        return mMeasuredHeight & MEASURED_SIZE_MASK;
13167    }
13168
13169    /**
13170     * Return the full height measurement information for this view as computed
13171     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13172     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13173     * This should be used during measurement and layout calculations only. Use
13174     * {@link #getHeight()} to see how wide a view is after layout.
13175     *
13176     * @return The measured height of this view as a bit mask.
13177     */
13178    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13179            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13180                    name = "MEASURED_STATE_TOO_SMALL"),
13181    })
13182    public final int getMeasuredHeightAndState() {
13183        return mMeasuredHeight;
13184    }
13185
13186    /**
13187     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13188     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13189     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13190     * and the height component is at the shifted bits
13191     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13192     */
13193    public final int getMeasuredState() {
13194        return (mMeasuredWidth&MEASURED_STATE_MASK)
13195                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13196                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13197    }
13198
13199    /**
13200     * The transform matrix of this view, which is calculated based on the current
13201     * rotation, scale, and pivot properties.
13202     *
13203     * @see #getRotation()
13204     * @see #getScaleX()
13205     * @see #getScaleY()
13206     * @see #getPivotX()
13207     * @see #getPivotY()
13208     * @return The current transform matrix for the view
13209     */
13210    public Matrix getMatrix() {
13211        ensureTransformationInfo();
13212        final Matrix matrix = mTransformationInfo.mMatrix;
13213        mRenderNode.getMatrix(matrix);
13214        return matrix;
13215    }
13216
13217    /**
13218     * Returns true if the transform matrix is the identity matrix.
13219     * Recomputes the matrix if necessary.
13220     *
13221     * @return True if the transform matrix is the identity matrix, false otherwise.
13222     */
13223    final boolean hasIdentityMatrix() {
13224        return mRenderNode.hasIdentityMatrix();
13225    }
13226
13227    void ensureTransformationInfo() {
13228        if (mTransformationInfo == null) {
13229            mTransformationInfo = new TransformationInfo();
13230        }
13231    }
13232
13233    /**
13234     * Utility method to retrieve the inverse of the current mMatrix property.
13235     * We cache the matrix to avoid recalculating it when transform properties
13236     * have not changed.
13237     *
13238     * @return The inverse of the current matrix of this view.
13239     * @hide
13240     */
13241    public final Matrix getInverseMatrix() {
13242        ensureTransformationInfo();
13243        if (mTransformationInfo.mInverseMatrix == null) {
13244            mTransformationInfo.mInverseMatrix = new Matrix();
13245        }
13246        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13247        mRenderNode.getInverseMatrix(matrix);
13248        return matrix;
13249    }
13250
13251    /**
13252     * Gets the distance along the Z axis from the camera to this view.
13253     *
13254     * @see #setCameraDistance(float)
13255     *
13256     * @return The distance along the Z axis.
13257     */
13258    public float getCameraDistance() {
13259        final float dpi = mResources.getDisplayMetrics().densityDpi;
13260        return -(mRenderNode.getCameraDistance() * dpi);
13261    }
13262
13263    /**
13264     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13265     * views are drawn) from the camera to this view. The camera's distance
13266     * affects 3D transformations, for instance rotations around the X and Y
13267     * axis. If the rotationX or rotationY properties are changed and this view is
13268     * large (more than half the size of the screen), it is recommended to always
13269     * use a camera distance that's greater than the height (X axis rotation) or
13270     * the width (Y axis rotation) of this view.</p>
13271     *
13272     * <p>The distance of the camera from the view plane can have an affect on the
13273     * perspective distortion of the view when it is rotated around the x or y axis.
13274     * For example, a large distance will result in a large viewing angle, and there
13275     * will not be much perspective distortion of the view as it rotates. A short
13276     * distance may cause much more perspective distortion upon rotation, and can
13277     * also result in some drawing artifacts if the rotated view ends up partially
13278     * behind the camera (which is why the recommendation is to use a distance at
13279     * least as far as the size of the view, if the view is to be rotated.)</p>
13280     *
13281     * <p>The distance is expressed in "depth pixels." The default distance depends
13282     * on the screen density. For instance, on a medium density display, the
13283     * default distance is 1280. On a high density display, the default distance
13284     * is 1920.</p>
13285     *
13286     * <p>If you want to specify a distance that leads to visually consistent
13287     * results across various densities, use the following formula:</p>
13288     * <pre>
13289     * float scale = context.getResources().getDisplayMetrics().density;
13290     * view.setCameraDistance(distance * scale);
13291     * </pre>
13292     *
13293     * <p>The density scale factor of a high density display is 1.5,
13294     * and 1920 = 1280 * 1.5.</p>
13295     *
13296     * @param distance The distance in "depth pixels", if negative the opposite
13297     *        value is used
13298     *
13299     * @see #setRotationX(float)
13300     * @see #setRotationY(float)
13301     */
13302    public void setCameraDistance(float distance) {
13303        final float dpi = mResources.getDisplayMetrics().densityDpi;
13304
13305        invalidateViewProperty(true, false);
13306        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13307        invalidateViewProperty(false, false);
13308
13309        invalidateParentIfNeededAndWasQuickRejected();
13310    }
13311
13312    /**
13313     * The degrees that the view is rotated around the pivot point.
13314     *
13315     * @see #setRotation(float)
13316     * @see #getPivotX()
13317     * @see #getPivotY()
13318     *
13319     * @return The degrees of rotation.
13320     */
13321    @ViewDebug.ExportedProperty(category = "drawing")
13322    public float getRotation() {
13323        return mRenderNode.getRotation();
13324    }
13325
13326    /**
13327     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13328     * result in clockwise rotation.
13329     *
13330     * @param rotation The degrees of rotation.
13331     *
13332     * @see #getRotation()
13333     * @see #getPivotX()
13334     * @see #getPivotY()
13335     * @see #setRotationX(float)
13336     * @see #setRotationY(float)
13337     *
13338     * @attr ref android.R.styleable#View_rotation
13339     */
13340    public void setRotation(float rotation) {
13341        if (rotation != getRotation()) {
13342            // Double-invalidation is necessary to capture view's old and new areas
13343            invalidateViewProperty(true, false);
13344            mRenderNode.setRotation(rotation);
13345            invalidateViewProperty(false, true);
13346
13347            invalidateParentIfNeededAndWasQuickRejected();
13348            notifySubtreeAccessibilityStateChangedIfNeeded();
13349        }
13350    }
13351
13352    /**
13353     * The degrees that the view is rotated around the vertical axis through the pivot point.
13354     *
13355     * @see #getPivotX()
13356     * @see #getPivotY()
13357     * @see #setRotationY(float)
13358     *
13359     * @return The degrees of Y rotation.
13360     */
13361    @ViewDebug.ExportedProperty(category = "drawing")
13362    public float getRotationY() {
13363        return mRenderNode.getRotationY();
13364    }
13365
13366    /**
13367     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13368     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13369     * down the y axis.
13370     *
13371     * When rotating large views, it is recommended to adjust the camera distance
13372     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13373     *
13374     * @param rotationY The degrees of Y rotation.
13375     *
13376     * @see #getRotationY()
13377     * @see #getPivotX()
13378     * @see #getPivotY()
13379     * @see #setRotation(float)
13380     * @see #setRotationX(float)
13381     * @see #setCameraDistance(float)
13382     *
13383     * @attr ref android.R.styleable#View_rotationY
13384     */
13385    public void setRotationY(float rotationY) {
13386        if (rotationY != getRotationY()) {
13387            invalidateViewProperty(true, false);
13388            mRenderNode.setRotationY(rotationY);
13389            invalidateViewProperty(false, true);
13390
13391            invalidateParentIfNeededAndWasQuickRejected();
13392            notifySubtreeAccessibilityStateChangedIfNeeded();
13393        }
13394    }
13395
13396    /**
13397     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13398     *
13399     * @see #getPivotX()
13400     * @see #getPivotY()
13401     * @see #setRotationX(float)
13402     *
13403     * @return The degrees of X rotation.
13404     */
13405    @ViewDebug.ExportedProperty(category = "drawing")
13406    public float getRotationX() {
13407        return mRenderNode.getRotationX();
13408    }
13409
13410    /**
13411     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13412     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13413     * x axis.
13414     *
13415     * When rotating large views, it is recommended to adjust the camera distance
13416     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13417     *
13418     * @param rotationX The degrees of X rotation.
13419     *
13420     * @see #getRotationX()
13421     * @see #getPivotX()
13422     * @see #getPivotY()
13423     * @see #setRotation(float)
13424     * @see #setRotationY(float)
13425     * @see #setCameraDistance(float)
13426     *
13427     * @attr ref android.R.styleable#View_rotationX
13428     */
13429    public void setRotationX(float rotationX) {
13430        if (rotationX != getRotationX()) {
13431            invalidateViewProperty(true, false);
13432            mRenderNode.setRotationX(rotationX);
13433            invalidateViewProperty(false, true);
13434
13435            invalidateParentIfNeededAndWasQuickRejected();
13436            notifySubtreeAccessibilityStateChangedIfNeeded();
13437        }
13438    }
13439
13440    /**
13441     * The amount that the view is scaled in x around the pivot point, as a proportion of
13442     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13443     *
13444     * <p>By default, this is 1.0f.
13445     *
13446     * @see #getPivotX()
13447     * @see #getPivotY()
13448     * @return The scaling factor.
13449     */
13450    @ViewDebug.ExportedProperty(category = "drawing")
13451    public float getScaleX() {
13452        return mRenderNode.getScaleX();
13453    }
13454
13455    /**
13456     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13457     * the view's unscaled width. A value of 1 means that no scaling is applied.
13458     *
13459     * @param scaleX The scaling factor.
13460     * @see #getPivotX()
13461     * @see #getPivotY()
13462     *
13463     * @attr ref android.R.styleable#View_scaleX
13464     */
13465    public void setScaleX(float scaleX) {
13466        if (scaleX != getScaleX()) {
13467            invalidateViewProperty(true, false);
13468            mRenderNode.setScaleX(scaleX);
13469            invalidateViewProperty(false, true);
13470
13471            invalidateParentIfNeededAndWasQuickRejected();
13472            notifySubtreeAccessibilityStateChangedIfNeeded();
13473        }
13474    }
13475
13476    /**
13477     * The amount that the view is scaled in y around the pivot point, as a proportion of
13478     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13479     *
13480     * <p>By default, this is 1.0f.
13481     *
13482     * @see #getPivotX()
13483     * @see #getPivotY()
13484     * @return The scaling factor.
13485     */
13486    @ViewDebug.ExportedProperty(category = "drawing")
13487    public float getScaleY() {
13488        return mRenderNode.getScaleY();
13489    }
13490
13491    /**
13492     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13493     * the view's unscaled width. A value of 1 means that no scaling is applied.
13494     *
13495     * @param scaleY The scaling factor.
13496     * @see #getPivotX()
13497     * @see #getPivotY()
13498     *
13499     * @attr ref android.R.styleable#View_scaleY
13500     */
13501    public void setScaleY(float scaleY) {
13502        if (scaleY != getScaleY()) {
13503            invalidateViewProperty(true, false);
13504            mRenderNode.setScaleY(scaleY);
13505            invalidateViewProperty(false, true);
13506
13507            invalidateParentIfNeededAndWasQuickRejected();
13508            notifySubtreeAccessibilityStateChangedIfNeeded();
13509        }
13510    }
13511
13512    /**
13513     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13514     * and {@link #setScaleX(float) scaled}.
13515     *
13516     * @see #getRotation()
13517     * @see #getScaleX()
13518     * @see #getScaleY()
13519     * @see #getPivotY()
13520     * @return The x location of the pivot point.
13521     *
13522     * @attr ref android.R.styleable#View_transformPivotX
13523     */
13524    @ViewDebug.ExportedProperty(category = "drawing")
13525    public float getPivotX() {
13526        return mRenderNode.getPivotX();
13527    }
13528
13529    /**
13530     * Sets the x location of the point around which the view is
13531     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13532     * By default, the pivot point is centered on the object.
13533     * Setting this property disables this behavior and causes the view to use only the
13534     * explicitly set pivotX and pivotY values.
13535     *
13536     * @param pivotX The x location of the pivot point.
13537     * @see #getRotation()
13538     * @see #getScaleX()
13539     * @see #getScaleY()
13540     * @see #getPivotY()
13541     *
13542     * @attr ref android.R.styleable#View_transformPivotX
13543     */
13544    public void setPivotX(float pivotX) {
13545        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13546            invalidateViewProperty(true, false);
13547            mRenderNode.setPivotX(pivotX);
13548            invalidateViewProperty(false, true);
13549
13550            invalidateParentIfNeededAndWasQuickRejected();
13551        }
13552    }
13553
13554    /**
13555     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13556     * and {@link #setScaleY(float) scaled}.
13557     *
13558     * @see #getRotation()
13559     * @see #getScaleX()
13560     * @see #getScaleY()
13561     * @see #getPivotY()
13562     * @return The y location of the pivot point.
13563     *
13564     * @attr ref android.R.styleable#View_transformPivotY
13565     */
13566    @ViewDebug.ExportedProperty(category = "drawing")
13567    public float getPivotY() {
13568        return mRenderNode.getPivotY();
13569    }
13570
13571    /**
13572     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13573     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13574     * Setting this property disables this behavior and causes the view to use only the
13575     * explicitly set pivotX and pivotY values.
13576     *
13577     * @param pivotY The y location of the pivot point.
13578     * @see #getRotation()
13579     * @see #getScaleX()
13580     * @see #getScaleY()
13581     * @see #getPivotY()
13582     *
13583     * @attr ref android.R.styleable#View_transformPivotY
13584     */
13585    public void setPivotY(float pivotY) {
13586        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13587            invalidateViewProperty(true, false);
13588            mRenderNode.setPivotY(pivotY);
13589            invalidateViewProperty(false, true);
13590
13591            invalidateParentIfNeededAndWasQuickRejected();
13592        }
13593    }
13594
13595    /**
13596     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13597     * completely transparent and 1 means the view is completely opaque.
13598     *
13599     * <p>By default this is 1.0f.
13600     * @return The opacity of the view.
13601     */
13602    @ViewDebug.ExportedProperty(category = "drawing")
13603    public float getAlpha() {
13604        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13605    }
13606
13607    /**
13608     * Sets the behavior for overlapping rendering for this view (see {@link
13609     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13610     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13611     * providing the value which is then used internally. That is, when {@link
13612     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13613     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13614     * instead.
13615     *
13616     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13617     * instead of that returned by {@link #hasOverlappingRendering()}.
13618     *
13619     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13620     */
13621    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13622        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13623        if (hasOverlappingRendering) {
13624            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13625        } else {
13626            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13627        }
13628    }
13629
13630    /**
13631     * Returns the value for overlapping rendering that is used internally. This is either
13632     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13633     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13634     *
13635     * @return The value for overlapping rendering being used internally.
13636     */
13637    public final boolean getHasOverlappingRendering() {
13638        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13639                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13640                hasOverlappingRendering();
13641    }
13642
13643    /**
13644     * Returns whether this View has content which overlaps.
13645     *
13646     * <p>This function, intended to be overridden by specific View types, is an optimization when
13647     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13648     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13649     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13650     * directly. An example of overlapping rendering is a TextView with a background image, such as
13651     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13652     * ImageView with only the foreground image. The default implementation returns true; subclasses
13653     * should override if they have cases which can be optimized.</p>
13654     *
13655     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13656     * necessitates that a View return true if it uses the methods internally without passing the
13657     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13658     *
13659     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13660     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13661     *
13662     * @return true if the content in this view might overlap, false otherwise.
13663     */
13664    @ViewDebug.ExportedProperty(category = "drawing")
13665    public boolean hasOverlappingRendering() {
13666        return true;
13667    }
13668
13669    /**
13670     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13671     * completely transparent and 1 means the view is completely opaque.
13672     *
13673     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13674     * can have significant performance implications, especially for large views. It is best to use
13675     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13676     *
13677     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13678     * strongly recommended for performance reasons to either override
13679     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13680     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13681     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13682     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13683     * of rendering cost, even for simple or small views. Starting with
13684     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13685     * applied to the view at the rendering level.</p>
13686     *
13687     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13688     * responsible for applying the opacity itself.</p>
13689     *
13690     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13691     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13692     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13693     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13694     *
13695     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13696     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13697     * {@link #hasOverlappingRendering}.</p>
13698     *
13699     * @param alpha The opacity of the view.
13700     *
13701     * @see #hasOverlappingRendering()
13702     * @see #setLayerType(int, android.graphics.Paint)
13703     *
13704     * @attr ref android.R.styleable#View_alpha
13705     */
13706    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13707        ensureTransformationInfo();
13708        if (mTransformationInfo.mAlpha != alpha) {
13709            // Report visibility changes, which can affect children, to accessibility
13710            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13711                notifySubtreeAccessibilityStateChangedIfNeeded();
13712            }
13713            mTransformationInfo.mAlpha = alpha;
13714            if (onSetAlpha((int) (alpha * 255))) {
13715                mPrivateFlags |= PFLAG_ALPHA_SET;
13716                // subclass is handling alpha - don't optimize rendering cache invalidation
13717                invalidateParentCaches();
13718                invalidate(true);
13719            } else {
13720                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13721                invalidateViewProperty(true, false);
13722                mRenderNode.setAlpha(getFinalAlpha());
13723            }
13724        }
13725    }
13726
13727    /**
13728     * Faster version of setAlpha() which performs the same steps except there are
13729     * no calls to invalidate(). The caller of this function should perform proper invalidation
13730     * on the parent and this object. The return value indicates whether the subclass handles
13731     * alpha (the return value for onSetAlpha()).
13732     *
13733     * @param alpha The new value for the alpha property
13734     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13735     *         the new value for the alpha property is different from the old value
13736     */
13737    boolean setAlphaNoInvalidation(float alpha) {
13738        ensureTransformationInfo();
13739        if (mTransformationInfo.mAlpha != alpha) {
13740            mTransformationInfo.mAlpha = alpha;
13741            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13742            if (subclassHandlesAlpha) {
13743                mPrivateFlags |= PFLAG_ALPHA_SET;
13744                return true;
13745            } else {
13746                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13747                mRenderNode.setAlpha(getFinalAlpha());
13748            }
13749        }
13750        return false;
13751    }
13752
13753    /**
13754     * This property is hidden and intended only for use by the Fade transition, which
13755     * animates it to produce a visual translucency that does not side-effect (or get
13756     * affected by) the real alpha property. This value is composited with the other
13757     * alpha value (and the AlphaAnimation value, when that is present) to produce
13758     * a final visual translucency result, which is what is passed into the DisplayList.
13759     *
13760     * @hide
13761     */
13762    public void setTransitionAlpha(float alpha) {
13763        ensureTransformationInfo();
13764        if (mTransformationInfo.mTransitionAlpha != alpha) {
13765            mTransformationInfo.mTransitionAlpha = alpha;
13766            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13767            invalidateViewProperty(true, false);
13768            mRenderNode.setAlpha(getFinalAlpha());
13769        }
13770    }
13771
13772    /**
13773     * Calculates the visual alpha of this view, which is a combination of the actual
13774     * alpha value and the transitionAlpha value (if set).
13775     */
13776    private float getFinalAlpha() {
13777        if (mTransformationInfo != null) {
13778            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13779        }
13780        return 1;
13781    }
13782
13783    /**
13784     * This property is hidden and intended only for use by the Fade transition, which
13785     * animates it to produce a visual translucency that does not side-effect (or get
13786     * affected by) the real alpha property. This value is composited with the other
13787     * alpha value (and the AlphaAnimation value, when that is present) to produce
13788     * a final visual translucency result, which is what is passed into the DisplayList.
13789     *
13790     * @hide
13791     */
13792    @ViewDebug.ExportedProperty(category = "drawing")
13793    public float getTransitionAlpha() {
13794        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13795    }
13796
13797    /**
13798     * Top position of this view relative to its parent.
13799     *
13800     * @return The top of this view, in pixels.
13801     */
13802    @ViewDebug.CapturedViewProperty
13803    public final int getTop() {
13804        return mTop;
13805    }
13806
13807    /**
13808     * Sets the top position of this view relative to its parent. This method is meant to be called
13809     * by the layout system and should not generally be called otherwise, because the property
13810     * may be changed at any time by the layout.
13811     *
13812     * @param top The top of this view, in pixels.
13813     */
13814    public final void setTop(int top) {
13815        if (top != mTop) {
13816            final boolean matrixIsIdentity = hasIdentityMatrix();
13817            if (matrixIsIdentity) {
13818                if (mAttachInfo != null) {
13819                    int minTop;
13820                    int yLoc;
13821                    if (top < mTop) {
13822                        minTop = top;
13823                        yLoc = top - mTop;
13824                    } else {
13825                        minTop = mTop;
13826                        yLoc = 0;
13827                    }
13828                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13829                }
13830            } else {
13831                // Double-invalidation is necessary to capture view's old and new areas
13832                invalidate(true);
13833            }
13834
13835            int width = mRight - mLeft;
13836            int oldHeight = mBottom - mTop;
13837
13838            mTop = top;
13839            mRenderNode.setTop(mTop);
13840
13841            sizeChange(width, mBottom - mTop, width, oldHeight);
13842
13843            if (!matrixIsIdentity) {
13844                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13845                invalidate(true);
13846            }
13847            mBackgroundSizeChanged = true;
13848            if (mForegroundInfo != null) {
13849                mForegroundInfo.mBoundsChanged = true;
13850            }
13851            invalidateParentIfNeeded();
13852            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13853                // View was rejected last time it was drawn by its parent; this may have changed
13854                invalidateParentIfNeeded();
13855            }
13856        }
13857    }
13858
13859    /**
13860     * Bottom position of this view relative to its parent.
13861     *
13862     * @return The bottom of this view, in pixels.
13863     */
13864    @ViewDebug.CapturedViewProperty
13865    public final int getBottom() {
13866        return mBottom;
13867    }
13868
13869    /**
13870     * True if this view has changed since the last time being drawn.
13871     *
13872     * @return The dirty state of this view.
13873     */
13874    public boolean isDirty() {
13875        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13876    }
13877
13878    /**
13879     * Sets the bottom position of this view relative to its parent. This method is meant to be
13880     * called by the layout system and should not generally be called otherwise, because the
13881     * property may be changed at any time by the layout.
13882     *
13883     * @param bottom The bottom of this view, in pixels.
13884     */
13885    public final void setBottom(int bottom) {
13886        if (bottom != mBottom) {
13887            final boolean matrixIsIdentity = hasIdentityMatrix();
13888            if (matrixIsIdentity) {
13889                if (mAttachInfo != null) {
13890                    int maxBottom;
13891                    if (bottom < mBottom) {
13892                        maxBottom = mBottom;
13893                    } else {
13894                        maxBottom = bottom;
13895                    }
13896                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13897                }
13898            } else {
13899                // Double-invalidation is necessary to capture view's old and new areas
13900                invalidate(true);
13901            }
13902
13903            int width = mRight - mLeft;
13904            int oldHeight = mBottom - mTop;
13905
13906            mBottom = bottom;
13907            mRenderNode.setBottom(mBottom);
13908
13909            sizeChange(width, mBottom - mTop, width, oldHeight);
13910
13911            if (!matrixIsIdentity) {
13912                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13913                invalidate(true);
13914            }
13915            mBackgroundSizeChanged = true;
13916            if (mForegroundInfo != null) {
13917                mForegroundInfo.mBoundsChanged = true;
13918            }
13919            invalidateParentIfNeeded();
13920            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13921                // View was rejected last time it was drawn by its parent; this may have changed
13922                invalidateParentIfNeeded();
13923            }
13924        }
13925    }
13926
13927    /**
13928     * Left position of this view relative to its parent.
13929     *
13930     * @return The left edge of this view, in pixels.
13931     */
13932    @ViewDebug.CapturedViewProperty
13933    public final int getLeft() {
13934        return mLeft;
13935    }
13936
13937    /**
13938     * Sets the left position of this view relative to its parent. This method is meant to be called
13939     * by the layout system and should not generally be called otherwise, because the property
13940     * may be changed at any time by the layout.
13941     *
13942     * @param left The left of this view, in pixels.
13943     */
13944    public final void setLeft(int left) {
13945        if (left != mLeft) {
13946            final boolean matrixIsIdentity = hasIdentityMatrix();
13947            if (matrixIsIdentity) {
13948                if (mAttachInfo != null) {
13949                    int minLeft;
13950                    int xLoc;
13951                    if (left < mLeft) {
13952                        minLeft = left;
13953                        xLoc = left - mLeft;
13954                    } else {
13955                        minLeft = mLeft;
13956                        xLoc = 0;
13957                    }
13958                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
13959                }
13960            } else {
13961                // Double-invalidation is necessary to capture view's old and new areas
13962                invalidate(true);
13963            }
13964
13965            int oldWidth = mRight - mLeft;
13966            int height = mBottom - mTop;
13967
13968            mLeft = left;
13969            mRenderNode.setLeft(left);
13970
13971            sizeChange(mRight - mLeft, height, oldWidth, height);
13972
13973            if (!matrixIsIdentity) {
13974                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13975                invalidate(true);
13976            }
13977            mBackgroundSizeChanged = true;
13978            if (mForegroundInfo != null) {
13979                mForegroundInfo.mBoundsChanged = true;
13980            }
13981            invalidateParentIfNeeded();
13982            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13983                // View was rejected last time it was drawn by its parent; this may have changed
13984                invalidateParentIfNeeded();
13985            }
13986        }
13987    }
13988
13989    /**
13990     * Right position of this view relative to its parent.
13991     *
13992     * @return The right edge of this view, in pixels.
13993     */
13994    @ViewDebug.CapturedViewProperty
13995    public final int getRight() {
13996        return mRight;
13997    }
13998
13999    /**
14000     * Sets the right position of this view relative to its parent. This method is meant to be called
14001     * by the layout system and should not generally be called otherwise, because the property
14002     * may be changed at any time by the layout.
14003     *
14004     * @param right The right of this view, in pixels.
14005     */
14006    public final void setRight(int right) {
14007        if (right != mRight) {
14008            final boolean matrixIsIdentity = hasIdentityMatrix();
14009            if (matrixIsIdentity) {
14010                if (mAttachInfo != null) {
14011                    int maxRight;
14012                    if (right < mRight) {
14013                        maxRight = mRight;
14014                    } else {
14015                        maxRight = right;
14016                    }
14017                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14018                }
14019            } else {
14020                // Double-invalidation is necessary to capture view's old and new areas
14021                invalidate(true);
14022            }
14023
14024            int oldWidth = mRight - mLeft;
14025            int height = mBottom - mTop;
14026
14027            mRight = right;
14028            mRenderNode.setRight(mRight);
14029
14030            sizeChange(mRight - mLeft, height, oldWidth, height);
14031
14032            if (!matrixIsIdentity) {
14033                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14034                invalidate(true);
14035            }
14036            mBackgroundSizeChanged = true;
14037            if (mForegroundInfo != null) {
14038                mForegroundInfo.mBoundsChanged = true;
14039            }
14040            invalidateParentIfNeeded();
14041            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14042                // View was rejected last time it was drawn by its parent; this may have changed
14043                invalidateParentIfNeeded();
14044            }
14045        }
14046    }
14047
14048    /**
14049     * The visual x position of this view, in pixels. This is equivalent to the
14050     * {@link #setTranslationX(float) translationX} property plus the current
14051     * {@link #getLeft() left} property.
14052     *
14053     * @return The visual x position of this view, in pixels.
14054     */
14055    @ViewDebug.ExportedProperty(category = "drawing")
14056    public float getX() {
14057        return mLeft + getTranslationX();
14058    }
14059
14060    /**
14061     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14062     * {@link #setTranslationX(float) translationX} property to be the difference between
14063     * the x value passed in and the current {@link #getLeft() left} property.
14064     *
14065     * @param x The visual x position of this view, in pixels.
14066     */
14067    public void setX(float x) {
14068        setTranslationX(x - mLeft);
14069    }
14070
14071    /**
14072     * The visual y position of this view, in pixels. This is equivalent to the
14073     * {@link #setTranslationY(float) translationY} property plus the current
14074     * {@link #getTop() top} property.
14075     *
14076     * @return The visual y position of this view, in pixels.
14077     */
14078    @ViewDebug.ExportedProperty(category = "drawing")
14079    public float getY() {
14080        return mTop + getTranslationY();
14081    }
14082
14083    /**
14084     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14085     * {@link #setTranslationY(float) translationY} property to be the difference between
14086     * the y value passed in and the current {@link #getTop() top} property.
14087     *
14088     * @param y The visual y position of this view, in pixels.
14089     */
14090    public void setY(float y) {
14091        setTranslationY(y - mTop);
14092    }
14093
14094    /**
14095     * The visual z position of this view, in pixels. This is equivalent to the
14096     * {@link #setTranslationZ(float) translationZ} property plus the current
14097     * {@link #getElevation() elevation} property.
14098     *
14099     * @return The visual z position of this view, in pixels.
14100     */
14101    @ViewDebug.ExportedProperty(category = "drawing")
14102    public float getZ() {
14103        return getElevation() + getTranslationZ();
14104    }
14105
14106    /**
14107     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14108     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14109     * the x value passed in and the current {@link #getElevation() elevation} property.
14110     *
14111     * @param z The visual z position of this view, in pixels.
14112     */
14113    public void setZ(float z) {
14114        setTranslationZ(z - getElevation());
14115    }
14116
14117    /**
14118     * The base elevation of this view relative to its parent, in pixels.
14119     *
14120     * @return The base depth position of the view, in pixels.
14121     */
14122    @ViewDebug.ExportedProperty(category = "drawing")
14123    public float getElevation() {
14124        return mRenderNode.getElevation();
14125    }
14126
14127    /**
14128     * Sets the base elevation of this view, in pixels.
14129     *
14130     * @attr ref android.R.styleable#View_elevation
14131     */
14132    public void setElevation(float elevation) {
14133        if (elevation != getElevation()) {
14134            invalidateViewProperty(true, false);
14135            mRenderNode.setElevation(elevation);
14136            invalidateViewProperty(false, true);
14137
14138            invalidateParentIfNeededAndWasQuickRejected();
14139        }
14140    }
14141
14142    /**
14143     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14144     * This position is post-layout, in addition to wherever the object's
14145     * layout placed it.
14146     *
14147     * @return The horizontal position of this view relative to its left position, in pixels.
14148     */
14149    @ViewDebug.ExportedProperty(category = "drawing")
14150    public float getTranslationX() {
14151        return mRenderNode.getTranslationX();
14152    }
14153
14154    /**
14155     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14156     * This effectively positions the object post-layout, in addition to wherever the object's
14157     * layout placed it.
14158     *
14159     * @param translationX The horizontal position of this view relative to its left position,
14160     * in pixels.
14161     *
14162     * @attr ref android.R.styleable#View_translationX
14163     */
14164    public void setTranslationX(float translationX) {
14165        if (translationX != getTranslationX()) {
14166            invalidateViewProperty(true, false);
14167            mRenderNode.setTranslationX(translationX);
14168            invalidateViewProperty(false, true);
14169
14170            invalidateParentIfNeededAndWasQuickRejected();
14171            notifySubtreeAccessibilityStateChangedIfNeeded();
14172        }
14173    }
14174
14175    /**
14176     * The vertical location of this view relative to its {@link #getTop() top} position.
14177     * This position is post-layout, in addition to wherever the object's
14178     * layout placed it.
14179     *
14180     * @return The vertical position of this view relative to its top position,
14181     * in pixels.
14182     */
14183    @ViewDebug.ExportedProperty(category = "drawing")
14184    public float getTranslationY() {
14185        return mRenderNode.getTranslationY();
14186    }
14187
14188    /**
14189     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14190     * This effectively positions the object post-layout, in addition to wherever the object's
14191     * layout placed it.
14192     *
14193     * @param translationY The vertical position of this view relative to its top position,
14194     * in pixels.
14195     *
14196     * @attr ref android.R.styleable#View_translationY
14197     */
14198    public void setTranslationY(float translationY) {
14199        if (translationY != getTranslationY()) {
14200            invalidateViewProperty(true, false);
14201            mRenderNode.setTranslationY(translationY);
14202            invalidateViewProperty(false, true);
14203
14204            invalidateParentIfNeededAndWasQuickRejected();
14205            notifySubtreeAccessibilityStateChangedIfNeeded();
14206        }
14207    }
14208
14209    /**
14210     * The depth location of this view relative to its {@link #getElevation() elevation}.
14211     *
14212     * @return The depth of this view relative to its elevation.
14213     */
14214    @ViewDebug.ExportedProperty(category = "drawing")
14215    public float getTranslationZ() {
14216        return mRenderNode.getTranslationZ();
14217    }
14218
14219    /**
14220     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14221     *
14222     * @attr ref android.R.styleable#View_translationZ
14223     */
14224    public void setTranslationZ(float translationZ) {
14225        if (translationZ != getTranslationZ()) {
14226            invalidateViewProperty(true, false);
14227            mRenderNode.setTranslationZ(translationZ);
14228            invalidateViewProperty(false, true);
14229
14230            invalidateParentIfNeededAndWasQuickRejected();
14231        }
14232    }
14233
14234    /** @hide */
14235    public void setAnimationMatrix(Matrix matrix) {
14236        invalidateViewProperty(true, false);
14237        mRenderNode.setAnimationMatrix(matrix);
14238        invalidateViewProperty(false, true);
14239
14240        invalidateParentIfNeededAndWasQuickRejected();
14241    }
14242
14243    /**
14244     * Returns the current StateListAnimator if exists.
14245     *
14246     * @return StateListAnimator or null if it does not exists
14247     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14248     */
14249    public StateListAnimator getStateListAnimator() {
14250        return mStateListAnimator;
14251    }
14252
14253    /**
14254     * Attaches the provided StateListAnimator to this View.
14255     * <p>
14256     * Any previously attached StateListAnimator will be detached.
14257     *
14258     * @param stateListAnimator The StateListAnimator to update the view
14259     * @see android.animation.StateListAnimator
14260     */
14261    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14262        if (mStateListAnimator == stateListAnimator) {
14263            return;
14264        }
14265        if (mStateListAnimator != null) {
14266            mStateListAnimator.setTarget(null);
14267        }
14268        mStateListAnimator = stateListAnimator;
14269        if (stateListAnimator != null) {
14270            stateListAnimator.setTarget(this);
14271            if (isAttachedToWindow()) {
14272                stateListAnimator.setState(getDrawableState());
14273            }
14274        }
14275    }
14276
14277    /**
14278     * Returns whether the Outline should be used to clip the contents of the View.
14279     * <p>
14280     * Note that this flag will only be respected if the View's Outline returns true from
14281     * {@link Outline#canClip()}.
14282     *
14283     * @see #setOutlineProvider(ViewOutlineProvider)
14284     * @see #setClipToOutline(boolean)
14285     */
14286    public final boolean getClipToOutline() {
14287        return mRenderNode.getClipToOutline();
14288    }
14289
14290    /**
14291     * Sets whether the View's Outline should be used to clip the contents of the View.
14292     * <p>
14293     * Only a single non-rectangular clip can be applied on a View at any time.
14294     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14295     * circular reveal} animation take priority over Outline clipping, and
14296     * child Outline clipping takes priority over Outline clipping done by a
14297     * parent.
14298     * <p>
14299     * Note that this flag will only be respected if the View's Outline returns true from
14300     * {@link Outline#canClip()}.
14301     *
14302     * @see #setOutlineProvider(ViewOutlineProvider)
14303     * @see #getClipToOutline()
14304     */
14305    public void setClipToOutline(boolean clipToOutline) {
14306        damageInParent();
14307        if (getClipToOutline() != clipToOutline) {
14308            mRenderNode.setClipToOutline(clipToOutline);
14309        }
14310    }
14311
14312    // correspond to the enum values of View_outlineProvider
14313    private static final int PROVIDER_BACKGROUND = 0;
14314    private static final int PROVIDER_NONE = 1;
14315    private static final int PROVIDER_BOUNDS = 2;
14316    private static final int PROVIDER_PADDED_BOUNDS = 3;
14317    private void setOutlineProviderFromAttribute(int providerInt) {
14318        switch (providerInt) {
14319            case PROVIDER_BACKGROUND:
14320                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14321                break;
14322            case PROVIDER_NONE:
14323                setOutlineProvider(null);
14324                break;
14325            case PROVIDER_BOUNDS:
14326                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14327                break;
14328            case PROVIDER_PADDED_BOUNDS:
14329                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14330                break;
14331        }
14332    }
14333
14334    /**
14335     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14336     * the shape of the shadow it casts, and enables outline clipping.
14337     * <p>
14338     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14339     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14340     * outline provider with this method allows this behavior to be overridden.
14341     * <p>
14342     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14343     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14344     * <p>
14345     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14346     *
14347     * @see #setClipToOutline(boolean)
14348     * @see #getClipToOutline()
14349     * @see #getOutlineProvider()
14350     */
14351    public void setOutlineProvider(ViewOutlineProvider provider) {
14352        mOutlineProvider = provider;
14353        invalidateOutline();
14354    }
14355
14356    /**
14357     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14358     * that defines the shape of the shadow it casts, and enables outline clipping.
14359     *
14360     * @see #setOutlineProvider(ViewOutlineProvider)
14361     */
14362    public ViewOutlineProvider getOutlineProvider() {
14363        return mOutlineProvider;
14364    }
14365
14366    /**
14367     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14368     *
14369     * @see #setOutlineProvider(ViewOutlineProvider)
14370     */
14371    public void invalidateOutline() {
14372        rebuildOutline();
14373
14374        notifySubtreeAccessibilityStateChangedIfNeeded();
14375        invalidateViewProperty(false, false);
14376    }
14377
14378    /**
14379     * Internal version of {@link #invalidateOutline()} which invalidates the
14380     * outline without invalidating the view itself. This is intended to be called from
14381     * within methods in the View class itself which are the result of the view being
14382     * invalidated already. For example, when we are drawing the background of a View,
14383     * we invalidate the outline in case it changed in the meantime, but we do not
14384     * need to invalidate the view because we're already drawing the background as part
14385     * of drawing the view in response to an earlier invalidation of the view.
14386     */
14387    private void rebuildOutline() {
14388        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14389        if (mAttachInfo == null) return;
14390
14391        if (mOutlineProvider == null) {
14392            // no provider, remove outline
14393            mRenderNode.setOutline(null);
14394        } else {
14395            final Outline outline = mAttachInfo.mTmpOutline;
14396            outline.setEmpty();
14397            outline.setAlpha(1.0f);
14398
14399            mOutlineProvider.getOutline(this, outline);
14400            mRenderNode.setOutline(outline);
14401        }
14402    }
14403
14404    /**
14405     * HierarchyViewer only
14406     *
14407     * @hide
14408     */
14409    @ViewDebug.ExportedProperty(category = "drawing")
14410    public boolean hasShadow() {
14411        return mRenderNode.hasShadow();
14412    }
14413
14414
14415    /** @hide */
14416    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14417        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14418        invalidateViewProperty(false, false);
14419    }
14420
14421    /**
14422     * Hit rectangle in parent's coordinates
14423     *
14424     * @param outRect The hit rectangle of the view.
14425     */
14426    public void getHitRect(Rect outRect) {
14427        if (hasIdentityMatrix() || mAttachInfo == null) {
14428            outRect.set(mLeft, mTop, mRight, mBottom);
14429        } else {
14430            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14431            tmpRect.set(0, 0, getWidth(), getHeight());
14432            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14433            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14434                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14435        }
14436    }
14437
14438    /**
14439     * Determines whether the given point, in local coordinates is inside the view.
14440     */
14441    /*package*/ final boolean pointInView(float localX, float localY) {
14442        return pointInView(localX, localY, 0);
14443    }
14444
14445    /**
14446     * Utility method to determine whether the given point, in local coordinates,
14447     * is inside the view, where the area of the view is expanded by the slop factor.
14448     * This method is called while processing touch-move events to determine if the event
14449     * is still within the view.
14450     *
14451     * @hide
14452     */
14453    public boolean pointInView(float localX, float localY, float slop) {
14454        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14455                localY < ((mBottom - mTop) + slop);
14456    }
14457
14458    /**
14459     * When a view has focus and the user navigates away from it, the next view is searched for
14460     * starting from the rectangle filled in by this method.
14461     *
14462     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14463     * of the view.  However, if your view maintains some idea of internal selection,
14464     * such as a cursor, or a selected row or column, you should override this method and
14465     * fill in a more specific rectangle.
14466     *
14467     * @param r The rectangle to fill in, in this view's coordinates.
14468     */
14469    public void getFocusedRect(Rect r) {
14470        getDrawingRect(r);
14471    }
14472
14473    /**
14474     * If some part of this view is not clipped by any of its parents, then
14475     * return that area in r in global (root) coordinates. To convert r to local
14476     * coordinates (without taking possible View rotations into account), offset
14477     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14478     * If the view is completely clipped or translated out, return false.
14479     *
14480     * @param r If true is returned, r holds the global coordinates of the
14481     *        visible portion of this view.
14482     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14483     *        between this view and its root. globalOffet may be null.
14484     * @return true if r is non-empty (i.e. part of the view is visible at the
14485     *         root level.
14486     */
14487    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14488        int width = mRight - mLeft;
14489        int height = mBottom - mTop;
14490        if (width > 0 && height > 0) {
14491            r.set(0, 0, width, height);
14492            if (globalOffset != null) {
14493                globalOffset.set(-mScrollX, -mScrollY);
14494            }
14495            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14496        }
14497        return false;
14498    }
14499
14500    public final boolean getGlobalVisibleRect(Rect r) {
14501        return getGlobalVisibleRect(r, null);
14502    }
14503
14504    public final boolean getLocalVisibleRect(Rect r) {
14505        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14506        if (getGlobalVisibleRect(r, offset)) {
14507            r.offset(-offset.x, -offset.y); // make r local
14508            return true;
14509        }
14510        return false;
14511    }
14512
14513    /**
14514     * Offset this view's vertical location by the specified number of pixels.
14515     *
14516     * @param offset the number of pixels to offset the view by
14517     */
14518    public void offsetTopAndBottom(int offset) {
14519        if (offset != 0) {
14520            final boolean matrixIsIdentity = hasIdentityMatrix();
14521            if (matrixIsIdentity) {
14522                if (isHardwareAccelerated()) {
14523                    invalidateViewProperty(false, false);
14524                } else {
14525                    final ViewParent p = mParent;
14526                    if (p != null && mAttachInfo != null) {
14527                        final Rect r = mAttachInfo.mTmpInvalRect;
14528                        int minTop;
14529                        int maxBottom;
14530                        int yLoc;
14531                        if (offset < 0) {
14532                            minTop = mTop + offset;
14533                            maxBottom = mBottom;
14534                            yLoc = offset;
14535                        } else {
14536                            minTop = mTop;
14537                            maxBottom = mBottom + offset;
14538                            yLoc = 0;
14539                        }
14540                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14541                        p.invalidateChild(this, r);
14542                    }
14543                }
14544            } else {
14545                invalidateViewProperty(false, false);
14546            }
14547
14548            mTop += offset;
14549            mBottom += offset;
14550            mRenderNode.offsetTopAndBottom(offset);
14551            if (isHardwareAccelerated()) {
14552                invalidateViewProperty(false, false);
14553                invalidateParentIfNeededAndWasQuickRejected();
14554            } else {
14555                if (!matrixIsIdentity) {
14556                    invalidateViewProperty(false, true);
14557                }
14558                invalidateParentIfNeeded();
14559            }
14560            notifySubtreeAccessibilityStateChangedIfNeeded();
14561        }
14562    }
14563
14564    /**
14565     * Offset this view's horizontal location by the specified amount of pixels.
14566     *
14567     * @param offset the number of pixels to offset the view by
14568     */
14569    public void offsetLeftAndRight(int offset) {
14570        if (offset != 0) {
14571            final boolean matrixIsIdentity = hasIdentityMatrix();
14572            if (matrixIsIdentity) {
14573                if (isHardwareAccelerated()) {
14574                    invalidateViewProperty(false, false);
14575                } else {
14576                    final ViewParent p = mParent;
14577                    if (p != null && mAttachInfo != null) {
14578                        final Rect r = mAttachInfo.mTmpInvalRect;
14579                        int minLeft;
14580                        int maxRight;
14581                        if (offset < 0) {
14582                            minLeft = mLeft + offset;
14583                            maxRight = mRight;
14584                        } else {
14585                            minLeft = mLeft;
14586                            maxRight = mRight + offset;
14587                        }
14588                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14589                        p.invalidateChild(this, r);
14590                    }
14591                }
14592            } else {
14593                invalidateViewProperty(false, false);
14594            }
14595
14596            mLeft += offset;
14597            mRight += offset;
14598            mRenderNode.offsetLeftAndRight(offset);
14599            if (isHardwareAccelerated()) {
14600                invalidateViewProperty(false, false);
14601                invalidateParentIfNeededAndWasQuickRejected();
14602            } else {
14603                if (!matrixIsIdentity) {
14604                    invalidateViewProperty(false, true);
14605                }
14606                invalidateParentIfNeeded();
14607            }
14608            notifySubtreeAccessibilityStateChangedIfNeeded();
14609        }
14610    }
14611
14612    /**
14613     * Get the LayoutParams associated with this view. All views should have
14614     * layout parameters. These supply parameters to the <i>parent</i> of this
14615     * view specifying how it should be arranged. There are many subclasses of
14616     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14617     * of ViewGroup that are responsible for arranging their children.
14618     *
14619     * This method may return null if this View is not attached to a parent
14620     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14621     * was not invoked successfully. When a View is attached to a parent
14622     * ViewGroup, this method must not return null.
14623     *
14624     * @return The LayoutParams associated with this view, or null if no
14625     *         parameters have been set yet
14626     */
14627    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14628    public ViewGroup.LayoutParams getLayoutParams() {
14629        return mLayoutParams;
14630    }
14631
14632    /**
14633     * Set the layout parameters associated with this view. These supply
14634     * parameters to the <i>parent</i> of this view specifying how it should be
14635     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14636     * correspond to the different subclasses of ViewGroup that are responsible
14637     * for arranging their children.
14638     *
14639     * @param params The layout parameters for this view, cannot be null
14640     */
14641    public void setLayoutParams(ViewGroup.LayoutParams params) {
14642        if (params == null) {
14643            throw new NullPointerException("Layout parameters cannot be null");
14644        }
14645        mLayoutParams = params;
14646        resolveLayoutParams();
14647        if (mParent instanceof ViewGroup) {
14648            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14649        }
14650        requestLayout();
14651    }
14652
14653    /**
14654     * Resolve the layout parameters depending on the resolved layout direction
14655     *
14656     * @hide
14657     */
14658    public void resolveLayoutParams() {
14659        if (mLayoutParams != null) {
14660            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14661        }
14662    }
14663
14664    /**
14665     * Set the scrolled position of your view. This will cause a call to
14666     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14667     * invalidated.
14668     * @param x the x position to scroll to
14669     * @param y the y position to scroll to
14670     */
14671    public void scrollTo(int x, int y) {
14672        if (mScrollX != x || mScrollY != y) {
14673            int oldX = mScrollX;
14674            int oldY = mScrollY;
14675            mScrollX = x;
14676            mScrollY = y;
14677            invalidateParentCaches();
14678            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14679            if (!awakenScrollBars()) {
14680                postInvalidateOnAnimation();
14681            }
14682        }
14683    }
14684
14685    /**
14686     * Move the scrolled position of your view. This will cause a call to
14687     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14688     * invalidated.
14689     * @param x the amount of pixels to scroll by horizontally
14690     * @param y the amount of pixels to scroll by vertically
14691     */
14692    public void scrollBy(int x, int y) {
14693        scrollTo(mScrollX + x, mScrollY + y);
14694    }
14695
14696    /**
14697     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14698     * animation to fade the scrollbars out after a default delay. If a subclass
14699     * provides animated scrolling, the start delay should equal the duration
14700     * of the scrolling animation.</p>
14701     *
14702     * <p>The animation starts only if at least one of the scrollbars is
14703     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14704     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14705     * this method returns true, and false otherwise. If the animation is
14706     * started, this method calls {@link #invalidate()}; in that case the
14707     * caller should not call {@link #invalidate()}.</p>
14708     *
14709     * <p>This method should be invoked every time a subclass directly updates
14710     * the scroll parameters.</p>
14711     *
14712     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14713     * and {@link #scrollTo(int, int)}.</p>
14714     *
14715     * @return true if the animation is played, false otherwise
14716     *
14717     * @see #awakenScrollBars(int)
14718     * @see #scrollBy(int, int)
14719     * @see #scrollTo(int, int)
14720     * @see #isHorizontalScrollBarEnabled()
14721     * @see #isVerticalScrollBarEnabled()
14722     * @see #setHorizontalScrollBarEnabled(boolean)
14723     * @see #setVerticalScrollBarEnabled(boolean)
14724     */
14725    protected boolean awakenScrollBars() {
14726        return mScrollCache != null &&
14727                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14728    }
14729
14730    /**
14731     * Trigger the scrollbars to draw.
14732     * This method differs from awakenScrollBars() only in its default duration.
14733     * initialAwakenScrollBars() will show the scroll bars for longer than
14734     * usual to give the user more of a chance to notice them.
14735     *
14736     * @return true if the animation is played, false otherwise.
14737     */
14738    private boolean initialAwakenScrollBars() {
14739        return mScrollCache != null &&
14740                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14741    }
14742
14743    /**
14744     * <p>
14745     * Trigger the scrollbars to draw. When invoked this method starts an
14746     * animation to fade the scrollbars out after a fixed delay. If a subclass
14747     * provides animated scrolling, the start delay should equal the duration of
14748     * the scrolling animation.
14749     * </p>
14750     *
14751     * <p>
14752     * The animation starts only if at least one of the scrollbars is enabled,
14753     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14754     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14755     * this method returns true, and false otherwise. If the animation is
14756     * started, this method calls {@link #invalidate()}; in that case the caller
14757     * should not call {@link #invalidate()}.
14758     * </p>
14759     *
14760     * <p>
14761     * This method should be invoked every time a subclass directly updates the
14762     * scroll parameters.
14763     * </p>
14764     *
14765     * @param startDelay the delay, in milliseconds, after which the animation
14766     *        should start; when the delay is 0, the animation starts
14767     *        immediately
14768     * @return true if the animation is played, false otherwise
14769     *
14770     * @see #scrollBy(int, int)
14771     * @see #scrollTo(int, int)
14772     * @see #isHorizontalScrollBarEnabled()
14773     * @see #isVerticalScrollBarEnabled()
14774     * @see #setHorizontalScrollBarEnabled(boolean)
14775     * @see #setVerticalScrollBarEnabled(boolean)
14776     */
14777    protected boolean awakenScrollBars(int startDelay) {
14778        return awakenScrollBars(startDelay, true);
14779    }
14780
14781    /**
14782     * <p>
14783     * Trigger the scrollbars to draw. When invoked this method starts an
14784     * animation to fade the scrollbars out after a fixed delay. If a subclass
14785     * provides animated scrolling, the start delay should equal the duration of
14786     * the scrolling animation.
14787     * </p>
14788     *
14789     * <p>
14790     * The animation starts only if at least one of the scrollbars is enabled,
14791     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14792     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14793     * this method returns true, and false otherwise. If the animation is
14794     * started, this method calls {@link #invalidate()} if the invalidate parameter
14795     * is set to true; in that case the caller
14796     * should not call {@link #invalidate()}.
14797     * </p>
14798     *
14799     * <p>
14800     * This method should be invoked every time a subclass directly updates the
14801     * scroll parameters.
14802     * </p>
14803     *
14804     * @param startDelay the delay, in milliseconds, after which the animation
14805     *        should start; when the delay is 0, the animation starts
14806     *        immediately
14807     *
14808     * @param invalidate Whether this method should call invalidate
14809     *
14810     * @return true if the animation is played, false otherwise
14811     *
14812     * @see #scrollBy(int, int)
14813     * @see #scrollTo(int, int)
14814     * @see #isHorizontalScrollBarEnabled()
14815     * @see #isVerticalScrollBarEnabled()
14816     * @see #setHorizontalScrollBarEnabled(boolean)
14817     * @see #setVerticalScrollBarEnabled(boolean)
14818     */
14819    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14820        final ScrollabilityCache scrollCache = mScrollCache;
14821
14822        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14823            return false;
14824        }
14825
14826        if (scrollCache.scrollBar == null) {
14827            scrollCache.scrollBar = new ScrollBarDrawable();
14828            scrollCache.scrollBar.setState(getDrawableState());
14829            scrollCache.scrollBar.setCallback(this);
14830        }
14831
14832        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14833
14834            if (invalidate) {
14835                // Invalidate to show the scrollbars
14836                postInvalidateOnAnimation();
14837            }
14838
14839            if (scrollCache.state == ScrollabilityCache.OFF) {
14840                // FIXME: this is copied from WindowManagerService.
14841                // We should get this value from the system when it
14842                // is possible to do so.
14843                final int KEY_REPEAT_FIRST_DELAY = 750;
14844                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14845            }
14846
14847            // Tell mScrollCache when we should start fading. This may
14848            // extend the fade start time if one was already scheduled
14849            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14850            scrollCache.fadeStartTime = fadeStartTime;
14851            scrollCache.state = ScrollabilityCache.ON;
14852
14853            // Schedule our fader to run, unscheduling any old ones first
14854            if (mAttachInfo != null) {
14855                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14856                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14857            }
14858
14859            return true;
14860        }
14861
14862        return false;
14863    }
14864
14865    /**
14866     * Do not invalidate views which are not visible and which are not running an animation. They
14867     * will not get drawn and they should not set dirty flags as if they will be drawn
14868     */
14869    private boolean skipInvalidate() {
14870        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14871                (!(mParent instanceof ViewGroup) ||
14872                        !((ViewGroup) mParent).isViewTransitioning(this));
14873    }
14874
14875    /**
14876     * Mark the area defined by dirty as needing to be drawn. If the view is
14877     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14878     * point in the future.
14879     * <p>
14880     * This must be called from a UI thread. To call from a non-UI thread, call
14881     * {@link #postInvalidate()}.
14882     * <p>
14883     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14884     * {@code dirty}.
14885     *
14886     * @param dirty the rectangle representing the bounds of the dirty region
14887     */
14888    public void invalidate(Rect dirty) {
14889        final int scrollX = mScrollX;
14890        final int scrollY = mScrollY;
14891        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14892                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14893    }
14894
14895    /**
14896     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
14897     * coordinates of the dirty rect are relative to the view. If the view is
14898     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14899     * point in the future.
14900     * <p>
14901     * This must be called from a UI thread. To call from a non-UI thread, call
14902     * {@link #postInvalidate()}.
14903     *
14904     * @param l the left position of the dirty region
14905     * @param t the top position of the dirty region
14906     * @param r the right position of the dirty region
14907     * @param b the bottom position of the dirty region
14908     */
14909    public void invalidate(int l, int t, int r, int b) {
14910        final int scrollX = mScrollX;
14911        final int scrollY = mScrollY;
14912        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14913    }
14914
14915    /**
14916     * Invalidate the whole view. If the view is visible,
14917     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
14918     * the future.
14919     * <p>
14920     * This must be called from a UI thread. To call from a non-UI thread, call
14921     * {@link #postInvalidate()}.
14922     */
14923    public void invalidate() {
14924        invalidate(true);
14925    }
14926
14927    /**
14928     * This is where the invalidate() work actually happens. A full invalidate()
14929     * causes the drawing cache to be invalidated, but this function can be
14930     * called with invalidateCache set to false to skip that invalidation step
14931     * for cases that do not need it (for example, a component that remains at
14932     * the same dimensions with the same content).
14933     *
14934     * @param invalidateCache Whether the drawing cache for this view should be
14935     *            invalidated as well. This is usually true for a full
14936     *            invalidate, but may be set to false if the View's contents or
14937     *            dimensions have not changed.
14938     * @hide
14939     */
14940    public void invalidate(boolean invalidateCache) {
14941        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
14942    }
14943
14944    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
14945            boolean fullInvalidate) {
14946        if (mGhostView != null) {
14947            mGhostView.invalidate(true);
14948            return;
14949        }
14950
14951        if (skipInvalidate()) {
14952            return;
14953        }
14954
14955        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
14956                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
14957                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
14958                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
14959            if (fullInvalidate) {
14960                mLastIsOpaque = isOpaque();
14961                mPrivateFlags &= ~PFLAG_DRAWN;
14962            }
14963
14964            mPrivateFlags |= PFLAG_DIRTY;
14965
14966            if (invalidateCache) {
14967                mPrivateFlags |= PFLAG_INVALIDATED;
14968                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14969            }
14970
14971            // Propagate the damage rectangle to the parent view.
14972            final AttachInfo ai = mAttachInfo;
14973            final ViewParent p = mParent;
14974            if (p != null && ai != null && l < r && t < b) {
14975                final Rect damage = ai.mTmpInvalRect;
14976                damage.set(l, t, r, b);
14977                p.invalidateChild(this, damage);
14978            }
14979
14980            // Damage the entire projection receiver, if necessary.
14981            if (mBackground != null && mBackground.isProjected()) {
14982                final View receiver = getProjectionReceiver();
14983                if (receiver != null) {
14984                    receiver.damageInParent();
14985                }
14986            }
14987        }
14988    }
14989
14990    /**
14991     * @return this view's projection receiver, or {@code null} if none exists
14992     */
14993    private View getProjectionReceiver() {
14994        ViewParent p = getParent();
14995        while (p != null && p instanceof View) {
14996            final View v = (View) p;
14997            if (v.isProjectionReceiver()) {
14998                return v;
14999            }
15000            p = p.getParent();
15001        }
15002
15003        return null;
15004    }
15005
15006    /**
15007     * @return whether the view is a projection receiver
15008     */
15009    private boolean isProjectionReceiver() {
15010        return mBackground != null;
15011    }
15012
15013    /**
15014     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15015     * set any flags or handle all of the cases handled by the default invalidation methods.
15016     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15017     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15018     * walk up the hierarchy, transforming the dirty rect as necessary.
15019     *
15020     * The method also handles normal invalidation logic if display list properties are not
15021     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15022     * backup approach, to handle these cases used in the various property-setting methods.
15023     *
15024     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15025     * are not being used in this view
15026     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15027     * list properties are not being used in this view
15028     */
15029    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15030        if (!isHardwareAccelerated()
15031                || !mRenderNode.isValid()
15032                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15033            if (invalidateParent) {
15034                invalidateParentCaches();
15035            }
15036            if (forceRedraw) {
15037                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15038            }
15039            invalidate(false);
15040        } else {
15041            damageInParent();
15042        }
15043    }
15044
15045    /**
15046     * Tells the parent view to damage this view's bounds.
15047     *
15048     * @hide
15049     */
15050    protected void damageInParent() {
15051        if (mParent != null && mAttachInfo != null) {
15052            mParent.onDescendantInvalidated(this, this);
15053        }
15054    }
15055
15056    /**
15057     * Utility method to transform a given Rect by the current matrix of this view.
15058     */
15059    void transformRect(final Rect rect) {
15060        if (!getMatrix().isIdentity()) {
15061            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15062            boundingRect.set(rect);
15063            getMatrix().mapRect(boundingRect);
15064            rect.set((int) Math.floor(boundingRect.left),
15065                    (int) Math.floor(boundingRect.top),
15066                    (int) Math.ceil(boundingRect.right),
15067                    (int) Math.ceil(boundingRect.bottom));
15068        }
15069    }
15070
15071    /**
15072     * Used to indicate that the parent of this view should clear its caches. This functionality
15073     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15074     * which is necessary when various parent-managed properties of the view change, such as
15075     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15076     * clears the parent caches and does not causes an invalidate event.
15077     *
15078     * @hide
15079     */
15080    protected void invalidateParentCaches() {
15081        if (mParent instanceof View) {
15082            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15083        }
15084    }
15085
15086    /**
15087     * Used to indicate that the parent of this view should be invalidated. This functionality
15088     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15089     * which is necessary when various parent-managed properties of the view change, such as
15090     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15091     * an invalidation event to the parent.
15092     *
15093     * @hide
15094     */
15095    protected void invalidateParentIfNeeded() {
15096        if (isHardwareAccelerated() && mParent instanceof View) {
15097            ((View) mParent).invalidate(true);
15098        }
15099    }
15100
15101    /**
15102     * @hide
15103     */
15104    protected void invalidateParentIfNeededAndWasQuickRejected() {
15105        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15106            // View was rejected last time it was drawn by its parent; this may have changed
15107            invalidateParentIfNeeded();
15108        }
15109    }
15110
15111    /**
15112     * Indicates whether this View is opaque. An opaque View guarantees that it will
15113     * draw all the pixels overlapping its bounds using a fully opaque color.
15114     *
15115     * Subclasses of View should override this method whenever possible to indicate
15116     * whether an instance is opaque. Opaque Views are treated in a special way by
15117     * the View hierarchy, possibly allowing it to perform optimizations during
15118     * invalidate/draw passes.
15119     *
15120     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15121     */
15122    @ViewDebug.ExportedProperty(category = "drawing")
15123    public boolean isOpaque() {
15124        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15125                getFinalAlpha() >= 1.0f;
15126    }
15127
15128    /**
15129     * @hide
15130     */
15131    protected void computeOpaqueFlags() {
15132        // Opaque if:
15133        //   - Has a background
15134        //   - Background is opaque
15135        //   - Doesn't have scrollbars or scrollbars overlay
15136
15137        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15138            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15139        } else {
15140            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15141        }
15142
15143        final int flags = mViewFlags;
15144        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15145                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15146                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15147            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15148        } else {
15149            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15150        }
15151    }
15152
15153    /**
15154     * @hide
15155     */
15156    protected boolean hasOpaqueScrollbars() {
15157        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15158    }
15159
15160    /**
15161     * @return A handler associated with the thread running the View. This
15162     * handler can be used to pump events in the UI events queue.
15163     */
15164    public Handler getHandler() {
15165        final AttachInfo attachInfo = mAttachInfo;
15166        if (attachInfo != null) {
15167            return attachInfo.mHandler;
15168        }
15169        return null;
15170    }
15171
15172    /**
15173     * Returns the queue of runnable for this view.
15174     *
15175     * @return the queue of runnables for this view
15176     */
15177    private HandlerActionQueue getRunQueue() {
15178        if (mRunQueue == null) {
15179            mRunQueue = new HandlerActionQueue();
15180        }
15181        return mRunQueue;
15182    }
15183
15184    /**
15185     * Gets the view root associated with the View.
15186     * @return The view root, or null if none.
15187     * @hide
15188     */
15189    public ViewRootImpl getViewRootImpl() {
15190        if (mAttachInfo != null) {
15191            return mAttachInfo.mViewRootImpl;
15192        }
15193        return null;
15194    }
15195
15196    /**
15197     * @hide
15198     */
15199    public ThreadedRenderer getThreadedRenderer() {
15200        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15201    }
15202
15203    /**
15204     * <p>Causes the Runnable to be added to the message queue.
15205     * The runnable will be run on the user interface thread.</p>
15206     *
15207     * @param action The Runnable that will be executed.
15208     *
15209     * @return Returns true if the Runnable was successfully placed in to the
15210     *         message queue.  Returns false on failure, usually because the
15211     *         looper processing the message queue is exiting.
15212     *
15213     * @see #postDelayed
15214     * @see #removeCallbacks
15215     */
15216    public boolean post(Runnable action) {
15217        final AttachInfo attachInfo = mAttachInfo;
15218        if (attachInfo != null) {
15219            return attachInfo.mHandler.post(action);
15220        }
15221
15222        // Postpone the runnable until we know on which thread it needs to run.
15223        // Assume that the runnable will be successfully placed after attach.
15224        getRunQueue().post(action);
15225        return true;
15226    }
15227
15228    /**
15229     * <p>Causes the Runnable to be added to the message queue, to be run
15230     * after the specified amount of time elapses.
15231     * The runnable will be run on the user interface thread.</p>
15232     *
15233     * @param action The Runnable that will be executed.
15234     * @param delayMillis The delay (in milliseconds) until the Runnable
15235     *        will be executed.
15236     *
15237     * @return true if the Runnable was successfully placed in to the
15238     *         message queue.  Returns false on failure, usually because the
15239     *         looper processing the message queue is exiting.  Note that a
15240     *         result of true does not mean the Runnable will be processed --
15241     *         if the looper is quit before the delivery time of the message
15242     *         occurs then the message will be dropped.
15243     *
15244     * @see #post
15245     * @see #removeCallbacks
15246     */
15247    public boolean postDelayed(Runnable action, long delayMillis) {
15248        final AttachInfo attachInfo = mAttachInfo;
15249        if (attachInfo != null) {
15250            return attachInfo.mHandler.postDelayed(action, delayMillis);
15251        }
15252
15253        // Postpone the runnable until we know on which thread it needs to run.
15254        // Assume that the runnable will be successfully placed after attach.
15255        getRunQueue().postDelayed(action, delayMillis);
15256        return true;
15257    }
15258
15259    /**
15260     * <p>Causes the Runnable to execute on the next animation time step.
15261     * The runnable will be run on the user interface thread.</p>
15262     *
15263     * @param action The Runnable that will be executed.
15264     *
15265     * @see #postOnAnimationDelayed
15266     * @see #removeCallbacks
15267     */
15268    public void postOnAnimation(Runnable action) {
15269        final AttachInfo attachInfo = mAttachInfo;
15270        if (attachInfo != null) {
15271            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15272                    Choreographer.CALLBACK_ANIMATION, action, null);
15273        } else {
15274            // Postpone the runnable until we know
15275            // on which thread it needs to run.
15276            getRunQueue().post(action);
15277        }
15278    }
15279
15280    /**
15281     * <p>Causes the Runnable to execute on the next animation time step,
15282     * after the specified amount of time elapses.
15283     * The runnable will be run on the user interface thread.</p>
15284     *
15285     * @param action The Runnable that will be executed.
15286     * @param delayMillis The delay (in milliseconds) until the Runnable
15287     *        will be executed.
15288     *
15289     * @see #postOnAnimation
15290     * @see #removeCallbacks
15291     */
15292    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15293        final AttachInfo attachInfo = mAttachInfo;
15294        if (attachInfo != null) {
15295            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15296                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15297        } else {
15298            // Postpone the runnable until we know
15299            // on which thread it needs to run.
15300            getRunQueue().postDelayed(action, delayMillis);
15301        }
15302    }
15303
15304    /**
15305     * <p>Removes the specified Runnable from the message queue.</p>
15306     *
15307     * @param action The Runnable to remove from the message handling queue
15308     *
15309     * @return true if this view could ask the Handler to remove the Runnable,
15310     *         false otherwise. When the returned value is true, the Runnable
15311     *         may or may not have been actually removed from the message queue
15312     *         (for instance, if the Runnable was not in the queue already.)
15313     *
15314     * @see #post
15315     * @see #postDelayed
15316     * @see #postOnAnimation
15317     * @see #postOnAnimationDelayed
15318     */
15319    public boolean removeCallbacks(Runnable action) {
15320        if (action != null) {
15321            final AttachInfo attachInfo = mAttachInfo;
15322            if (attachInfo != null) {
15323                attachInfo.mHandler.removeCallbacks(action);
15324                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15325                        Choreographer.CALLBACK_ANIMATION, action, null);
15326            }
15327            getRunQueue().removeCallbacks(action);
15328        }
15329        return true;
15330    }
15331
15332    /**
15333     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15334     * Use this to invalidate the View from a non-UI thread.</p>
15335     *
15336     * <p>This method can be invoked from outside of the UI thread
15337     * only when this View is attached to a window.</p>
15338     *
15339     * @see #invalidate()
15340     * @see #postInvalidateDelayed(long)
15341     */
15342    public void postInvalidate() {
15343        postInvalidateDelayed(0);
15344    }
15345
15346    /**
15347     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15348     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15349     *
15350     * <p>This method can be invoked from outside of the UI thread
15351     * only when this View is attached to a window.</p>
15352     *
15353     * @param left The left coordinate of the rectangle to invalidate.
15354     * @param top The top coordinate of the rectangle to invalidate.
15355     * @param right The right coordinate of the rectangle to invalidate.
15356     * @param bottom The bottom coordinate of the rectangle to invalidate.
15357     *
15358     * @see #invalidate(int, int, int, int)
15359     * @see #invalidate(Rect)
15360     * @see #postInvalidateDelayed(long, int, int, int, int)
15361     */
15362    public void postInvalidate(int left, int top, int right, int bottom) {
15363        postInvalidateDelayed(0, left, top, right, bottom);
15364    }
15365
15366    /**
15367     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15368     * loop. Waits for the specified amount of time.</p>
15369     *
15370     * <p>This method can be invoked from outside of the UI thread
15371     * only when this View is attached to a window.</p>
15372     *
15373     * @param delayMilliseconds the duration in milliseconds to delay the
15374     *         invalidation by
15375     *
15376     * @see #invalidate()
15377     * @see #postInvalidate()
15378     */
15379    public void postInvalidateDelayed(long delayMilliseconds) {
15380        // We try only with the AttachInfo because there's no point in invalidating
15381        // if we are not attached to our window
15382        final AttachInfo attachInfo = mAttachInfo;
15383        if (attachInfo != null) {
15384            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15385        }
15386    }
15387
15388    /**
15389     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15390     * through the event loop. Waits for the specified amount of time.</p>
15391     *
15392     * <p>This method can be invoked from outside of the UI thread
15393     * only when this View is attached to a window.</p>
15394     *
15395     * @param delayMilliseconds the duration in milliseconds to delay the
15396     *         invalidation by
15397     * @param left The left coordinate of the rectangle to invalidate.
15398     * @param top The top coordinate of the rectangle to invalidate.
15399     * @param right The right coordinate of the rectangle to invalidate.
15400     * @param bottom The bottom coordinate of the rectangle to invalidate.
15401     *
15402     * @see #invalidate(int, int, int, int)
15403     * @see #invalidate(Rect)
15404     * @see #postInvalidate(int, int, int, int)
15405     */
15406    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15407            int right, int bottom) {
15408
15409        // We try only with the AttachInfo because there's no point in invalidating
15410        // if we are not attached to our window
15411        final AttachInfo attachInfo = mAttachInfo;
15412        if (attachInfo != null) {
15413            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15414            info.target = this;
15415            info.left = left;
15416            info.top = top;
15417            info.right = right;
15418            info.bottom = bottom;
15419
15420            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15421        }
15422    }
15423
15424    /**
15425     * <p>Cause an invalidate to happen on the next animation time step, typically the
15426     * next display frame.</p>
15427     *
15428     * <p>This method can be invoked from outside of the UI thread
15429     * only when this View is attached to a window.</p>
15430     *
15431     * @see #invalidate()
15432     */
15433    public void postInvalidateOnAnimation() {
15434        // We try only with the AttachInfo because there's no point in invalidating
15435        // if we are not attached to our window
15436        final AttachInfo attachInfo = mAttachInfo;
15437        if (attachInfo != null) {
15438            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15439        }
15440    }
15441
15442    /**
15443     * <p>Cause an invalidate of the specified area to happen on the next animation
15444     * time step, typically the next display frame.</p>
15445     *
15446     * <p>This method can be invoked from outside of the UI thread
15447     * only when this View is attached to a window.</p>
15448     *
15449     * @param left The left coordinate of the rectangle to invalidate.
15450     * @param top The top coordinate of the rectangle to invalidate.
15451     * @param right The right coordinate of the rectangle to invalidate.
15452     * @param bottom The bottom coordinate of the rectangle to invalidate.
15453     *
15454     * @see #invalidate(int, int, int, int)
15455     * @see #invalidate(Rect)
15456     */
15457    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15458        // We try only with the AttachInfo because there's no point in invalidating
15459        // if we are not attached to our window
15460        final AttachInfo attachInfo = mAttachInfo;
15461        if (attachInfo != null) {
15462            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15463            info.target = this;
15464            info.left = left;
15465            info.top = top;
15466            info.right = right;
15467            info.bottom = bottom;
15468
15469            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15470        }
15471    }
15472
15473    /**
15474     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15475     * This event is sent at most once every
15476     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15477     */
15478    private void postSendViewScrolledAccessibilityEventCallback() {
15479        if (mSendViewScrolledAccessibilityEvent == null) {
15480            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15481        }
15482        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15483            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15484            postDelayed(mSendViewScrolledAccessibilityEvent,
15485                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15486        }
15487    }
15488
15489    /**
15490     * Called by a parent to request that a child update its values for mScrollX
15491     * and mScrollY if necessary. This will typically be done if the child is
15492     * animating a scroll using a {@link android.widget.Scroller Scroller}
15493     * object.
15494     */
15495    public void computeScroll() {
15496    }
15497
15498    /**
15499     * <p>Indicate whether the horizontal edges are faded when the view is
15500     * scrolled horizontally.</p>
15501     *
15502     * @return true if the horizontal edges should are faded on scroll, false
15503     *         otherwise
15504     *
15505     * @see #setHorizontalFadingEdgeEnabled(boolean)
15506     *
15507     * @attr ref android.R.styleable#View_requiresFadingEdge
15508     */
15509    public boolean isHorizontalFadingEdgeEnabled() {
15510        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15511    }
15512
15513    /**
15514     * <p>Define whether the horizontal edges should be faded when this view
15515     * is scrolled horizontally.</p>
15516     *
15517     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15518     *                                    be faded when the view is scrolled
15519     *                                    horizontally
15520     *
15521     * @see #isHorizontalFadingEdgeEnabled()
15522     *
15523     * @attr ref android.R.styleable#View_requiresFadingEdge
15524     */
15525    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15526        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15527            if (horizontalFadingEdgeEnabled) {
15528                initScrollCache();
15529            }
15530
15531            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15532        }
15533    }
15534
15535    /**
15536     * <p>Indicate whether the vertical edges are faded when the view is
15537     * scrolled horizontally.</p>
15538     *
15539     * @return true if the vertical edges should are faded on scroll, false
15540     *         otherwise
15541     *
15542     * @see #setVerticalFadingEdgeEnabled(boolean)
15543     *
15544     * @attr ref android.R.styleable#View_requiresFadingEdge
15545     */
15546    public boolean isVerticalFadingEdgeEnabled() {
15547        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15548    }
15549
15550    /**
15551     * <p>Define whether the vertical edges should be faded when this view
15552     * is scrolled vertically.</p>
15553     *
15554     * @param verticalFadingEdgeEnabled true if the vertical edges should
15555     *                                  be faded when the view is scrolled
15556     *                                  vertically
15557     *
15558     * @see #isVerticalFadingEdgeEnabled()
15559     *
15560     * @attr ref android.R.styleable#View_requiresFadingEdge
15561     */
15562    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15563        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15564            if (verticalFadingEdgeEnabled) {
15565                initScrollCache();
15566            }
15567
15568            mViewFlags ^= FADING_EDGE_VERTICAL;
15569        }
15570    }
15571
15572    /**
15573     * Returns the strength, or intensity, of the top faded edge. The strength is
15574     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15575     * returns 0.0 or 1.0 but no value in between.
15576     *
15577     * Subclasses should override this method to provide a smoother fade transition
15578     * when scrolling occurs.
15579     *
15580     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15581     */
15582    protected float getTopFadingEdgeStrength() {
15583        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15584    }
15585
15586    /**
15587     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15588     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15589     * returns 0.0 or 1.0 but no value in between.
15590     *
15591     * Subclasses should override this method to provide a smoother fade transition
15592     * when scrolling occurs.
15593     *
15594     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15595     */
15596    protected float getBottomFadingEdgeStrength() {
15597        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15598                computeVerticalScrollRange() ? 1.0f : 0.0f;
15599    }
15600
15601    /**
15602     * Returns the strength, or intensity, of the left faded edge. The strength is
15603     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15604     * returns 0.0 or 1.0 but no value in between.
15605     *
15606     * Subclasses should override this method to provide a smoother fade transition
15607     * when scrolling occurs.
15608     *
15609     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15610     */
15611    protected float getLeftFadingEdgeStrength() {
15612        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15613    }
15614
15615    /**
15616     * Returns the strength, or intensity, of the right faded edge. The strength is
15617     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15618     * returns 0.0 or 1.0 but no value in between.
15619     *
15620     * Subclasses should override this method to provide a smoother fade transition
15621     * when scrolling occurs.
15622     *
15623     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15624     */
15625    protected float getRightFadingEdgeStrength() {
15626        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15627                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15628    }
15629
15630    /**
15631     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15632     * scrollbar is not drawn by default.</p>
15633     *
15634     * @return true if the horizontal scrollbar should be painted, false
15635     *         otherwise
15636     *
15637     * @see #setHorizontalScrollBarEnabled(boolean)
15638     */
15639    public boolean isHorizontalScrollBarEnabled() {
15640        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15641    }
15642
15643    /**
15644     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15645     * scrollbar is not drawn by default.</p>
15646     *
15647     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15648     *                                   be painted
15649     *
15650     * @see #isHorizontalScrollBarEnabled()
15651     */
15652    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15653        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15654            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15655            computeOpaqueFlags();
15656            resolvePadding();
15657        }
15658    }
15659
15660    /**
15661     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15662     * scrollbar is not drawn by default.</p>
15663     *
15664     * @return true if the vertical scrollbar should be painted, false
15665     *         otherwise
15666     *
15667     * @see #setVerticalScrollBarEnabled(boolean)
15668     */
15669    public boolean isVerticalScrollBarEnabled() {
15670        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15671    }
15672
15673    /**
15674     * <p>Define whether the vertical scrollbar should be drawn or not. The
15675     * scrollbar is not drawn by default.</p>
15676     *
15677     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15678     *                                 be painted
15679     *
15680     * @see #isVerticalScrollBarEnabled()
15681     */
15682    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15683        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15684            mViewFlags ^= SCROLLBARS_VERTICAL;
15685            computeOpaqueFlags();
15686            resolvePadding();
15687        }
15688    }
15689
15690    /**
15691     * @hide
15692     */
15693    protected void recomputePadding() {
15694        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15695    }
15696
15697    /**
15698     * Define whether scrollbars will fade when the view is not scrolling.
15699     *
15700     * @param fadeScrollbars whether to enable fading
15701     *
15702     * @attr ref android.R.styleable#View_fadeScrollbars
15703     */
15704    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15705        initScrollCache();
15706        final ScrollabilityCache scrollabilityCache = mScrollCache;
15707        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15708        if (fadeScrollbars) {
15709            scrollabilityCache.state = ScrollabilityCache.OFF;
15710        } else {
15711            scrollabilityCache.state = ScrollabilityCache.ON;
15712        }
15713    }
15714
15715    /**
15716     *
15717     * Returns true if scrollbars will fade when this view is not scrolling
15718     *
15719     * @return true if scrollbar fading is enabled
15720     *
15721     * @attr ref android.R.styleable#View_fadeScrollbars
15722     */
15723    public boolean isScrollbarFadingEnabled() {
15724        return mScrollCache != null && mScrollCache.fadeScrollBars;
15725    }
15726
15727    /**
15728     *
15729     * Returns the delay before scrollbars fade.
15730     *
15731     * @return the delay before scrollbars fade
15732     *
15733     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15734     */
15735    public int getScrollBarDefaultDelayBeforeFade() {
15736        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15737                mScrollCache.scrollBarDefaultDelayBeforeFade;
15738    }
15739
15740    /**
15741     * Define the delay before scrollbars fade.
15742     *
15743     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15744     *
15745     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15746     */
15747    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15748        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15749    }
15750
15751    /**
15752     *
15753     * Returns the scrollbar fade duration.
15754     *
15755     * @return the scrollbar fade duration, in milliseconds
15756     *
15757     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15758     */
15759    public int getScrollBarFadeDuration() {
15760        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15761                mScrollCache.scrollBarFadeDuration;
15762    }
15763
15764    /**
15765     * Define the scrollbar fade duration.
15766     *
15767     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15768     *
15769     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15770     */
15771    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15772        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15773    }
15774
15775    /**
15776     *
15777     * Returns the scrollbar size.
15778     *
15779     * @return the scrollbar size
15780     *
15781     * @attr ref android.R.styleable#View_scrollbarSize
15782     */
15783    public int getScrollBarSize() {
15784        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15785                mScrollCache.scrollBarSize;
15786    }
15787
15788    /**
15789     * Define the scrollbar size.
15790     *
15791     * @param scrollBarSize - the scrollbar size
15792     *
15793     * @attr ref android.R.styleable#View_scrollbarSize
15794     */
15795    public void setScrollBarSize(int scrollBarSize) {
15796        getScrollCache().scrollBarSize = scrollBarSize;
15797    }
15798
15799    /**
15800     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15801     * inset. When inset, they add to the padding of the view. And the scrollbars
15802     * can be drawn inside the padding area or on the edge of the view. For example,
15803     * if a view has a background drawable and you want to draw the scrollbars
15804     * inside the padding specified by the drawable, you can use
15805     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15806     * appear at the edge of the view, ignoring the padding, then you can use
15807     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15808     * @param style the style of the scrollbars. Should be one of
15809     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15810     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15811     * @see #SCROLLBARS_INSIDE_OVERLAY
15812     * @see #SCROLLBARS_INSIDE_INSET
15813     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15814     * @see #SCROLLBARS_OUTSIDE_INSET
15815     *
15816     * @attr ref android.R.styleable#View_scrollbarStyle
15817     */
15818    public void setScrollBarStyle(@ScrollBarStyle int style) {
15819        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15820            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15821            computeOpaqueFlags();
15822            resolvePadding();
15823        }
15824    }
15825
15826    /**
15827     * <p>Returns the current scrollbar style.</p>
15828     * @return the current scrollbar style
15829     * @see #SCROLLBARS_INSIDE_OVERLAY
15830     * @see #SCROLLBARS_INSIDE_INSET
15831     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15832     * @see #SCROLLBARS_OUTSIDE_INSET
15833     *
15834     * @attr ref android.R.styleable#View_scrollbarStyle
15835     */
15836    @ViewDebug.ExportedProperty(mapping = {
15837            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15838            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15839            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15840            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15841    })
15842    @ScrollBarStyle
15843    public int getScrollBarStyle() {
15844        return mViewFlags & SCROLLBARS_STYLE_MASK;
15845    }
15846
15847    /**
15848     * <p>Compute the horizontal range that the horizontal scrollbar
15849     * represents.</p>
15850     *
15851     * <p>The range is expressed in arbitrary units that must be the same as the
15852     * units used by {@link #computeHorizontalScrollExtent()} and
15853     * {@link #computeHorizontalScrollOffset()}.</p>
15854     *
15855     * <p>The default range is the drawing width of this view.</p>
15856     *
15857     * @return the total horizontal range represented by the horizontal
15858     *         scrollbar
15859     *
15860     * @see #computeHorizontalScrollExtent()
15861     * @see #computeHorizontalScrollOffset()
15862     * @see android.widget.ScrollBarDrawable
15863     */
15864    protected int computeHorizontalScrollRange() {
15865        return getWidth();
15866    }
15867
15868    /**
15869     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15870     * within the horizontal range. This value is used to compute the position
15871     * of the thumb within the scrollbar's track.</p>
15872     *
15873     * <p>The range is expressed in arbitrary units that must be the same as the
15874     * units used by {@link #computeHorizontalScrollRange()} and
15875     * {@link #computeHorizontalScrollExtent()}.</p>
15876     *
15877     * <p>The default offset is the scroll offset of this view.</p>
15878     *
15879     * @return the horizontal offset of the scrollbar's thumb
15880     *
15881     * @see #computeHorizontalScrollRange()
15882     * @see #computeHorizontalScrollExtent()
15883     * @see android.widget.ScrollBarDrawable
15884     */
15885    protected int computeHorizontalScrollOffset() {
15886        return mScrollX;
15887    }
15888
15889    /**
15890     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15891     * within the horizontal range. This value is used to compute the length
15892     * of the thumb within the scrollbar's track.</p>
15893     *
15894     * <p>The range is expressed in arbitrary units that must be the same as the
15895     * units used by {@link #computeHorizontalScrollRange()} and
15896     * {@link #computeHorizontalScrollOffset()}.</p>
15897     *
15898     * <p>The default extent is the drawing width of this view.</p>
15899     *
15900     * @return the horizontal extent of the scrollbar's thumb
15901     *
15902     * @see #computeHorizontalScrollRange()
15903     * @see #computeHorizontalScrollOffset()
15904     * @see android.widget.ScrollBarDrawable
15905     */
15906    protected int computeHorizontalScrollExtent() {
15907        return getWidth();
15908    }
15909
15910    /**
15911     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15912     *
15913     * <p>The range is expressed in arbitrary units that must be the same as the
15914     * units used by {@link #computeVerticalScrollExtent()} and
15915     * {@link #computeVerticalScrollOffset()}.</p>
15916     *
15917     * @return the total vertical range represented by the vertical scrollbar
15918     *
15919     * <p>The default range is the drawing height of this view.</p>
15920     *
15921     * @see #computeVerticalScrollExtent()
15922     * @see #computeVerticalScrollOffset()
15923     * @see android.widget.ScrollBarDrawable
15924     */
15925    protected int computeVerticalScrollRange() {
15926        return getHeight();
15927    }
15928
15929    /**
15930     * <p>Compute the vertical offset of the vertical scrollbar's thumb
15931     * within the horizontal range. This value is used to compute the position
15932     * of the thumb within the scrollbar's track.</p>
15933     *
15934     * <p>The range is expressed in arbitrary units that must be the same as the
15935     * units used by {@link #computeVerticalScrollRange()} and
15936     * {@link #computeVerticalScrollExtent()}.</p>
15937     *
15938     * <p>The default offset is the scroll offset of this view.</p>
15939     *
15940     * @return the vertical offset of the scrollbar's thumb
15941     *
15942     * @see #computeVerticalScrollRange()
15943     * @see #computeVerticalScrollExtent()
15944     * @see android.widget.ScrollBarDrawable
15945     */
15946    protected int computeVerticalScrollOffset() {
15947        return mScrollY;
15948    }
15949
15950    /**
15951     * <p>Compute the vertical extent of the vertical scrollbar's thumb
15952     * within the vertical range. This value is used to compute the length
15953     * of the thumb within the scrollbar's track.</p>
15954     *
15955     * <p>The range is expressed in arbitrary units that must be the same as the
15956     * units used by {@link #computeVerticalScrollRange()} and
15957     * {@link #computeVerticalScrollOffset()}.</p>
15958     *
15959     * <p>The default extent is the drawing height of this view.</p>
15960     *
15961     * @return the vertical extent of the scrollbar's thumb
15962     *
15963     * @see #computeVerticalScrollRange()
15964     * @see #computeVerticalScrollOffset()
15965     * @see android.widget.ScrollBarDrawable
15966     */
15967    protected int computeVerticalScrollExtent() {
15968        return getHeight();
15969    }
15970
15971    /**
15972     * Check if this view can be scrolled horizontally in a certain direction.
15973     *
15974     * @param direction Negative to check scrolling left, positive to check scrolling right.
15975     * @return true if this view can be scrolled in the specified direction, false otherwise.
15976     */
15977    public boolean canScrollHorizontally(int direction) {
15978        final int offset = computeHorizontalScrollOffset();
15979        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
15980        if (range == 0) return false;
15981        if (direction < 0) {
15982            return offset > 0;
15983        } else {
15984            return offset < range - 1;
15985        }
15986    }
15987
15988    /**
15989     * Check if this view can be scrolled vertically in a certain direction.
15990     *
15991     * @param direction Negative to check scrolling up, positive to check scrolling down.
15992     * @return true if this view can be scrolled in the specified direction, false otherwise.
15993     */
15994    public boolean canScrollVertically(int direction) {
15995        final int offset = computeVerticalScrollOffset();
15996        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
15997        if (range == 0) return false;
15998        if (direction < 0) {
15999            return offset > 0;
16000        } else {
16001            return offset < range - 1;
16002        }
16003    }
16004
16005    void getScrollIndicatorBounds(@NonNull Rect out) {
16006        out.left = mScrollX;
16007        out.right = mScrollX + mRight - mLeft;
16008        out.top = mScrollY;
16009        out.bottom = mScrollY + mBottom - mTop;
16010    }
16011
16012    private void onDrawScrollIndicators(Canvas c) {
16013        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16014            // No scroll indicators enabled.
16015            return;
16016        }
16017
16018        final Drawable dr = mScrollIndicatorDrawable;
16019        if (dr == null) {
16020            // Scroll indicators aren't supported here.
16021            return;
16022        }
16023
16024        final int h = dr.getIntrinsicHeight();
16025        final int w = dr.getIntrinsicWidth();
16026        final Rect rect = mAttachInfo.mTmpInvalRect;
16027        getScrollIndicatorBounds(rect);
16028
16029        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16030            final boolean canScrollUp = canScrollVertically(-1);
16031            if (canScrollUp) {
16032                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16033                dr.draw(c);
16034            }
16035        }
16036
16037        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16038            final boolean canScrollDown = canScrollVertically(1);
16039            if (canScrollDown) {
16040                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16041                dr.draw(c);
16042            }
16043        }
16044
16045        final int leftRtl;
16046        final int rightRtl;
16047        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16048            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16049            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16050        } else {
16051            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16052            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16053        }
16054
16055        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16056        if ((mPrivateFlags3 & leftMask) != 0) {
16057            final boolean canScrollLeft = canScrollHorizontally(-1);
16058            if (canScrollLeft) {
16059                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16060                dr.draw(c);
16061            }
16062        }
16063
16064        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16065        if ((mPrivateFlags3 & rightMask) != 0) {
16066            final boolean canScrollRight = canScrollHorizontally(1);
16067            if (canScrollRight) {
16068                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16069                dr.draw(c);
16070            }
16071        }
16072    }
16073
16074    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16075            @Nullable Rect touchBounds) {
16076        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16077        if (bounds == null) {
16078            return;
16079        }
16080        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16081        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16082                && !isVerticalScrollBarHidden();
16083        final int size = getHorizontalScrollbarHeight();
16084        final int verticalScrollBarGap = drawVerticalScrollBar ?
16085                getVerticalScrollbarWidth() : 0;
16086        final int width = mRight - mLeft;
16087        final int height = mBottom - mTop;
16088        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16089        bounds.left = mScrollX + (mPaddingLeft & inside);
16090        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16091        bounds.bottom = bounds.top + size;
16092
16093        if (touchBounds == null) {
16094            return;
16095        }
16096        if (touchBounds != bounds) {
16097            touchBounds.set(bounds);
16098        }
16099        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16100        if (touchBounds.height() < minTouchTarget) {
16101            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16102            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16103            touchBounds.top = touchBounds.bottom - minTouchTarget;
16104        }
16105        if (touchBounds.width() < minTouchTarget) {
16106            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16107            touchBounds.left -= adjust;
16108            touchBounds.right = touchBounds.left + minTouchTarget;
16109        }
16110    }
16111
16112    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16113        if (mRoundScrollbarRenderer == null) {
16114            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16115        } else {
16116            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16117        }
16118    }
16119
16120    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16121        final int width = mRight - mLeft;
16122        final int height = mBottom - mTop;
16123        // Do not take padding into account as we always want the scrollbars
16124        // to hug the screen for round wearable devices.
16125        bounds.left = mScrollX;
16126        bounds.top = mScrollY;
16127        bounds.right = bounds.left + width;
16128        bounds.bottom = mScrollY + height;
16129    }
16130
16131    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16132            @Nullable Rect touchBounds) {
16133        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16134        if (bounds == null) {
16135            return;
16136        }
16137        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16138        final int size = getVerticalScrollbarWidth();
16139        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16140        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16141            verticalScrollbarPosition = isLayoutRtl() ?
16142                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16143        }
16144        final int width = mRight - mLeft;
16145        final int height = mBottom - mTop;
16146        switch (verticalScrollbarPosition) {
16147            default:
16148            case SCROLLBAR_POSITION_RIGHT:
16149                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16150                break;
16151            case SCROLLBAR_POSITION_LEFT:
16152                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16153                break;
16154        }
16155        bounds.top = mScrollY + (mPaddingTop & inside);
16156        bounds.right = bounds.left + size;
16157        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16158
16159        if (touchBounds == null) {
16160            return;
16161        }
16162        if (touchBounds != bounds) {
16163            touchBounds.set(bounds);
16164        }
16165        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16166        if (touchBounds.width() < minTouchTarget) {
16167            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16168            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16169                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16170                touchBounds.left = touchBounds.right - minTouchTarget;
16171            } else {
16172                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16173                touchBounds.right = touchBounds.left + minTouchTarget;
16174            }
16175        }
16176        if (touchBounds.height() < minTouchTarget) {
16177            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16178            touchBounds.top -= adjust;
16179            touchBounds.bottom = touchBounds.top + minTouchTarget;
16180        }
16181    }
16182
16183    /**
16184     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16185     * scrollbars are painted only if they have been awakened first.</p>
16186     *
16187     * @param canvas the canvas on which to draw the scrollbars
16188     *
16189     * @see #awakenScrollBars(int)
16190     */
16191    protected final void onDrawScrollBars(Canvas canvas) {
16192        // scrollbars are drawn only when the animation is running
16193        final ScrollabilityCache cache = mScrollCache;
16194
16195        if (cache != null) {
16196
16197            int state = cache.state;
16198
16199            if (state == ScrollabilityCache.OFF) {
16200                return;
16201            }
16202
16203            boolean invalidate = false;
16204
16205            if (state == ScrollabilityCache.FADING) {
16206                // We're fading -- get our fade interpolation
16207                if (cache.interpolatorValues == null) {
16208                    cache.interpolatorValues = new float[1];
16209                }
16210
16211                float[] values = cache.interpolatorValues;
16212
16213                // Stops the animation if we're done
16214                if (cache.scrollBarInterpolator.timeToValues(values) ==
16215                        Interpolator.Result.FREEZE_END) {
16216                    cache.state = ScrollabilityCache.OFF;
16217                } else {
16218                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16219                }
16220
16221                // This will make the scroll bars inval themselves after
16222                // drawing. We only want this when we're fading so that
16223                // we prevent excessive redraws
16224                invalidate = true;
16225            } else {
16226                // We're just on -- but we may have been fading before so
16227                // reset alpha
16228                cache.scrollBar.mutate().setAlpha(255);
16229            }
16230
16231            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16232            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16233                    && !isVerticalScrollBarHidden();
16234
16235            // Fork out the scroll bar drawing for round wearable devices.
16236            if (mRoundScrollbarRenderer != null) {
16237                if (drawVerticalScrollBar) {
16238                    final Rect bounds = cache.mScrollBarBounds;
16239                    getVerticalScrollBarBounds(bounds, null);
16240                    mRoundScrollbarRenderer.drawRoundScrollbars(
16241                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16242                    if (invalidate) {
16243                        invalidate();
16244                    }
16245                }
16246                // Do not draw horizontal scroll bars for round wearable devices.
16247            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16248                final ScrollBarDrawable scrollBar = cache.scrollBar;
16249
16250                if (drawHorizontalScrollBar) {
16251                    scrollBar.setParameters(computeHorizontalScrollRange(),
16252                            computeHorizontalScrollOffset(),
16253                            computeHorizontalScrollExtent(), false);
16254                    final Rect bounds = cache.mScrollBarBounds;
16255                    getHorizontalScrollBarBounds(bounds, null);
16256                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16257                            bounds.right, bounds.bottom);
16258                    if (invalidate) {
16259                        invalidate(bounds);
16260                    }
16261                }
16262
16263                if (drawVerticalScrollBar) {
16264                    scrollBar.setParameters(computeVerticalScrollRange(),
16265                            computeVerticalScrollOffset(),
16266                            computeVerticalScrollExtent(), true);
16267                    final Rect bounds = cache.mScrollBarBounds;
16268                    getVerticalScrollBarBounds(bounds, null);
16269                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16270                            bounds.right, bounds.bottom);
16271                    if (invalidate) {
16272                        invalidate(bounds);
16273                    }
16274                }
16275            }
16276        }
16277    }
16278
16279    /**
16280     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16281     * FastScroller is visible.
16282     * @return whether to temporarily hide the vertical scrollbar
16283     * @hide
16284     */
16285    protected boolean isVerticalScrollBarHidden() {
16286        return false;
16287    }
16288
16289    /**
16290     * <p>Draw the horizontal scrollbar if
16291     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16292     *
16293     * @param canvas the canvas on which to draw the scrollbar
16294     * @param scrollBar the scrollbar's drawable
16295     *
16296     * @see #isHorizontalScrollBarEnabled()
16297     * @see #computeHorizontalScrollRange()
16298     * @see #computeHorizontalScrollExtent()
16299     * @see #computeHorizontalScrollOffset()
16300     * @see android.widget.ScrollBarDrawable
16301     * @hide
16302     */
16303    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16304            int l, int t, int r, int b) {
16305        scrollBar.setBounds(l, t, r, b);
16306        scrollBar.draw(canvas);
16307    }
16308
16309    /**
16310     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16311     * returns true.</p>
16312     *
16313     * @param canvas the canvas on which to draw the scrollbar
16314     * @param scrollBar the scrollbar's drawable
16315     *
16316     * @see #isVerticalScrollBarEnabled()
16317     * @see #computeVerticalScrollRange()
16318     * @see #computeVerticalScrollExtent()
16319     * @see #computeVerticalScrollOffset()
16320     * @see android.widget.ScrollBarDrawable
16321     * @hide
16322     */
16323    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16324            int l, int t, int r, int b) {
16325        scrollBar.setBounds(l, t, r, b);
16326        scrollBar.draw(canvas);
16327    }
16328
16329    /**
16330     * Implement this to do your drawing.
16331     *
16332     * @param canvas the canvas on which the background will be drawn
16333     */
16334    protected void onDraw(Canvas canvas) {
16335    }
16336
16337    /*
16338     * Caller is responsible for calling requestLayout if necessary.
16339     * (This allows addViewInLayout to not request a new layout.)
16340     */
16341    void assignParent(ViewParent parent) {
16342        if (mParent == null) {
16343            mParent = parent;
16344        } else if (parent == null) {
16345            mParent = null;
16346        } else {
16347            throw new RuntimeException("view " + this + " being added, but"
16348                    + " it already has a parent");
16349        }
16350    }
16351
16352    /**
16353     * This is called when the view is attached to a window.  At this point it
16354     * has a Surface and will start drawing.  Note that this function is
16355     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16356     * however it may be called any time before the first onDraw -- including
16357     * before or after {@link #onMeasure(int, int)}.
16358     *
16359     * @see #onDetachedFromWindow()
16360     */
16361    @CallSuper
16362    protected void onAttachedToWindow() {
16363        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16364            mParent.requestTransparentRegion(this);
16365        }
16366
16367        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16368
16369        jumpDrawablesToCurrentState();
16370
16371        resetSubtreeAccessibilityStateChanged();
16372
16373        // rebuild, since Outline not maintained while View is detached
16374        rebuildOutline();
16375
16376        if (isFocused()) {
16377            InputMethodManager imm = InputMethodManager.peekInstance();
16378            if (imm != null) {
16379                imm.focusIn(this);
16380            }
16381        }
16382    }
16383
16384    /**
16385     * Resolve all RTL related properties.
16386     *
16387     * @return true if resolution of RTL properties has been done
16388     *
16389     * @hide
16390     */
16391    public boolean resolveRtlPropertiesIfNeeded() {
16392        if (!needRtlPropertiesResolution()) return false;
16393
16394        // Order is important here: LayoutDirection MUST be resolved first
16395        if (!isLayoutDirectionResolved()) {
16396            resolveLayoutDirection();
16397            resolveLayoutParams();
16398        }
16399        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16400        if (!isTextDirectionResolved()) {
16401            resolveTextDirection();
16402        }
16403        if (!isTextAlignmentResolved()) {
16404            resolveTextAlignment();
16405        }
16406        // Should resolve Drawables before Padding because we need the layout direction of the
16407        // Drawable to correctly resolve Padding.
16408        if (!areDrawablesResolved()) {
16409            resolveDrawables();
16410        }
16411        if (!isPaddingResolved()) {
16412            resolvePadding();
16413        }
16414        onRtlPropertiesChanged(getLayoutDirection());
16415        return true;
16416    }
16417
16418    /**
16419     * Reset resolution of all RTL related properties.
16420     *
16421     * @hide
16422     */
16423    public void resetRtlProperties() {
16424        resetResolvedLayoutDirection();
16425        resetResolvedTextDirection();
16426        resetResolvedTextAlignment();
16427        resetResolvedPadding();
16428        resetResolvedDrawables();
16429    }
16430
16431    /**
16432     * @see #onScreenStateChanged(int)
16433     */
16434    void dispatchScreenStateChanged(int screenState) {
16435        onScreenStateChanged(screenState);
16436    }
16437
16438    /**
16439     * This method is called whenever the state of the screen this view is
16440     * attached to changes. A state change will usually occurs when the screen
16441     * turns on or off (whether it happens automatically or the user does it
16442     * manually.)
16443     *
16444     * @param screenState The new state of the screen. Can be either
16445     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16446     */
16447    public void onScreenStateChanged(int screenState) {
16448    }
16449
16450    /**
16451     * @see #onMovedToDisplay(int)
16452     */
16453    void dispatchMovedToDisplay(Display display) {
16454        mAttachInfo.mDisplay = display;
16455        mAttachInfo.mDisplayState = display.getState();
16456        onMovedToDisplay(display.getDisplayId());
16457    }
16458
16459    /**
16460     * Called by the system when the hosting activity is moved from one display to another without
16461     * recreation. This means that the activity is declared to handle all changes to configuration
16462     * that happened when it was switched to another display, so it wasn't destroyed and created
16463     * again. This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16464     * applied configuration actually changed.
16465     *
16466     * <p>Use this callback to track changes to the displays if some functionality relies on an
16467     * association with some display properties.
16468     *
16469     * @param displayId The id of the display to which the view was moved.
16470     *
16471     * @see #onConfigurationChanged(Configuration)
16472     */
16473    public void onMovedToDisplay(int displayId) {
16474    }
16475
16476    /**
16477     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16478     */
16479    private boolean hasRtlSupport() {
16480        return mContext.getApplicationInfo().hasRtlSupport();
16481    }
16482
16483    /**
16484     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16485     * RTL not supported)
16486     */
16487    private boolean isRtlCompatibilityMode() {
16488        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16489        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16490    }
16491
16492    /**
16493     * @return true if RTL properties need resolution.
16494     *
16495     */
16496    private boolean needRtlPropertiesResolution() {
16497        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16498    }
16499
16500    /**
16501     * Called when any RTL property (layout direction or text direction or text alignment) has
16502     * been changed.
16503     *
16504     * Subclasses need to override this method to take care of cached information that depends on the
16505     * resolved layout direction, or to inform child views that inherit their layout direction.
16506     *
16507     * The default implementation does nothing.
16508     *
16509     * @param layoutDirection the direction of the layout
16510     *
16511     * @see #LAYOUT_DIRECTION_LTR
16512     * @see #LAYOUT_DIRECTION_RTL
16513     */
16514    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16515    }
16516
16517    /**
16518     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16519     * that the parent directionality can and will be resolved before its children.
16520     *
16521     * @return true if resolution has been done, false otherwise.
16522     *
16523     * @hide
16524     */
16525    public boolean resolveLayoutDirection() {
16526        // Clear any previous layout direction resolution
16527        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16528
16529        if (hasRtlSupport()) {
16530            // Set resolved depending on layout direction
16531            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16532                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16533                case LAYOUT_DIRECTION_INHERIT:
16534                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16535                    // later to get the correct resolved value
16536                    if (!canResolveLayoutDirection()) return false;
16537
16538                    // Parent has not yet resolved, LTR is still the default
16539                    try {
16540                        if (!mParent.isLayoutDirectionResolved()) return false;
16541
16542                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16543                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16544                        }
16545                    } catch (AbstractMethodError e) {
16546                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16547                                " does not fully implement ViewParent", e);
16548                    }
16549                    break;
16550                case LAYOUT_DIRECTION_RTL:
16551                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16552                    break;
16553                case LAYOUT_DIRECTION_LOCALE:
16554                    if((LAYOUT_DIRECTION_RTL ==
16555                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16556                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16557                    }
16558                    break;
16559                default:
16560                    // Nothing to do, LTR by default
16561            }
16562        }
16563
16564        // Set to resolved
16565        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16566        return true;
16567    }
16568
16569    /**
16570     * Check if layout direction resolution can be done.
16571     *
16572     * @return true if layout direction resolution can be done otherwise return false.
16573     */
16574    public boolean canResolveLayoutDirection() {
16575        switch (getRawLayoutDirection()) {
16576            case LAYOUT_DIRECTION_INHERIT:
16577                if (mParent != null) {
16578                    try {
16579                        return mParent.canResolveLayoutDirection();
16580                    } catch (AbstractMethodError e) {
16581                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16582                                " does not fully implement ViewParent", e);
16583                    }
16584                }
16585                return false;
16586
16587            default:
16588                return true;
16589        }
16590    }
16591
16592    /**
16593     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16594     * {@link #onMeasure(int, int)}.
16595     *
16596     * @hide
16597     */
16598    public void resetResolvedLayoutDirection() {
16599        // Reset the current resolved bits
16600        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16601    }
16602
16603    /**
16604     * @return true if the layout direction is inherited.
16605     *
16606     * @hide
16607     */
16608    public boolean isLayoutDirectionInherited() {
16609        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16610    }
16611
16612    /**
16613     * @return true if layout direction has been resolved.
16614     */
16615    public boolean isLayoutDirectionResolved() {
16616        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16617    }
16618
16619    /**
16620     * Return if padding has been resolved
16621     *
16622     * @hide
16623     */
16624    boolean isPaddingResolved() {
16625        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16626    }
16627
16628    /**
16629     * Resolves padding depending on layout direction, if applicable, and
16630     * recomputes internal padding values to adjust for scroll bars.
16631     *
16632     * @hide
16633     */
16634    public void resolvePadding() {
16635        final int resolvedLayoutDirection = getLayoutDirection();
16636
16637        if (!isRtlCompatibilityMode()) {
16638            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16639            // If start / end padding are defined, they will be resolved (hence overriding) to
16640            // left / right or right / left depending on the resolved layout direction.
16641            // If start / end padding are not defined, use the left / right ones.
16642            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16643                Rect padding = sThreadLocal.get();
16644                if (padding == null) {
16645                    padding = new Rect();
16646                    sThreadLocal.set(padding);
16647                }
16648                mBackground.getPadding(padding);
16649                if (!mLeftPaddingDefined) {
16650                    mUserPaddingLeftInitial = padding.left;
16651                }
16652                if (!mRightPaddingDefined) {
16653                    mUserPaddingRightInitial = padding.right;
16654                }
16655            }
16656            switch (resolvedLayoutDirection) {
16657                case LAYOUT_DIRECTION_RTL:
16658                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16659                        mUserPaddingRight = mUserPaddingStart;
16660                    } else {
16661                        mUserPaddingRight = mUserPaddingRightInitial;
16662                    }
16663                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16664                        mUserPaddingLeft = mUserPaddingEnd;
16665                    } else {
16666                        mUserPaddingLeft = mUserPaddingLeftInitial;
16667                    }
16668                    break;
16669                case LAYOUT_DIRECTION_LTR:
16670                default:
16671                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16672                        mUserPaddingLeft = mUserPaddingStart;
16673                    } else {
16674                        mUserPaddingLeft = mUserPaddingLeftInitial;
16675                    }
16676                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16677                        mUserPaddingRight = mUserPaddingEnd;
16678                    } else {
16679                        mUserPaddingRight = mUserPaddingRightInitial;
16680                    }
16681            }
16682
16683            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16684        }
16685
16686        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16687        onRtlPropertiesChanged(resolvedLayoutDirection);
16688
16689        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16690    }
16691
16692    /**
16693     * Reset the resolved layout direction.
16694     *
16695     * @hide
16696     */
16697    public void resetResolvedPadding() {
16698        resetResolvedPaddingInternal();
16699    }
16700
16701    /**
16702     * Used when we only want to reset *this* view's padding and not trigger overrides
16703     * in ViewGroup that reset children too.
16704     */
16705    void resetResolvedPaddingInternal() {
16706        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16707    }
16708
16709    /**
16710     * This is called when the view is detached from a window.  At this point it
16711     * no longer has a surface for drawing.
16712     *
16713     * @see #onAttachedToWindow()
16714     */
16715    @CallSuper
16716    protected void onDetachedFromWindow() {
16717    }
16718
16719    /**
16720     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16721     * after onDetachedFromWindow().
16722     *
16723     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16724     * The super method should be called at the end of the overridden method to ensure
16725     * subclasses are destroyed first
16726     *
16727     * @hide
16728     */
16729    @CallSuper
16730    protected void onDetachedFromWindowInternal() {
16731        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16732        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16733        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16734
16735        removeUnsetPressCallback();
16736        removeLongPressCallback();
16737        removePerformClickCallback();
16738        removeSendViewScrolledAccessibilityEventCallback();
16739        stopNestedScroll();
16740
16741        // Anything that started animating right before detach should already
16742        // be in its final state when re-attached.
16743        jumpDrawablesToCurrentState();
16744
16745        destroyDrawingCache();
16746
16747        cleanupDraw();
16748        mCurrentAnimation = null;
16749
16750        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16751            hideTooltip();
16752        }
16753    }
16754
16755    private void cleanupDraw() {
16756        resetDisplayList();
16757        if (mAttachInfo != null) {
16758            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16759        }
16760    }
16761
16762    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16763    }
16764
16765    /**
16766     * @return The number of times this view has been attached to a window
16767     */
16768    protected int getWindowAttachCount() {
16769        return mWindowAttachCount;
16770    }
16771
16772    /**
16773     * Retrieve a unique token identifying the window this view is attached to.
16774     * @return Return the window's token for use in
16775     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16776     */
16777    public IBinder getWindowToken() {
16778        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16779    }
16780
16781    /**
16782     * Retrieve the {@link WindowId} for the window this view is
16783     * currently attached to.
16784     */
16785    public WindowId getWindowId() {
16786        if (mAttachInfo == null) {
16787            return null;
16788        }
16789        if (mAttachInfo.mWindowId == null) {
16790            try {
16791                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16792                        mAttachInfo.mWindowToken);
16793                mAttachInfo.mWindowId = new WindowId(
16794                        mAttachInfo.mIWindowId);
16795            } catch (RemoteException e) {
16796            }
16797        }
16798        return mAttachInfo.mWindowId;
16799    }
16800
16801    /**
16802     * Retrieve a unique token identifying the top-level "real" window of
16803     * the window that this view is attached to.  That is, this is like
16804     * {@link #getWindowToken}, except if the window this view in is a panel
16805     * window (attached to another containing window), then the token of
16806     * the containing window is returned instead.
16807     *
16808     * @return Returns the associated window token, either
16809     * {@link #getWindowToken()} or the containing window's token.
16810     */
16811    public IBinder getApplicationWindowToken() {
16812        AttachInfo ai = mAttachInfo;
16813        if (ai != null) {
16814            IBinder appWindowToken = ai.mPanelParentWindowToken;
16815            if (appWindowToken == null) {
16816                appWindowToken = ai.mWindowToken;
16817            }
16818            return appWindowToken;
16819        }
16820        return null;
16821    }
16822
16823    /**
16824     * Gets the logical display to which the view's window has been attached.
16825     *
16826     * @return The logical display, or null if the view is not currently attached to a window.
16827     */
16828    public Display getDisplay() {
16829        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16830    }
16831
16832    /**
16833     * Retrieve private session object this view hierarchy is using to
16834     * communicate with the window manager.
16835     * @return the session object to communicate with the window manager
16836     */
16837    /*package*/ IWindowSession getWindowSession() {
16838        return mAttachInfo != null ? mAttachInfo.mSession : null;
16839    }
16840
16841    /**
16842     * Return the visibility value of the least visible component passed.
16843     */
16844    int combineVisibility(int vis1, int vis2) {
16845        // This works because VISIBLE < INVISIBLE < GONE.
16846        return Math.max(vis1, vis2);
16847    }
16848
16849    /**
16850     * @param info the {@link android.view.View.AttachInfo} to associated with
16851     *        this view
16852     */
16853    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16854        mAttachInfo = info;
16855        if (mOverlay != null) {
16856            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16857        }
16858        mWindowAttachCount++;
16859        // We will need to evaluate the drawable state at least once.
16860        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16861        if (mFloatingTreeObserver != null) {
16862            info.mTreeObserver.merge(mFloatingTreeObserver);
16863            mFloatingTreeObserver = null;
16864        }
16865
16866        registerPendingFrameMetricsObservers();
16867
16868        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16869            mAttachInfo.mScrollContainers.add(this);
16870            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16871        }
16872        // Transfer all pending runnables.
16873        if (mRunQueue != null) {
16874            mRunQueue.executeActions(info.mHandler);
16875            mRunQueue = null;
16876        }
16877        performCollectViewAttributes(mAttachInfo, visibility);
16878        onAttachedToWindow();
16879
16880        ListenerInfo li = mListenerInfo;
16881        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16882                li != null ? li.mOnAttachStateChangeListeners : null;
16883        if (listeners != null && listeners.size() > 0) {
16884            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16885            // perform the dispatching. The iterator is a safe guard against listeners that
16886            // could mutate the list by calling the various add/remove methods. This prevents
16887            // the array from being modified while we iterate it.
16888            for (OnAttachStateChangeListener listener : listeners) {
16889                listener.onViewAttachedToWindow(this);
16890            }
16891        }
16892
16893        int vis = info.mWindowVisibility;
16894        if (vis != GONE) {
16895            onWindowVisibilityChanged(vis);
16896            if (isShown()) {
16897                // Calling onVisibilityAggregated directly here since the subtree will also
16898                // receive dispatchAttachedToWindow and this same call
16899                onVisibilityAggregated(vis == VISIBLE);
16900            }
16901        }
16902
16903        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
16904        // As all views in the subtree will already receive dispatchAttachedToWindow
16905        // traversing the subtree again here is not desired.
16906        onVisibilityChanged(this, visibility);
16907
16908        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
16909            // If nobody has evaluated the drawable state yet, then do it now.
16910            refreshDrawableState();
16911        }
16912        needGlobalAttributesUpdate(false);
16913
16914        notifyEnterOrExitForAutoFillIfNeeded(true);
16915    }
16916
16917    void dispatchDetachedFromWindow() {
16918        AttachInfo info = mAttachInfo;
16919        if (info != null) {
16920            int vis = info.mWindowVisibility;
16921            if (vis != GONE) {
16922                onWindowVisibilityChanged(GONE);
16923                if (isShown()) {
16924                    // Invoking onVisibilityAggregated directly here since the subtree
16925                    // will also receive detached from window
16926                    onVisibilityAggregated(false);
16927                }
16928            }
16929        }
16930
16931        onDetachedFromWindow();
16932        onDetachedFromWindowInternal();
16933
16934        InputMethodManager imm = InputMethodManager.peekInstance();
16935        if (imm != null) {
16936            imm.onViewDetachedFromWindow(this);
16937        }
16938
16939        ListenerInfo li = mListenerInfo;
16940        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16941                li != null ? li.mOnAttachStateChangeListeners : null;
16942        if (listeners != null && listeners.size() > 0) {
16943            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16944            // perform the dispatching. The iterator is a safe guard against listeners that
16945            // could mutate the list by calling the various add/remove methods. This prevents
16946            // the array from being modified while we iterate it.
16947            for (OnAttachStateChangeListener listener : listeners) {
16948                listener.onViewDetachedFromWindow(this);
16949            }
16950        }
16951
16952        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
16953            mAttachInfo.mScrollContainers.remove(this);
16954            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
16955        }
16956
16957        mAttachInfo = null;
16958        if (mOverlay != null) {
16959            mOverlay.getOverlayView().dispatchDetachedFromWindow();
16960        }
16961
16962        notifyEnterOrExitForAutoFillIfNeeded(false);
16963    }
16964
16965    /**
16966     * Cancel any deferred high-level input events that were previously posted to the event queue.
16967     *
16968     * <p>Many views post high-level events such as click handlers to the event queue
16969     * to run deferred in order to preserve a desired user experience - clearing visible
16970     * pressed states before executing, etc. This method will abort any events of this nature
16971     * that are currently in flight.</p>
16972     *
16973     * <p>Custom views that generate their own high-level deferred input events should override
16974     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
16975     *
16976     * <p>This will also cancel pending input events for any child views.</p>
16977     *
16978     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
16979     * This will not impact newer events posted after this call that may occur as a result of
16980     * lower-level input events still waiting in the queue. If you are trying to prevent
16981     * double-submitted  events for the duration of some sort of asynchronous transaction
16982     * you should also take other steps to protect against unexpected double inputs e.g. calling
16983     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
16984     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
16985     */
16986    public final void cancelPendingInputEvents() {
16987        dispatchCancelPendingInputEvents();
16988    }
16989
16990    /**
16991     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
16992     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
16993     */
16994    void dispatchCancelPendingInputEvents() {
16995        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
16996        onCancelPendingInputEvents();
16997        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
16998            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
16999                    " did not call through to super.onCancelPendingInputEvents()");
17000        }
17001    }
17002
17003    /**
17004     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17005     * a parent view.
17006     *
17007     * <p>This method is responsible for removing any pending high-level input events that were
17008     * posted to the event queue to run later. Custom view classes that post their own deferred
17009     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17010     * {@link android.os.Handler} should override this method, call
17011     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17012     * </p>
17013     */
17014    public void onCancelPendingInputEvents() {
17015        removePerformClickCallback();
17016        cancelLongPress();
17017        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17018    }
17019
17020    /**
17021     * Store this view hierarchy's frozen state into the given container.
17022     *
17023     * @param container The SparseArray in which to save the view's state.
17024     *
17025     * @see #restoreHierarchyState(android.util.SparseArray)
17026     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17027     * @see #onSaveInstanceState()
17028     */
17029    public void saveHierarchyState(SparseArray<Parcelable> container) {
17030        dispatchSaveInstanceState(container);
17031    }
17032
17033    /**
17034     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17035     * this view and its children. May be overridden to modify how freezing happens to a
17036     * view's children; for example, some views may want to not store state for their children.
17037     *
17038     * @param container The SparseArray in which to save the view's state.
17039     *
17040     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17041     * @see #saveHierarchyState(android.util.SparseArray)
17042     * @see #onSaveInstanceState()
17043     */
17044    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17045        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17046            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17047            Parcelable state = onSaveInstanceState();
17048            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17049                throw new IllegalStateException(
17050                        "Derived class did not call super.onSaveInstanceState()");
17051            }
17052            if (state != null) {
17053                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17054                // + ": " + state);
17055                container.put(mID, state);
17056            }
17057        }
17058    }
17059
17060    /**
17061     * Hook allowing a view to generate a representation of its internal state
17062     * that can later be used to create a new instance with that same state.
17063     * This state should only contain information that is not persistent or can
17064     * not be reconstructed later. For example, you will never store your
17065     * current position on screen because that will be computed again when a
17066     * new instance of the view is placed in its view hierarchy.
17067     * <p>
17068     * Some examples of things you may store here: the current cursor position
17069     * in a text view (but usually not the text itself since that is stored in a
17070     * content provider or other persistent storage), the currently selected
17071     * item in a list view.
17072     *
17073     * @return Returns a Parcelable object containing the view's current dynamic
17074     *         state, or null if there is nothing interesting to save. The
17075     *         default implementation returns null.
17076     * @see #onRestoreInstanceState(android.os.Parcelable)
17077     * @see #saveHierarchyState(android.util.SparseArray)
17078     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17079     * @see #setSaveEnabled(boolean)
17080     */
17081    @CallSuper
17082    protected Parcelable onSaveInstanceState() {
17083        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17084        if (mStartActivityRequestWho != null) {
17085            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17086            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17087            return state;
17088        }
17089        return BaseSavedState.EMPTY_STATE;
17090    }
17091
17092    /**
17093     * Restore this view hierarchy's frozen state from the given container.
17094     *
17095     * @param container The SparseArray which holds previously frozen states.
17096     *
17097     * @see #saveHierarchyState(android.util.SparseArray)
17098     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17099     * @see #onRestoreInstanceState(android.os.Parcelable)
17100     */
17101    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17102        dispatchRestoreInstanceState(container);
17103    }
17104
17105    /**
17106     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17107     * state for this view and its children. May be overridden to modify how restoring
17108     * happens to a view's children; for example, some views may want to not store state
17109     * for their children.
17110     *
17111     * @param container The SparseArray which holds previously saved state.
17112     *
17113     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17114     * @see #restoreHierarchyState(android.util.SparseArray)
17115     * @see #onRestoreInstanceState(android.os.Parcelable)
17116     */
17117    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17118        if (mID != NO_ID) {
17119            Parcelable state = container.get(mID);
17120            if (state != null) {
17121                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17122                // + ": " + state);
17123                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17124                onRestoreInstanceState(state);
17125                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17126                    throw new IllegalStateException(
17127                            "Derived class did not call super.onRestoreInstanceState()");
17128                }
17129            }
17130        }
17131    }
17132
17133    /**
17134     * Hook allowing a view to re-apply a representation of its internal state that had previously
17135     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17136     * null state.
17137     *
17138     * @param state The frozen state that had previously been returned by
17139     *        {@link #onSaveInstanceState}.
17140     *
17141     * @see #onSaveInstanceState()
17142     * @see #restoreHierarchyState(android.util.SparseArray)
17143     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17144     */
17145    @CallSuper
17146    protected void onRestoreInstanceState(Parcelable state) {
17147        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17148        if (state != null && !(state instanceof AbsSavedState)) {
17149            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17150                    + "received " + state.getClass().toString() + " instead. This usually happens "
17151                    + "when two views of different type have the same id in the same hierarchy. "
17152                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17153                    + "other views do not use the same id.");
17154        }
17155        if (state != null && state instanceof BaseSavedState) {
17156            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
17157        }
17158    }
17159
17160    /**
17161     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17162     *
17163     * @return the drawing start time in milliseconds
17164     */
17165    public long getDrawingTime() {
17166        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17167    }
17168
17169    /**
17170     * <p>Enables or disables the duplication of the parent's state into this view. When
17171     * duplication is enabled, this view gets its drawable state from its parent rather
17172     * than from its own internal properties.</p>
17173     *
17174     * <p>Note: in the current implementation, setting this property to true after the
17175     * view was added to a ViewGroup might have no effect at all. This property should
17176     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17177     *
17178     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17179     * property is enabled, an exception will be thrown.</p>
17180     *
17181     * <p>Note: if the child view uses and updates additional states which are unknown to the
17182     * parent, these states should not be affected by this method.</p>
17183     *
17184     * @param enabled True to enable duplication of the parent's drawable state, false
17185     *                to disable it.
17186     *
17187     * @see #getDrawableState()
17188     * @see #isDuplicateParentStateEnabled()
17189     */
17190    public void setDuplicateParentStateEnabled(boolean enabled) {
17191        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17192    }
17193
17194    /**
17195     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17196     *
17197     * @return True if this view's drawable state is duplicated from the parent,
17198     *         false otherwise
17199     *
17200     * @see #getDrawableState()
17201     * @see #setDuplicateParentStateEnabled(boolean)
17202     */
17203    public boolean isDuplicateParentStateEnabled() {
17204        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17205    }
17206
17207    /**
17208     * <p>Specifies the type of layer backing this view. The layer can be
17209     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17210     * {@link #LAYER_TYPE_HARDWARE}.</p>
17211     *
17212     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17213     * instance that controls how the layer is composed on screen. The following
17214     * properties of the paint are taken into account when composing the layer:</p>
17215     * <ul>
17216     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17217     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17218     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17219     * </ul>
17220     *
17221     * <p>If this view has an alpha value set to < 1.0 by calling
17222     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17223     * by this view's alpha value.</p>
17224     *
17225     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17226     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17227     * for more information on when and how to use layers.</p>
17228     *
17229     * @param layerType The type of layer to use with this view, must be one of
17230     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17231     *        {@link #LAYER_TYPE_HARDWARE}
17232     * @param paint The paint used to compose the layer. This argument is optional
17233     *        and can be null. It is ignored when the layer type is
17234     *        {@link #LAYER_TYPE_NONE}
17235     *
17236     * @see #getLayerType()
17237     * @see #LAYER_TYPE_NONE
17238     * @see #LAYER_TYPE_SOFTWARE
17239     * @see #LAYER_TYPE_HARDWARE
17240     * @see #setAlpha(float)
17241     *
17242     * @attr ref android.R.styleable#View_layerType
17243     */
17244    public void setLayerType(int layerType, @Nullable Paint paint) {
17245        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17246            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17247                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17248        }
17249
17250        boolean typeChanged = mRenderNode.setLayerType(layerType);
17251
17252        if (!typeChanged) {
17253            setLayerPaint(paint);
17254            return;
17255        }
17256
17257        if (layerType != LAYER_TYPE_SOFTWARE) {
17258            // Destroy any previous software drawing cache if present
17259            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17260            // drawing cache created in View#draw when drawing to a SW canvas.
17261            destroyDrawingCache();
17262        }
17263
17264        mLayerType = layerType;
17265        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17266        mRenderNode.setLayerPaint(mLayerPaint);
17267
17268        // draw() behaves differently if we are on a layer, so we need to
17269        // invalidate() here
17270        invalidateParentCaches();
17271        invalidate(true);
17272    }
17273
17274    /**
17275     * Updates the {@link Paint} object used with the current layer (used only if the current
17276     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17277     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17278     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17279     * ensure that the view gets redrawn immediately.
17280     *
17281     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17282     * instance that controls how the layer is composed on screen. The following
17283     * properties of the paint are taken into account when composing the layer:</p>
17284     * <ul>
17285     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17286     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17287     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17288     * </ul>
17289     *
17290     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17291     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17292     *
17293     * @param paint The paint used to compose the layer. This argument is optional
17294     *        and can be null. It is ignored when the layer type is
17295     *        {@link #LAYER_TYPE_NONE}
17296     *
17297     * @see #setLayerType(int, android.graphics.Paint)
17298     */
17299    public void setLayerPaint(@Nullable Paint paint) {
17300        int layerType = getLayerType();
17301        if (layerType != LAYER_TYPE_NONE) {
17302            mLayerPaint = paint;
17303            if (layerType == LAYER_TYPE_HARDWARE) {
17304                if (mRenderNode.setLayerPaint(paint)) {
17305                    invalidateViewProperty(false, false);
17306                }
17307            } else {
17308                invalidate();
17309            }
17310        }
17311    }
17312
17313    /**
17314     * Indicates what type of layer is currently associated with this view. By default
17315     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17316     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17317     * for more information on the different types of layers.
17318     *
17319     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17320     *         {@link #LAYER_TYPE_HARDWARE}
17321     *
17322     * @see #setLayerType(int, android.graphics.Paint)
17323     * @see #buildLayer()
17324     * @see #LAYER_TYPE_NONE
17325     * @see #LAYER_TYPE_SOFTWARE
17326     * @see #LAYER_TYPE_HARDWARE
17327     */
17328    public int getLayerType() {
17329        return mLayerType;
17330    }
17331
17332    /**
17333     * Forces this view's layer to be created and this view to be rendered
17334     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17335     * invoking this method will have no effect.
17336     *
17337     * This method can for instance be used to render a view into its layer before
17338     * starting an animation. If this view is complex, rendering into the layer
17339     * before starting the animation will avoid skipping frames.
17340     *
17341     * @throws IllegalStateException If this view is not attached to a window
17342     *
17343     * @see #setLayerType(int, android.graphics.Paint)
17344     */
17345    public void buildLayer() {
17346        if (mLayerType == LAYER_TYPE_NONE) return;
17347
17348        final AttachInfo attachInfo = mAttachInfo;
17349        if (attachInfo == null) {
17350            throw new IllegalStateException("This view must be attached to a window first");
17351        }
17352
17353        if (getWidth() == 0 || getHeight() == 0) {
17354            return;
17355        }
17356
17357        switch (mLayerType) {
17358            case LAYER_TYPE_HARDWARE:
17359                updateDisplayListIfDirty();
17360                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17361                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17362                }
17363                break;
17364            case LAYER_TYPE_SOFTWARE:
17365                buildDrawingCache(true);
17366                break;
17367        }
17368    }
17369
17370    /**
17371     * Destroys all hardware rendering resources. This method is invoked
17372     * when the system needs to reclaim resources. Upon execution of this
17373     * method, you should free any OpenGL resources created by the view.
17374     *
17375     * Note: you <strong>must</strong> call
17376     * <code>super.destroyHardwareResources()</code> when overriding
17377     * this method.
17378     *
17379     * @hide
17380     */
17381    @CallSuper
17382    protected void destroyHardwareResources() {
17383        if (mOverlay != null) {
17384            mOverlay.getOverlayView().destroyHardwareResources();
17385        }
17386        if (mGhostView != null) {
17387            mGhostView.destroyHardwareResources();
17388        }
17389    }
17390
17391    /**
17392     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17393     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17394     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17395     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17396     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17397     * null.</p>
17398     *
17399     * <p>Enabling the drawing cache is similar to
17400     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17401     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17402     * drawing cache has no effect on rendering because the system uses a different mechanism
17403     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17404     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17405     * for information on how to enable software and hardware layers.</p>
17406     *
17407     * <p>This API can be used to manually generate
17408     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17409     * {@link #getDrawingCache()}.</p>
17410     *
17411     * @param enabled true to enable the drawing cache, false otherwise
17412     *
17413     * @see #isDrawingCacheEnabled()
17414     * @see #getDrawingCache()
17415     * @see #buildDrawingCache()
17416     * @see #setLayerType(int, android.graphics.Paint)
17417     */
17418    public void setDrawingCacheEnabled(boolean enabled) {
17419        mCachingFailed = false;
17420        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17421    }
17422
17423    /**
17424     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17425     *
17426     * @return true if the drawing cache is enabled
17427     *
17428     * @see #setDrawingCacheEnabled(boolean)
17429     * @see #getDrawingCache()
17430     */
17431    @ViewDebug.ExportedProperty(category = "drawing")
17432    public boolean isDrawingCacheEnabled() {
17433        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17434    }
17435
17436    /**
17437     * Debugging utility which recursively outputs the dirty state of a view and its
17438     * descendants.
17439     *
17440     * @hide
17441     */
17442    @SuppressWarnings({"UnusedDeclaration"})
17443    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17444        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17445                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17446                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17447                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17448        if (clear) {
17449            mPrivateFlags &= clearMask;
17450        }
17451        if (this instanceof ViewGroup) {
17452            ViewGroup parent = (ViewGroup) this;
17453            final int count = parent.getChildCount();
17454            for (int i = 0; i < count; i++) {
17455                final View child = parent.getChildAt(i);
17456                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17457            }
17458        }
17459    }
17460
17461    /**
17462     * This method is used by ViewGroup to cause its children to restore or recreate their
17463     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17464     * to recreate its own display list, which would happen if it went through the normal
17465     * draw/dispatchDraw mechanisms.
17466     *
17467     * @hide
17468     */
17469    protected void dispatchGetDisplayList() {}
17470
17471    /**
17472     * A view that is not attached or hardware accelerated cannot create a display list.
17473     * This method checks these conditions and returns the appropriate result.
17474     *
17475     * @return true if view has the ability to create a display list, false otherwise.
17476     *
17477     * @hide
17478     */
17479    public boolean canHaveDisplayList() {
17480        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17481    }
17482
17483    /**
17484     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17485     * @hide
17486     */
17487    @NonNull
17488    public RenderNode updateDisplayListIfDirty() {
17489        final RenderNode renderNode = mRenderNode;
17490        if (!canHaveDisplayList()) {
17491            // can't populate RenderNode, don't try
17492            return renderNode;
17493        }
17494
17495        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17496                || !renderNode.isValid()
17497                || (mRecreateDisplayList)) {
17498            // Don't need to recreate the display list, just need to tell our
17499            // children to restore/recreate theirs
17500            if (renderNode.isValid()
17501                    && !mRecreateDisplayList) {
17502                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17503                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17504                dispatchGetDisplayList();
17505
17506                return renderNode; // no work needed
17507            }
17508
17509            // If we got here, we're recreating it. Mark it as such to ensure that
17510            // we copy in child display lists into ours in drawChild()
17511            mRecreateDisplayList = true;
17512
17513            int width = mRight - mLeft;
17514            int height = mBottom - mTop;
17515            int layerType = getLayerType();
17516
17517            final DisplayListCanvas canvas = renderNode.start(width, height);
17518            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17519
17520            try {
17521                if (layerType == LAYER_TYPE_SOFTWARE) {
17522                    buildDrawingCache(true);
17523                    Bitmap cache = getDrawingCache(true);
17524                    if (cache != null) {
17525                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17526                    }
17527                } else {
17528                    computeScroll();
17529
17530                    canvas.translate(-mScrollX, -mScrollY);
17531                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17532                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17533
17534                    // Fast path for layouts with no backgrounds
17535                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17536                        dispatchDraw(canvas);
17537                        if (mOverlay != null && !mOverlay.isEmpty()) {
17538                            mOverlay.getOverlayView().draw(canvas);
17539                        }
17540                        if (debugDraw()) {
17541                            debugDrawFocus(canvas);
17542                        }
17543                    } else {
17544                        draw(canvas);
17545                    }
17546                }
17547            } finally {
17548                renderNode.end(canvas);
17549                setDisplayListProperties(renderNode);
17550            }
17551        } else {
17552            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17553            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17554        }
17555        return renderNode;
17556    }
17557
17558    private void resetDisplayList() {
17559        mRenderNode.discardDisplayList();
17560        if (mBackgroundRenderNode != null) {
17561            mBackgroundRenderNode.discardDisplayList();
17562        }
17563    }
17564
17565    /**
17566     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17567     *
17568     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17569     *
17570     * @see #getDrawingCache(boolean)
17571     */
17572    public Bitmap getDrawingCache() {
17573        return getDrawingCache(false);
17574    }
17575
17576    /**
17577     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17578     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17579     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17580     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17581     * request the drawing cache by calling this method and draw it on screen if the
17582     * returned bitmap is not null.</p>
17583     *
17584     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17585     * this method will create a bitmap of the same size as this view. Because this bitmap
17586     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17587     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17588     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17589     * size than the view. This implies that your application must be able to handle this
17590     * size.</p>
17591     *
17592     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17593     *        the current density of the screen when the application is in compatibility
17594     *        mode.
17595     *
17596     * @return A bitmap representing this view or null if cache is disabled.
17597     *
17598     * @see #setDrawingCacheEnabled(boolean)
17599     * @see #isDrawingCacheEnabled()
17600     * @see #buildDrawingCache(boolean)
17601     * @see #destroyDrawingCache()
17602     */
17603    public Bitmap getDrawingCache(boolean autoScale) {
17604        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17605            return null;
17606        }
17607        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17608            buildDrawingCache(autoScale);
17609        }
17610        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17611    }
17612
17613    /**
17614     * <p>Frees the resources used by the drawing cache. If you call
17615     * {@link #buildDrawingCache()} manually without calling
17616     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17617     * should cleanup the cache with this method afterwards.</p>
17618     *
17619     * @see #setDrawingCacheEnabled(boolean)
17620     * @see #buildDrawingCache()
17621     * @see #getDrawingCache()
17622     */
17623    public void destroyDrawingCache() {
17624        if (mDrawingCache != null) {
17625            mDrawingCache.recycle();
17626            mDrawingCache = null;
17627        }
17628        if (mUnscaledDrawingCache != null) {
17629            mUnscaledDrawingCache.recycle();
17630            mUnscaledDrawingCache = null;
17631        }
17632    }
17633
17634    /**
17635     * Setting a solid background color for the drawing cache's bitmaps will improve
17636     * performance and memory usage. Note, though that this should only be used if this
17637     * view will always be drawn on top of a solid color.
17638     *
17639     * @param color The background color to use for the drawing cache's bitmap
17640     *
17641     * @see #setDrawingCacheEnabled(boolean)
17642     * @see #buildDrawingCache()
17643     * @see #getDrawingCache()
17644     */
17645    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17646        if (color != mDrawingCacheBackgroundColor) {
17647            mDrawingCacheBackgroundColor = color;
17648            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17649        }
17650    }
17651
17652    /**
17653     * @see #setDrawingCacheBackgroundColor(int)
17654     *
17655     * @return The background color to used for the drawing cache's bitmap
17656     */
17657    @ColorInt
17658    public int getDrawingCacheBackgroundColor() {
17659        return mDrawingCacheBackgroundColor;
17660    }
17661
17662    /**
17663     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17664     *
17665     * @see #buildDrawingCache(boolean)
17666     */
17667    public void buildDrawingCache() {
17668        buildDrawingCache(false);
17669    }
17670
17671    /**
17672     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17673     *
17674     * <p>If you call {@link #buildDrawingCache()} manually without calling
17675     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17676     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17677     *
17678     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17679     * this method will create a bitmap of the same size as this view. Because this bitmap
17680     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17681     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17682     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17683     * size than the view. This implies that your application must be able to handle this
17684     * size.</p>
17685     *
17686     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17687     * you do not need the drawing cache bitmap, calling this method will increase memory
17688     * usage and cause the view to be rendered in software once, thus negatively impacting
17689     * performance.</p>
17690     *
17691     * @see #getDrawingCache()
17692     * @see #destroyDrawingCache()
17693     */
17694    public void buildDrawingCache(boolean autoScale) {
17695        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17696                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17697            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17698                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17699                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17700            }
17701            try {
17702                buildDrawingCacheImpl(autoScale);
17703            } finally {
17704                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17705            }
17706        }
17707    }
17708
17709    /**
17710     * private, internal implementation of buildDrawingCache, used to enable tracing
17711     */
17712    private void buildDrawingCacheImpl(boolean autoScale) {
17713        mCachingFailed = false;
17714
17715        int width = mRight - mLeft;
17716        int height = mBottom - mTop;
17717
17718        final AttachInfo attachInfo = mAttachInfo;
17719        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17720
17721        if (autoScale && scalingRequired) {
17722            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17723            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17724        }
17725
17726        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17727        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17728        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17729
17730        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17731        final long drawingCacheSize =
17732                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17733        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17734            if (width > 0 && height > 0) {
17735                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17736                        + " too large to fit into a software layer (or drawing cache), needs "
17737                        + projectedBitmapSize + " bytes, only "
17738                        + drawingCacheSize + " available");
17739            }
17740            destroyDrawingCache();
17741            mCachingFailed = true;
17742            return;
17743        }
17744
17745        boolean clear = true;
17746        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17747
17748        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17749            Bitmap.Config quality;
17750            if (!opaque) {
17751                // Never pick ARGB_4444 because it looks awful
17752                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17753                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17754                    case DRAWING_CACHE_QUALITY_AUTO:
17755                    case DRAWING_CACHE_QUALITY_LOW:
17756                    case DRAWING_CACHE_QUALITY_HIGH:
17757                    default:
17758                        quality = Bitmap.Config.ARGB_8888;
17759                        break;
17760                }
17761            } else {
17762                // Optimization for translucent windows
17763                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17764                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17765            }
17766
17767            // Try to cleanup memory
17768            if (bitmap != null) bitmap.recycle();
17769
17770            try {
17771                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17772                        width, height, quality);
17773                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17774                if (autoScale) {
17775                    mDrawingCache = bitmap;
17776                } else {
17777                    mUnscaledDrawingCache = bitmap;
17778                }
17779                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17780            } catch (OutOfMemoryError e) {
17781                // If there is not enough memory to create the bitmap cache, just
17782                // ignore the issue as bitmap caches are not required to draw the
17783                // view hierarchy
17784                if (autoScale) {
17785                    mDrawingCache = null;
17786                } else {
17787                    mUnscaledDrawingCache = null;
17788                }
17789                mCachingFailed = true;
17790                return;
17791            }
17792
17793            clear = drawingCacheBackgroundColor != 0;
17794        }
17795
17796        Canvas canvas;
17797        if (attachInfo != null) {
17798            canvas = attachInfo.mCanvas;
17799            if (canvas == null) {
17800                canvas = new Canvas();
17801            }
17802            canvas.setBitmap(bitmap);
17803            // Temporarily clobber the cached Canvas in case one of our children
17804            // is also using a drawing cache. Without this, the children would
17805            // steal the canvas by attaching their own bitmap to it and bad, bad
17806            // thing would happen (invisible views, corrupted drawings, etc.)
17807            attachInfo.mCanvas = null;
17808        } else {
17809            // This case should hopefully never or seldom happen
17810            canvas = new Canvas(bitmap);
17811        }
17812
17813        if (clear) {
17814            bitmap.eraseColor(drawingCacheBackgroundColor);
17815        }
17816
17817        computeScroll();
17818        final int restoreCount = canvas.save();
17819
17820        if (autoScale && scalingRequired) {
17821            final float scale = attachInfo.mApplicationScale;
17822            canvas.scale(scale, scale);
17823        }
17824
17825        canvas.translate(-mScrollX, -mScrollY);
17826
17827        mPrivateFlags |= PFLAG_DRAWN;
17828        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17829                mLayerType != LAYER_TYPE_NONE) {
17830            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17831        }
17832
17833        // Fast path for layouts with no backgrounds
17834        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17835            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17836            dispatchDraw(canvas);
17837            if (mOverlay != null && !mOverlay.isEmpty()) {
17838                mOverlay.getOverlayView().draw(canvas);
17839            }
17840        } else {
17841            draw(canvas);
17842        }
17843
17844        canvas.restoreToCount(restoreCount);
17845        canvas.setBitmap(null);
17846
17847        if (attachInfo != null) {
17848            // Restore the cached Canvas for our siblings
17849            attachInfo.mCanvas = canvas;
17850        }
17851    }
17852
17853    /**
17854     * Create a snapshot of the view into a bitmap.  We should probably make
17855     * some form of this public, but should think about the API.
17856     *
17857     * @hide
17858     */
17859    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17860        int width = mRight - mLeft;
17861        int height = mBottom - mTop;
17862
17863        final AttachInfo attachInfo = mAttachInfo;
17864        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
17865        width = (int) ((width * scale) + 0.5f);
17866        height = (int) ((height * scale) + 0.5f);
17867
17868        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17869                width > 0 ? width : 1, height > 0 ? height : 1, quality);
17870        if (bitmap == null) {
17871            throw new OutOfMemoryError();
17872        }
17873
17874        Resources resources = getResources();
17875        if (resources != null) {
17876            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
17877        }
17878
17879        Canvas canvas;
17880        if (attachInfo != null) {
17881            canvas = attachInfo.mCanvas;
17882            if (canvas == null) {
17883                canvas = new Canvas();
17884            }
17885            canvas.setBitmap(bitmap);
17886            // Temporarily clobber the cached Canvas in case one of our children
17887            // is also using a drawing cache. Without this, the children would
17888            // steal the canvas by attaching their own bitmap to it and bad, bad
17889            // things would happen (invisible views, corrupted drawings, etc.)
17890            attachInfo.mCanvas = null;
17891        } else {
17892            // This case should hopefully never or seldom happen
17893            canvas = new Canvas(bitmap);
17894        }
17895
17896        if ((backgroundColor & 0xff000000) != 0) {
17897            bitmap.eraseColor(backgroundColor);
17898        }
17899
17900        computeScroll();
17901        final int restoreCount = canvas.save();
17902        canvas.scale(scale, scale);
17903        canvas.translate(-mScrollX, -mScrollY);
17904
17905        // Temporarily remove the dirty mask
17906        int flags = mPrivateFlags;
17907        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17908
17909        // Fast path for layouts with no backgrounds
17910        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17911            dispatchDraw(canvas);
17912            if (mOverlay != null && !mOverlay.isEmpty()) {
17913                mOverlay.getOverlayView().draw(canvas);
17914            }
17915        } else {
17916            draw(canvas);
17917        }
17918
17919        mPrivateFlags = flags;
17920
17921        canvas.restoreToCount(restoreCount);
17922        canvas.setBitmap(null);
17923
17924        if (attachInfo != null) {
17925            // Restore the cached Canvas for our siblings
17926            attachInfo.mCanvas = canvas;
17927        }
17928
17929        return bitmap;
17930    }
17931
17932    /**
17933     * Indicates whether this View is currently in edit mode. A View is usually
17934     * in edit mode when displayed within a developer tool. For instance, if
17935     * this View is being drawn by a visual user interface builder, this method
17936     * should return true.
17937     *
17938     * Subclasses should check the return value of this method to provide
17939     * different behaviors if their normal behavior might interfere with the
17940     * host environment. For instance: the class spawns a thread in its
17941     * constructor, the drawing code relies on device-specific features, etc.
17942     *
17943     * This method is usually checked in the drawing code of custom widgets.
17944     *
17945     * @return True if this View is in edit mode, false otherwise.
17946     */
17947    public boolean isInEditMode() {
17948        return false;
17949    }
17950
17951    /**
17952     * If the View draws content inside its padding and enables fading edges,
17953     * it needs to support padding offsets. Padding offsets are added to the
17954     * fading edges to extend the length of the fade so that it covers pixels
17955     * drawn inside the padding.
17956     *
17957     * Subclasses of this class should override this method if they need
17958     * to draw content inside the padding.
17959     *
17960     * @return True if padding offset must be applied, false otherwise.
17961     *
17962     * @see #getLeftPaddingOffset()
17963     * @see #getRightPaddingOffset()
17964     * @see #getTopPaddingOffset()
17965     * @see #getBottomPaddingOffset()
17966     *
17967     * @since CURRENT
17968     */
17969    protected boolean isPaddingOffsetRequired() {
17970        return false;
17971    }
17972
17973    /**
17974     * Amount by which to extend the left fading region. Called only when
17975     * {@link #isPaddingOffsetRequired()} returns true.
17976     *
17977     * @return The left padding offset in pixels.
17978     *
17979     * @see #isPaddingOffsetRequired()
17980     *
17981     * @since CURRENT
17982     */
17983    protected int getLeftPaddingOffset() {
17984        return 0;
17985    }
17986
17987    /**
17988     * Amount by which to extend the right fading region. Called only when
17989     * {@link #isPaddingOffsetRequired()} returns true.
17990     *
17991     * @return The right padding offset in pixels.
17992     *
17993     * @see #isPaddingOffsetRequired()
17994     *
17995     * @since CURRENT
17996     */
17997    protected int getRightPaddingOffset() {
17998        return 0;
17999    }
18000
18001    /**
18002     * Amount by which to extend the top fading region. Called only when
18003     * {@link #isPaddingOffsetRequired()} returns true.
18004     *
18005     * @return The top padding offset in pixels.
18006     *
18007     * @see #isPaddingOffsetRequired()
18008     *
18009     * @since CURRENT
18010     */
18011    protected int getTopPaddingOffset() {
18012        return 0;
18013    }
18014
18015    /**
18016     * Amount by which to extend the bottom fading region. Called only when
18017     * {@link #isPaddingOffsetRequired()} returns true.
18018     *
18019     * @return The bottom padding offset in pixels.
18020     *
18021     * @see #isPaddingOffsetRequired()
18022     *
18023     * @since CURRENT
18024     */
18025    protected int getBottomPaddingOffset() {
18026        return 0;
18027    }
18028
18029    /**
18030     * @hide
18031     * @param offsetRequired
18032     */
18033    protected int getFadeTop(boolean offsetRequired) {
18034        int top = mPaddingTop;
18035        if (offsetRequired) top += getTopPaddingOffset();
18036        return top;
18037    }
18038
18039    /**
18040     * @hide
18041     * @param offsetRequired
18042     */
18043    protected int getFadeHeight(boolean offsetRequired) {
18044        int padding = mPaddingTop;
18045        if (offsetRequired) padding += getTopPaddingOffset();
18046        return mBottom - mTop - mPaddingBottom - padding;
18047    }
18048
18049    /**
18050     * <p>Indicates whether this view is attached to a hardware accelerated
18051     * window or not.</p>
18052     *
18053     * <p>Even if this method returns true, it does not mean that every call
18054     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18055     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18056     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18057     * window is hardware accelerated,
18058     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18059     * return false, and this method will return true.</p>
18060     *
18061     * @return True if the view is attached to a window and the window is
18062     *         hardware accelerated; false in any other case.
18063     */
18064    @ViewDebug.ExportedProperty(category = "drawing")
18065    public boolean isHardwareAccelerated() {
18066        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18067    }
18068
18069    /**
18070     * Sets a rectangular area on this view to which the view will be clipped
18071     * when it is drawn. Setting the value to null will remove the clip bounds
18072     * and the view will draw normally, using its full bounds.
18073     *
18074     * @param clipBounds The rectangular area, in the local coordinates of
18075     * this view, to which future drawing operations will be clipped.
18076     */
18077    public void setClipBounds(Rect clipBounds) {
18078        if (clipBounds == mClipBounds
18079                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18080            return;
18081        }
18082        if (clipBounds != null) {
18083            if (mClipBounds == null) {
18084                mClipBounds = new Rect(clipBounds);
18085            } else {
18086                mClipBounds.set(clipBounds);
18087            }
18088        } else {
18089            mClipBounds = null;
18090        }
18091        mRenderNode.setClipBounds(mClipBounds);
18092        invalidateViewProperty(false, false);
18093    }
18094
18095    /**
18096     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18097     *
18098     * @return A copy of the current clip bounds if clip bounds are set,
18099     * otherwise null.
18100     */
18101    public Rect getClipBounds() {
18102        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18103    }
18104
18105
18106    /**
18107     * Populates an output rectangle with the clip bounds of the view,
18108     * returning {@code true} if successful or {@code false} if the view's
18109     * clip bounds are {@code null}.
18110     *
18111     * @param outRect rectangle in which to place the clip bounds of the view
18112     * @return {@code true} if successful or {@code false} if the view's
18113     *         clip bounds are {@code null}
18114     */
18115    public boolean getClipBounds(Rect outRect) {
18116        if (mClipBounds != null) {
18117            outRect.set(mClipBounds);
18118            return true;
18119        }
18120        return false;
18121    }
18122
18123    /**
18124     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18125     * case of an active Animation being run on the view.
18126     */
18127    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18128            Animation a, boolean scalingRequired) {
18129        Transformation invalidationTransform;
18130        final int flags = parent.mGroupFlags;
18131        final boolean initialized = a.isInitialized();
18132        if (!initialized) {
18133            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18134            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18135            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18136            onAnimationStart();
18137        }
18138
18139        final Transformation t = parent.getChildTransformation();
18140        boolean more = a.getTransformation(drawingTime, t, 1f);
18141        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18142            if (parent.mInvalidationTransformation == null) {
18143                parent.mInvalidationTransformation = new Transformation();
18144            }
18145            invalidationTransform = parent.mInvalidationTransformation;
18146            a.getTransformation(drawingTime, invalidationTransform, 1f);
18147        } else {
18148            invalidationTransform = t;
18149        }
18150
18151        if (more) {
18152            if (!a.willChangeBounds()) {
18153                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18154                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18155                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18156                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18157                    // The child need to draw an animation, potentially offscreen, so
18158                    // make sure we do not cancel invalidate requests
18159                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18160                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18161                }
18162            } else {
18163                if (parent.mInvalidateRegion == null) {
18164                    parent.mInvalidateRegion = new RectF();
18165                }
18166                final RectF region = parent.mInvalidateRegion;
18167                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18168                        invalidationTransform);
18169
18170                // The child need to draw an animation, potentially offscreen, so
18171                // make sure we do not cancel invalidate requests
18172                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18173
18174                final int left = mLeft + (int) region.left;
18175                final int top = mTop + (int) region.top;
18176                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18177                        top + (int) (region.height() + .5f));
18178            }
18179        }
18180        return more;
18181    }
18182
18183    /**
18184     * This method is called by getDisplayList() when a display list is recorded for a View.
18185     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18186     */
18187    void setDisplayListProperties(RenderNode renderNode) {
18188        if (renderNode != null) {
18189            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18190            renderNode.setClipToBounds(mParent instanceof ViewGroup
18191                    && ((ViewGroup) mParent).getClipChildren());
18192
18193            float alpha = 1;
18194            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18195                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18196                ViewGroup parentVG = (ViewGroup) mParent;
18197                final Transformation t = parentVG.getChildTransformation();
18198                if (parentVG.getChildStaticTransformation(this, t)) {
18199                    final int transformType = t.getTransformationType();
18200                    if (transformType != Transformation.TYPE_IDENTITY) {
18201                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18202                            alpha = t.getAlpha();
18203                        }
18204                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18205                            renderNode.setStaticMatrix(t.getMatrix());
18206                        }
18207                    }
18208                }
18209            }
18210            if (mTransformationInfo != null) {
18211                alpha *= getFinalAlpha();
18212                if (alpha < 1) {
18213                    final int multipliedAlpha = (int) (255 * alpha);
18214                    if (onSetAlpha(multipliedAlpha)) {
18215                        alpha = 1;
18216                    }
18217                }
18218                renderNode.setAlpha(alpha);
18219            } else if (alpha < 1) {
18220                renderNode.setAlpha(alpha);
18221            }
18222        }
18223    }
18224
18225    /**
18226     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18227     *
18228     * This is where the View specializes rendering behavior based on layer type,
18229     * and hardware acceleration.
18230     */
18231    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18232        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18233        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18234         *
18235         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18236         * HW accelerated, it can't handle drawing RenderNodes.
18237         */
18238        boolean drawingWithRenderNode = mAttachInfo != null
18239                && mAttachInfo.mHardwareAccelerated
18240                && hardwareAcceleratedCanvas;
18241
18242        boolean more = false;
18243        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18244        final int parentFlags = parent.mGroupFlags;
18245
18246        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18247            parent.getChildTransformation().clear();
18248            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18249        }
18250
18251        Transformation transformToApply = null;
18252        boolean concatMatrix = false;
18253        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18254        final Animation a = getAnimation();
18255        if (a != null) {
18256            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18257            concatMatrix = a.willChangeTransformationMatrix();
18258            if (concatMatrix) {
18259                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18260            }
18261            transformToApply = parent.getChildTransformation();
18262        } else {
18263            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18264                // No longer animating: clear out old animation matrix
18265                mRenderNode.setAnimationMatrix(null);
18266                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18267            }
18268            if (!drawingWithRenderNode
18269                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18270                final Transformation t = parent.getChildTransformation();
18271                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18272                if (hasTransform) {
18273                    final int transformType = t.getTransformationType();
18274                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18275                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18276                }
18277            }
18278        }
18279
18280        concatMatrix |= !childHasIdentityMatrix;
18281
18282        // Sets the flag as early as possible to allow draw() implementations
18283        // to call invalidate() successfully when doing animations
18284        mPrivateFlags |= PFLAG_DRAWN;
18285
18286        if (!concatMatrix &&
18287                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18288                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18289                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18290                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18291            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18292            return more;
18293        }
18294        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18295
18296        if (hardwareAcceleratedCanvas) {
18297            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18298            // retain the flag's value temporarily in the mRecreateDisplayList flag
18299            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18300            mPrivateFlags &= ~PFLAG_INVALIDATED;
18301        }
18302
18303        RenderNode renderNode = null;
18304        Bitmap cache = null;
18305        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18306        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18307             if (layerType != LAYER_TYPE_NONE) {
18308                 // If not drawing with RenderNode, treat HW layers as SW
18309                 layerType = LAYER_TYPE_SOFTWARE;
18310                 buildDrawingCache(true);
18311            }
18312            cache = getDrawingCache(true);
18313        }
18314
18315        if (drawingWithRenderNode) {
18316            // Delay getting the display list until animation-driven alpha values are
18317            // set up and possibly passed on to the view
18318            renderNode = updateDisplayListIfDirty();
18319            if (!renderNode.isValid()) {
18320                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18321                // to getDisplayList(), the display list will be marked invalid and we should not
18322                // try to use it again.
18323                renderNode = null;
18324                drawingWithRenderNode = false;
18325            }
18326        }
18327
18328        int sx = 0;
18329        int sy = 0;
18330        if (!drawingWithRenderNode) {
18331            computeScroll();
18332            sx = mScrollX;
18333            sy = mScrollY;
18334        }
18335
18336        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18337        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18338
18339        int restoreTo = -1;
18340        if (!drawingWithRenderNode || transformToApply != null) {
18341            restoreTo = canvas.save();
18342        }
18343        if (offsetForScroll) {
18344            canvas.translate(mLeft - sx, mTop - sy);
18345        } else {
18346            if (!drawingWithRenderNode) {
18347                canvas.translate(mLeft, mTop);
18348            }
18349            if (scalingRequired) {
18350                if (drawingWithRenderNode) {
18351                    // TODO: Might not need this if we put everything inside the DL
18352                    restoreTo = canvas.save();
18353                }
18354                // mAttachInfo cannot be null, otherwise scalingRequired == false
18355                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18356                canvas.scale(scale, scale);
18357            }
18358        }
18359
18360        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18361        if (transformToApply != null
18362                || alpha < 1
18363                || !hasIdentityMatrix()
18364                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18365            if (transformToApply != null || !childHasIdentityMatrix) {
18366                int transX = 0;
18367                int transY = 0;
18368
18369                if (offsetForScroll) {
18370                    transX = -sx;
18371                    transY = -sy;
18372                }
18373
18374                if (transformToApply != null) {
18375                    if (concatMatrix) {
18376                        if (drawingWithRenderNode) {
18377                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18378                        } else {
18379                            // Undo the scroll translation, apply the transformation matrix,
18380                            // then redo the scroll translate to get the correct result.
18381                            canvas.translate(-transX, -transY);
18382                            canvas.concat(transformToApply.getMatrix());
18383                            canvas.translate(transX, transY);
18384                        }
18385                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18386                    }
18387
18388                    float transformAlpha = transformToApply.getAlpha();
18389                    if (transformAlpha < 1) {
18390                        alpha *= transformAlpha;
18391                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18392                    }
18393                }
18394
18395                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18396                    canvas.translate(-transX, -transY);
18397                    canvas.concat(getMatrix());
18398                    canvas.translate(transX, transY);
18399                }
18400            }
18401
18402            // Deal with alpha if it is or used to be <1
18403            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18404                if (alpha < 1) {
18405                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18406                } else {
18407                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18408                }
18409                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18410                if (!drawingWithDrawingCache) {
18411                    final int multipliedAlpha = (int) (255 * alpha);
18412                    if (!onSetAlpha(multipliedAlpha)) {
18413                        if (drawingWithRenderNode) {
18414                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18415                        } else if (layerType == LAYER_TYPE_NONE) {
18416                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18417                                    multipliedAlpha);
18418                        }
18419                    } else {
18420                        // Alpha is handled by the child directly, clobber the layer's alpha
18421                        mPrivateFlags |= PFLAG_ALPHA_SET;
18422                    }
18423                }
18424            }
18425        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18426            onSetAlpha(255);
18427            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18428        }
18429
18430        if (!drawingWithRenderNode) {
18431            // apply clips directly, since RenderNode won't do it for this draw
18432            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18433                if (offsetForScroll) {
18434                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18435                } else {
18436                    if (!scalingRequired || cache == null) {
18437                        canvas.clipRect(0, 0, getWidth(), getHeight());
18438                    } else {
18439                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18440                    }
18441                }
18442            }
18443
18444            if (mClipBounds != null) {
18445                // clip bounds ignore scroll
18446                canvas.clipRect(mClipBounds);
18447            }
18448        }
18449
18450        if (!drawingWithDrawingCache) {
18451            if (drawingWithRenderNode) {
18452                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18453                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18454            } else {
18455                // Fast path for layouts with no backgrounds
18456                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18457                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18458                    dispatchDraw(canvas);
18459                } else {
18460                    draw(canvas);
18461                }
18462            }
18463        } else if (cache != null) {
18464            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18465            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18466                // no layer paint, use temporary paint to draw bitmap
18467                Paint cachePaint = parent.mCachePaint;
18468                if (cachePaint == null) {
18469                    cachePaint = new Paint();
18470                    cachePaint.setDither(false);
18471                    parent.mCachePaint = cachePaint;
18472                }
18473                cachePaint.setAlpha((int) (alpha * 255));
18474                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18475            } else {
18476                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18477                int layerPaintAlpha = mLayerPaint.getAlpha();
18478                if (alpha < 1) {
18479                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18480                }
18481                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18482                if (alpha < 1) {
18483                    mLayerPaint.setAlpha(layerPaintAlpha);
18484                }
18485            }
18486        }
18487
18488        if (restoreTo >= 0) {
18489            canvas.restoreToCount(restoreTo);
18490        }
18491
18492        if (a != null && !more) {
18493            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18494                onSetAlpha(255);
18495            }
18496            parent.finishAnimatingView(this, a);
18497        }
18498
18499        if (more && hardwareAcceleratedCanvas) {
18500            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18501                // alpha animations should cause the child to recreate its display list
18502                invalidate(true);
18503            }
18504        }
18505
18506        mRecreateDisplayList = false;
18507
18508        return more;
18509    }
18510
18511    static Paint getDebugPaint() {
18512        if (sDebugPaint == null) {
18513            sDebugPaint = new Paint();
18514            sDebugPaint.setAntiAlias(false);
18515        }
18516        return sDebugPaint;
18517    }
18518
18519    final int dipsToPixels(int dips) {
18520        float scale = getContext().getResources().getDisplayMetrics().density;
18521        return (int) (dips * scale + 0.5f);
18522    }
18523
18524    final private void debugDrawFocus(Canvas canvas) {
18525        if (isFocused()) {
18526            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18527            final int l = mScrollX;
18528            final int r = l + mRight - mLeft;
18529            final int t = mScrollY;
18530            final int b = t + mBottom - mTop;
18531
18532            final Paint paint = getDebugPaint();
18533            paint.setColor(DEBUG_CORNERS_COLOR);
18534
18535            // Draw squares in corners.
18536            paint.setStyle(Paint.Style.FILL);
18537            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18538            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18539            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18540            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18541
18542            // Draw big X across the view.
18543            paint.setStyle(Paint.Style.STROKE);
18544            canvas.drawLine(l, t, r, b, paint);
18545            canvas.drawLine(l, b, r, t, paint);
18546        }
18547    }
18548
18549    /**
18550     * Manually render this view (and all of its children) to the given Canvas.
18551     * The view must have already done a full layout before this function is
18552     * called.  When implementing a view, implement
18553     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18554     * If you do need to override this method, call the superclass version.
18555     *
18556     * @param canvas The Canvas to which the View is rendered.
18557     */
18558    @CallSuper
18559    public void draw(Canvas canvas) {
18560        final int privateFlags = mPrivateFlags;
18561        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18562                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18563        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18564
18565        /*
18566         * Draw traversal performs several drawing steps which must be executed
18567         * in the appropriate order:
18568         *
18569         *      1. Draw the background
18570         *      2. If necessary, save the canvas' layers to prepare for fading
18571         *      3. Draw view's content
18572         *      4. Draw children
18573         *      5. If necessary, draw the fading edges and restore layers
18574         *      6. Draw decorations (scrollbars for instance)
18575         */
18576
18577        // Step 1, draw the background, if needed
18578        int saveCount;
18579
18580        if (!dirtyOpaque) {
18581            drawBackground(canvas);
18582        }
18583
18584        // skip step 2 & 5 if possible (common case)
18585        final int viewFlags = mViewFlags;
18586        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18587        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18588        if (!verticalEdges && !horizontalEdges) {
18589            // Step 3, draw the content
18590            if (!dirtyOpaque) onDraw(canvas);
18591
18592            // Step 4, draw the children
18593            dispatchDraw(canvas);
18594
18595            // Overlay is part of the content and draws beneath Foreground
18596            if (mOverlay != null && !mOverlay.isEmpty()) {
18597                mOverlay.getOverlayView().dispatchDraw(canvas);
18598            }
18599
18600            // Step 6, draw decorations (foreground, scrollbars)
18601            onDrawForeground(canvas);
18602
18603            if (debugDraw()) {
18604                debugDrawFocus(canvas);
18605            }
18606
18607            // we're done...
18608            return;
18609        }
18610
18611        /*
18612         * Here we do the full fledged routine...
18613         * (this is an uncommon case where speed matters less,
18614         * this is why we repeat some of the tests that have been
18615         * done above)
18616         */
18617
18618        boolean drawTop = false;
18619        boolean drawBottom = false;
18620        boolean drawLeft = false;
18621        boolean drawRight = false;
18622
18623        float topFadeStrength = 0.0f;
18624        float bottomFadeStrength = 0.0f;
18625        float leftFadeStrength = 0.0f;
18626        float rightFadeStrength = 0.0f;
18627
18628        // Step 2, save the canvas' layers
18629        int paddingLeft = mPaddingLeft;
18630
18631        final boolean offsetRequired = isPaddingOffsetRequired();
18632        if (offsetRequired) {
18633            paddingLeft += getLeftPaddingOffset();
18634        }
18635
18636        int left = mScrollX + paddingLeft;
18637        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18638        int top = mScrollY + getFadeTop(offsetRequired);
18639        int bottom = top + getFadeHeight(offsetRequired);
18640
18641        if (offsetRequired) {
18642            right += getRightPaddingOffset();
18643            bottom += getBottomPaddingOffset();
18644        }
18645
18646        final ScrollabilityCache scrollabilityCache = mScrollCache;
18647        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18648        int length = (int) fadeHeight;
18649
18650        // clip the fade length if top and bottom fades overlap
18651        // overlapping fades produce odd-looking artifacts
18652        if (verticalEdges && (top + length > bottom - length)) {
18653            length = (bottom - top) / 2;
18654        }
18655
18656        // also clip horizontal fades if necessary
18657        if (horizontalEdges && (left + length > right - length)) {
18658            length = (right - left) / 2;
18659        }
18660
18661        if (verticalEdges) {
18662            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18663            drawTop = topFadeStrength * fadeHeight > 1.0f;
18664            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18665            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18666        }
18667
18668        if (horizontalEdges) {
18669            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18670            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18671            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18672            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18673        }
18674
18675        saveCount = canvas.getSaveCount();
18676
18677        int solidColor = getSolidColor();
18678        if (solidColor == 0) {
18679            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18680
18681            if (drawTop) {
18682                canvas.saveLayer(left, top, right, top + length, null, flags);
18683            }
18684
18685            if (drawBottom) {
18686                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18687            }
18688
18689            if (drawLeft) {
18690                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18691            }
18692
18693            if (drawRight) {
18694                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18695            }
18696        } else {
18697            scrollabilityCache.setFadeColor(solidColor);
18698        }
18699
18700        // Step 3, draw the content
18701        if (!dirtyOpaque) onDraw(canvas);
18702
18703        // Step 4, draw the children
18704        dispatchDraw(canvas);
18705
18706        // Step 5, draw the fade effect and restore layers
18707        final Paint p = scrollabilityCache.paint;
18708        final Matrix matrix = scrollabilityCache.matrix;
18709        final Shader fade = scrollabilityCache.shader;
18710
18711        if (drawTop) {
18712            matrix.setScale(1, fadeHeight * topFadeStrength);
18713            matrix.postTranslate(left, top);
18714            fade.setLocalMatrix(matrix);
18715            p.setShader(fade);
18716            canvas.drawRect(left, top, right, top + length, p);
18717        }
18718
18719        if (drawBottom) {
18720            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18721            matrix.postRotate(180);
18722            matrix.postTranslate(left, bottom);
18723            fade.setLocalMatrix(matrix);
18724            p.setShader(fade);
18725            canvas.drawRect(left, bottom - length, right, bottom, p);
18726        }
18727
18728        if (drawLeft) {
18729            matrix.setScale(1, fadeHeight * leftFadeStrength);
18730            matrix.postRotate(-90);
18731            matrix.postTranslate(left, top);
18732            fade.setLocalMatrix(matrix);
18733            p.setShader(fade);
18734            canvas.drawRect(left, top, left + length, bottom, p);
18735        }
18736
18737        if (drawRight) {
18738            matrix.setScale(1, fadeHeight * rightFadeStrength);
18739            matrix.postRotate(90);
18740            matrix.postTranslate(right, top);
18741            fade.setLocalMatrix(matrix);
18742            p.setShader(fade);
18743            canvas.drawRect(right - length, top, right, bottom, p);
18744        }
18745
18746        canvas.restoreToCount(saveCount);
18747
18748        // Overlay is part of the content and draws beneath Foreground
18749        if (mOverlay != null && !mOverlay.isEmpty()) {
18750            mOverlay.getOverlayView().dispatchDraw(canvas);
18751        }
18752
18753        // Step 6, draw decorations (foreground, scrollbars)
18754        onDrawForeground(canvas);
18755
18756        if (debugDraw()) {
18757            debugDrawFocus(canvas);
18758        }
18759    }
18760
18761    /**
18762     * Draws the background onto the specified canvas.
18763     *
18764     * @param canvas Canvas on which to draw the background
18765     */
18766    private void drawBackground(Canvas canvas) {
18767        final Drawable background = mBackground;
18768        if (background == null) {
18769            return;
18770        }
18771
18772        setBackgroundBounds();
18773
18774        // Attempt to use a display list if requested.
18775        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18776                && mAttachInfo.mThreadedRenderer != null) {
18777            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18778
18779            final RenderNode renderNode = mBackgroundRenderNode;
18780            if (renderNode != null && renderNode.isValid()) {
18781                setBackgroundRenderNodeProperties(renderNode);
18782                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18783                return;
18784            }
18785        }
18786
18787        final int scrollX = mScrollX;
18788        final int scrollY = mScrollY;
18789        if ((scrollX | scrollY) == 0) {
18790            background.draw(canvas);
18791        } else {
18792            canvas.translate(scrollX, scrollY);
18793            background.draw(canvas);
18794            canvas.translate(-scrollX, -scrollY);
18795        }
18796    }
18797
18798    /**
18799     * Sets the correct background bounds and rebuilds the outline, if needed.
18800     * <p/>
18801     * This is called by LayoutLib.
18802     */
18803    void setBackgroundBounds() {
18804        if (mBackgroundSizeChanged && mBackground != null) {
18805            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18806            mBackgroundSizeChanged = false;
18807            rebuildOutline();
18808        }
18809    }
18810
18811    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18812        renderNode.setTranslationX(mScrollX);
18813        renderNode.setTranslationY(mScrollY);
18814    }
18815
18816    /**
18817     * Creates a new display list or updates the existing display list for the
18818     * specified Drawable.
18819     *
18820     * @param drawable Drawable for which to create a display list
18821     * @param renderNode Existing RenderNode, or {@code null}
18822     * @return A valid display list for the specified drawable
18823     */
18824    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18825        if (renderNode == null) {
18826            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18827        }
18828
18829        final Rect bounds = drawable.getBounds();
18830        final int width = bounds.width();
18831        final int height = bounds.height();
18832        final DisplayListCanvas canvas = renderNode.start(width, height);
18833
18834        // Reverse left/top translation done by drawable canvas, which will
18835        // instead be applied by rendernode's LTRB bounds below. This way, the
18836        // drawable's bounds match with its rendernode bounds and its content
18837        // will lie within those bounds in the rendernode tree.
18838        canvas.translate(-bounds.left, -bounds.top);
18839
18840        try {
18841            drawable.draw(canvas);
18842        } finally {
18843            renderNode.end(canvas);
18844        }
18845
18846        // Set up drawable properties that are view-independent.
18847        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18848        renderNode.setProjectBackwards(drawable.isProjected());
18849        renderNode.setProjectionReceiver(true);
18850        renderNode.setClipToBounds(false);
18851        return renderNode;
18852    }
18853
18854    /**
18855     * Returns the overlay for this view, creating it if it does not yet exist.
18856     * Adding drawables to the overlay will cause them to be displayed whenever
18857     * the view itself is redrawn. Objects in the overlay should be actively
18858     * managed: remove them when they should not be displayed anymore. The
18859     * overlay will always have the same size as its host view.
18860     *
18861     * <p>Note: Overlays do not currently work correctly with {@link
18862     * SurfaceView} or {@link TextureView}; contents in overlays for these
18863     * types of views may not display correctly.</p>
18864     *
18865     * @return The ViewOverlay object for this view.
18866     * @see ViewOverlay
18867     */
18868    public ViewOverlay getOverlay() {
18869        if (mOverlay == null) {
18870            mOverlay = new ViewOverlay(mContext, this);
18871        }
18872        return mOverlay;
18873    }
18874
18875    /**
18876     * Override this if your view is known to always be drawn on top of a solid color background,
18877     * and needs to draw fading edges. Returning a non-zero color enables the view system to
18878     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
18879     * should be set to 0xFF.
18880     *
18881     * @see #setVerticalFadingEdgeEnabled(boolean)
18882     * @see #setHorizontalFadingEdgeEnabled(boolean)
18883     *
18884     * @return The known solid color background for this view, or 0 if the color may vary
18885     */
18886    @ViewDebug.ExportedProperty(category = "drawing")
18887    @ColorInt
18888    public int getSolidColor() {
18889        return 0;
18890    }
18891
18892    /**
18893     * Build a human readable string representation of the specified view flags.
18894     *
18895     * @param flags the view flags to convert to a string
18896     * @return a String representing the supplied flags
18897     */
18898    private static String printFlags(int flags) {
18899        String output = "";
18900        int numFlags = 0;
18901        if ((flags & FOCUSABLE) == FOCUSABLE) {
18902            output += "TAKES_FOCUS";
18903            numFlags++;
18904        }
18905
18906        switch (flags & VISIBILITY_MASK) {
18907        case INVISIBLE:
18908            if (numFlags > 0) {
18909                output += " ";
18910            }
18911            output += "INVISIBLE";
18912            // USELESS HERE numFlags++;
18913            break;
18914        case GONE:
18915            if (numFlags > 0) {
18916                output += " ";
18917            }
18918            output += "GONE";
18919            // USELESS HERE numFlags++;
18920            break;
18921        default:
18922            break;
18923        }
18924        return output;
18925    }
18926
18927    /**
18928     * Build a human readable string representation of the specified private
18929     * view flags.
18930     *
18931     * @param privateFlags the private view flags to convert to a string
18932     * @return a String representing the supplied flags
18933     */
18934    private static String printPrivateFlags(int privateFlags) {
18935        String output = "";
18936        int numFlags = 0;
18937
18938        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
18939            output += "WANTS_FOCUS";
18940            numFlags++;
18941        }
18942
18943        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
18944            if (numFlags > 0) {
18945                output += " ";
18946            }
18947            output += "FOCUSED";
18948            numFlags++;
18949        }
18950
18951        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
18952            if (numFlags > 0) {
18953                output += " ";
18954            }
18955            output += "SELECTED";
18956            numFlags++;
18957        }
18958
18959        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
18960            if (numFlags > 0) {
18961                output += " ";
18962            }
18963            output += "IS_ROOT_NAMESPACE";
18964            numFlags++;
18965        }
18966
18967        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
18968            if (numFlags > 0) {
18969                output += " ";
18970            }
18971            output += "HAS_BOUNDS";
18972            numFlags++;
18973        }
18974
18975        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
18976            if (numFlags > 0) {
18977                output += " ";
18978            }
18979            output += "DRAWN";
18980            // USELESS HERE numFlags++;
18981        }
18982        return output;
18983    }
18984
18985    /**
18986     * <p>Indicates whether or not this view's layout will be requested during
18987     * the next hierarchy layout pass.</p>
18988     *
18989     * @return true if the layout will be forced during next layout pass
18990     */
18991    public boolean isLayoutRequested() {
18992        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18993    }
18994
18995    /**
18996     * Return true if o is a ViewGroup that is laying out using optical bounds.
18997     * @hide
18998     */
18999    public static boolean isLayoutModeOptical(Object o) {
19000        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19001    }
19002
19003    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19004        Insets parentInsets = mParent instanceof View ?
19005                ((View) mParent).getOpticalInsets() : Insets.NONE;
19006        Insets childInsets = getOpticalInsets();
19007        return setFrame(
19008                left   + parentInsets.left - childInsets.left,
19009                top    + parentInsets.top  - childInsets.top,
19010                right  + parentInsets.left + childInsets.right,
19011                bottom + parentInsets.top  + childInsets.bottom);
19012    }
19013
19014    /**
19015     * Assign a size and position to a view and all of its
19016     * descendants
19017     *
19018     * <p>This is the second phase of the layout mechanism.
19019     * (The first is measuring). In this phase, each parent calls
19020     * layout on all of its children to position them.
19021     * This is typically done using the child measurements
19022     * that were stored in the measure pass().</p>
19023     *
19024     * <p>Derived classes should not override this method.
19025     * Derived classes with children should override
19026     * onLayout. In that method, they should
19027     * call layout on each of their children.</p>
19028     *
19029     * @param l Left position, relative to parent
19030     * @param t Top position, relative to parent
19031     * @param r Right position, relative to parent
19032     * @param b Bottom position, relative to parent
19033     */
19034    @SuppressWarnings({"unchecked"})
19035    public void layout(int l, int t, int r, int b) {
19036        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19037            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19038            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19039        }
19040
19041        int oldL = mLeft;
19042        int oldT = mTop;
19043        int oldB = mBottom;
19044        int oldR = mRight;
19045
19046        boolean changed = isLayoutModeOptical(mParent) ?
19047                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19048
19049        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19050            onLayout(changed, l, t, r, b);
19051
19052            if (shouldDrawRoundScrollbar()) {
19053                if(mRoundScrollbarRenderer == null) {
19054                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19055                }
19056            } else {
19057                mRoundScrollbarRenderer = null;
19058            }
19059
19060            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19061
19062            ListenerInfo li = mListenerInfo;
19063            if (li != null && li.mOnLayoutChangeListeners != null) {
19064                ArrayList<OnLayoutChangeListener> listenersCopy =
19065                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19066                int numListeners = listenersCopy.size();
19067                for (int i = 0; i < numListeners; ++i) {
19068                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19069                }
19070            }
19071        }
19072
19073        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19074        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19075    }
19076
19077    /**
19078     * Called from layout when this view should
19079     * assign a size and position to each of its children.
19080     *
19081     * Derived classes with children should override
19082     * this method and call layout on each of
19083     * their children.
19084     * @param changed This is a new size or position for this view
19085     * @param left Left position, relative to parent
19086     * @param top Top position, relative to parent
19087     * @param right Right position, relative to parent
19088     * @param bottom Bottom position, relative to parent
19089     */
19090    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19091    }
19092
19093    /**
19094     * Assign a size and position to this view.
19095     *
19096     * This is called from layout.
19097     *
19098     * @param left Left position, relative to parent
19099     * @param top Top position, relative to parent
19100     * @param right Right position, relative to parent
19101     * @param bottom Bottom position, relative to parent
19102     * @return true if the new size and position are different than the
19103     *         previous ones
19104     * {@hide}
19105     */
19106    protected boolean setFrame(int left, int top, int right, int bottom) {
19107        boolean changed = false;
19108
19109        if (DBG) {
19110            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19111                    + right + "," + bottom + ")");
19112        }
19113
19114        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19115            changed = true;
19116
19117            // Remember our drawn bit
19118            int drawn = mPrivateFlags & PFLAG_DRAWN;
19119
19120            int oldWidth = mRight - mLeft;
19121            int oldHeight = mBottom - mTop;
19122            int newWidth = right - left;
19123            int newHeight = bottom - top;
19124            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19125
19126            // Invalidate our old position
19127            invalidate(sizeChanged);
19128
19129            mLeft = left;
19130            mTop = top;
19131            mRight = right;
19132            mBottom = bottom;
19133            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19134
19135            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19136
19137
19138            if (sizeChanged) {
19139                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19140            }
19141
19142            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19143                // If we are visible, force the DRAWN bit to on so that
19144                // this invalidate will go through (at least to our parent).
19145                // This is because someone may have invalidated this view
19146                // before this call to setFrame came in, thereby clearing
19147                // the DRAWN bit.
19148                mPrivateFlags |= PFLAG_DRAWN;
19149                invalidate(sizeChanged);
19150                // parent display list may need to be recreated based on a change in the bounds
19151                // of any child
19152                invalidateParentCaches();
19153            }
19154
19155            // Reset drawn bit to original value (invalidate turns it off)
19156            mPrivateFlags |= drawn;
19157
19158            mBackgroundSizeChanged = true;
19159            if (mForegroundInfo != null) {
19160                mForegroundInfo.mBoundsChanged = true;
19161            }
19162
19163            notifySubtreeAccessibilityStateChangedIfNeeded();
19164        }
19165        return changed;
19166    }
19167
19168    /**
19169     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19170     * @hide
19171     */
19172    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19173        setFrame(left, top, right, bottom);
19174    }
19175
19176    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19177        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19178        if (mOverlay != null) {
19179            mOverlay.getOverlayView().setRight(newWidth);
19180            mOverlay.getOverlayView().setBottom(newHeight);
19181        }
19182        rebuildOutline();
19183    }
19184
19185    /**
19186     * Finalize inflating a view from XML.  This is called as the last phase
19187     * of inflation, after all child views have been added.
19188     *
19189     * <p>Even if the subclass overrides onFinishInflate, they should always be
19190     * sure to call the super method, so that we get called.
19191     */
19192    @CallSuper
19193    protected void onFinishInflate() {
19194    }
19195
19196    /**
19197     * Returns the resources associated with this view.
19198     *
19199     * @return Resources object.
19200     */
19201    public Resources getResources() {
19202        return mResources;
19203    }
19204
19205    /**
19206     * Invalidates the specified Drawable.
19207     *
19208     * @param drawable the drawable to invalidate
19209     */
19210    @Override
19211    public void invalidateDrawable(@NonNull Drawable drawable) {
19212        if (verifyDrawable(drawable)) {
19213            final Rect dirty = drawable.getDirtyBounds();
19214            final int scrollX = mScrollX;
19215            final int scrollY = mScrollY;
19216
19217            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19218                    dirty.right + scrollX, dirty.bottom + scrollY);
19219            rebuildOutline();
19220        }
19221    }
19222
19223    /**
19224     * Schedules an action on a drawable to occur at a specified time.
19225     *
19226     * @param who the recipient of the action
19227     * @param what the action to run on the drawable
19228     * @param when the time at which the action must occur. Uses the
19229     *        {@link SystemClock#uptimeMillis} timebase.
19230     */
19231    @Override
19232    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19233        if (verifyDrawable(who) && what != null) {
19234            final long delay = when - SystemClock.uptimeMillis();
19235            if (mAttachInfo != null) {
19236                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19237                        Choreographer.CALLBACK_ANIMATION, what, who,
19238                        Choreographer.subtractFrameDelay(delay));
19239            } else {
19240                // Postpone the runnable until we know
19241                // on which thread it needs to run.
19242                getRunQueue().postDelayed(what, delay);
19243            }
19244        }
19245    }
19246
19247    /**
19248     * Cancels a scheduled action on a drawable.
19249     *
19250     * @param who the recipient of the action
19251     * @param what the action to cancel
19252     */
19253    @Override
19254    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19255        if (verifyDrawable(who) && what != null) {
19256            if (mAttachInfo != null) {
19257                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19258                        Choreographer.CALLBACK_ANIMATION, what, who);
19259            }
19260            getRunQueue().removeCallbacks(what);
19261        }
19262    }
19263
19264    /**
19265     * Unschedule any events associated with the given Drawable.  This can be
19266     * used when selecting a new Drawable into a view, so that the previous
19267     * one is completely unscheduled.
19268     *
19269     * @param who The Drawable to unschedule.
19270     *
19271     * @see #drawableStateChanged
19272     */
19273    public void unscheduleDrawable(Drawable who) {
19274        if (mAttachInfo != null && who != null) {
19275            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19276                    Choreographer.CALLBACK_ANIMATION, null, who);
19277        }
19278    }
19279
19280    /**
19281     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19282     * that the View directionality can and will be resolved before its Drawables.
19283     *
19284     * Will call {@link View#onResolveDrawables} when resolution is done.
19285     *
19286     * @hide
19287     */
19288    protected void resolveDrawables() {
19289        // Drawables resolution may need to happen before resolving the layout direction (which is
19290        // done only during the measure() call).
19291        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19292        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19293        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19294        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19295        // direction to be resolved as its resolved value will be the same as its raw value.
19296        if (!isLayoutDirectionResolved() &&
19297                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19298            return;
19299        }
19300
19301        final int layoutDirection = isLayoutDirectionResolved() ?
19302                getLayoutDirection() : getRawLayoutDirection();
19303
19304        if (mBackground != null) {
19305            mBackground.setLayoutDirection(layoutDirection);
19306        }
19307        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19308            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19309        }
19310        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19311        onResolveDrawables(layoutDirection);
19312    }
19313
19314    boolean areDrawablesResolved() {
19315        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19316    }
19317
19318    /**
19319     * Called when layout direction has been resolved.
19320     *
19321     * The default implementation does nothing.
19322     *
19323     * @param layoutDirection The resolved layout direction.
19324     *
19325     * @see #LAYOUT_DIRECTION_LTR
19326     * @see #LAYOUT_DIRECTION_RTL
19327     *
19328     * @hide
19329     */
19330    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19331    }
19332
19333    /**
19334     * @hide
19335     */
19336    protected void resetResolvedDrawables() {
19337        resetResolvedDrawablesInternal();
19338    }
19339
19340    void resetResolvedDrawablesInternal() {
19341        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19342    }
19343
19344    /**
19345     * If your view subclass is displaying its own Drawable objects, it should
19346     * override this function and return true for any Drawable it is
19347     * displaying.  This allows animations for those drawables to be
19348     * scheduled.
19349     *
19350     * <p>Be sure to call through to the super class when overriding this
19351     * function.
19352     *
19353     * @param who The Drawable to verify.  Return true if it is one you are
19354     *            displaying, else return the result of calling through to the
19355     *            super class.
19356     *
19357     * @return boolean If true than the Drawable is being displayed in the
19358     *         view; else false and it is not allowed to animate.
19359     *
19360     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19361     * @see #drawableStateChanged()
19362     */
19363    @CallSuper
19364    protected boolean verifyDrawable(@NonNull Drawable who) {
19365        // Avoid verifying the scroll bar drawable so that we don't end up in
19366        // an invalidation loop. This effectively prevents the scroll bar
19367        // drawable from triggering invalidations and scheduling runnables.
19368        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
19369    }
19370
19371    /**
19372     * This function is called whenever the state of the view changes in such
19373     * a way that it impacts the state of drawables being shown.
19374     * <p>
19375     * If the View has a StateListAnimator, it will also be called to run necessary state
19376     * change animations.
19377     * <p>
19378     * Be sure to call through to the superclass when overriding this function.
19379     *
19380     * @see Drawable#setState(int[])
19381     */
19382    @CallSuper
19383    protected void drawableStateChanged() {
19384        final int[] state = getDrawableState();
19385        boolean changed = false;
19386
19387        final Drawable bg = mBackground;
19388        if (bg != null && bg.isStateful()) {
19389            changed |= bg.setState(state);
19390        }
19391
19392        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19393        if (fg != null && fg.isStateful()) {
19394            changed |= fg.setState(state);
19395        }
19396
19397        if (mScrollCache != null) {
19398            final Drawable scrollBar = mScrollCache.scrollBar;
19399            if (scrollBar != null && scrollBar.isStateful()) {
19400                changed |= scrollBar.setState(state)
19401                        && mScrollCache.state != ScrollabilityCache.OFF;
19402            }
19403        }
19404
19405        if (mStateListAnimator != null) {
19406            mStateListAnimator.setState(state);
19407        }
19408
19409        if (changed) {
19410            invalidate();
19411        }
19412    }
19413
19414    /**
19415     * This function is called whenever the view hotspot changes and needs to
19416     * be propagated to drawables or child views managed by the view.
19417     * <p>
19418     * Dispatching to child views is handled by
19419     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19420     * <p>
19421     * Be sure to call through to the superclass when overriding this function.
19422     *
19423     * @param x hotspot x coordinate
19424     * @param y hotspot y coordinate
19425     */
19426    @CallSuper
19427    public void drawableHotspotChanged(float x, float y) {
19428        if (mBackground != null) {
19429            mBackground.setHotspot(x, y);
19430        }
19431        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19432            mForegroundInfo.mDrawable.setHotspot(x, y);
19433        }
19434
19435        dispatchDrawableHotspotChanged(x, y);
19436    }
19437
19438    /**
19439     * Dispatches drawableHotspotChanged to all of this View's children.
19440     *
19441     * @param x hotspot x coordinate
19442     * @param y hotspot y coordinate
19443     * @see #drawableHotspotChanged(float, float)
19444     */
19445    public void dispatchDrawableHotspotChanged(float x, float y) {
19446    }
19447
19448    /**
19449     * Call this to force a view to update its drawable state. This will cause
19450     * drawableStateChanged to be called on this view. Views that are interested
19451     * in the new state should call getDrawableState.
19452     *
19453     * @see #drawableStateChanged
19454     * @see #getDrawableState
19455     */
19456    public void refreshDrawableState() {
19457        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19458        drawableStateChanged();
19459
19460        ViewParent parent = mParent;
19461        if (parent != null) {
19462            parent.childDrawableStateChanged(this);
19463        }
19464    }
19465
19466    /**
19467     * Return an array of resource IDs of the drawable states representing the
19468     * current state of the view.
19469     *
19470     * @return The current drawable state
19471     *
19472     * @see Drawable#setState(int[])
19473     * @see #drawableStateChanged()
19474     * @see #onCreateDrawableState(int)
19475     */
19476    public final int[] getDrawableState() {
19477        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19478            return mDrawableState;
19479        } else {
19480            mDrawableState = onCreateDrawableState(0);
19481            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19482            return mDrawableState;
19483        }
19484    }
19485
19486    /**
19487     * Generate the new {@link android.graphics.drawable.Drawable} state for
19488     * this view. This is called by the view
19489     * system when the cached Drawable state is determined to be invalid.  To
19490     * retrieve the current state, you should use {@link #getDrawableState}.
19491     *
19492     * @param extraSpace if non-zero, this is the number of extra entries you
19493     * would like in the returned array in which you can place your own
19494     * states.
19495     *
19496     * @return Returns an array holding the current {@link Drawable} state of
19497     * the view.
19498     *
19499     * @see #mergeDrawableStates(int[], int[])
19500     */
19501    protected int[] onCreateDrawableState(int extraSpace) {
19502        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19503                mParent instanceof View) {
19504            return ((View) mParent).onCreateDrawableState(extraSpace);
19505        }
19506
19507        int[] drawableState;
19508
19509        int privateFlags = mPrivateFlags;
19510
19511        int viewStateIndex = 0;
19512        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19513        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19514        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19515        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19516        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19517        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19518        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19519                ThreadedRenderer.isAvailable()) {
19520            // This is set if HW acceleration is requested, even if the current
19521            // process doesn't allow it.  This is just to allow app preview
19522            // windows to better match their app.
19523            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19524        }
19525        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19526
19527        final int privateFlags2 = mPrivateFlags2;
19528        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19529            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19530        }
19531        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19532            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19533        }
19534
19535        drawableState = StateSet.get(viewStateIndex);
19536
19537        //noinspection ConstantIfStatement
19538        if (false) {
19539            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19540            Log.i("View", toString()
19541                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19542                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19543                    + " fo=" + hasFocus()
19544                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19545                    + " wf=" + hasWindowFocus()
19546                    + ": " + Arrays.toString(drawableState));
19547        }
19548
19549        if (extraSpace == 0) {
19550            return drawableState;
19551        }
19552
19553        final int[] fullState;
19554        if (drawableState != null) {
19555            fullState = new int[drawableState.length + extraSpace];
19556            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19557        } else {
19558            fullState = new int[extraSpace];
19559        }
19560
19561        return fullState;
19562    }
19563
19564    /**
19565     * Merge your own state values in <var>additionalState</var> into the base
19566     * state values <var>baseState</var> that were returned by
19567     * {@link #onCreateDrawableState(int)}.
19568     *
19569     * @param baseState The base state values returned by
19570     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19571     * own additional state values.
19572     *
19573     * @param additionalState The additional state values you would like
19574     * added to <var>baseState</var>; this array is not modified.
19575     *
19576     * @return As a convenience, the <var>baseState</var> array you originally
19577     * passed into the function is returned.
19578     *
19579     * @see #onCreateDrawableState(int)
19580     */
19581    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19582        final int N = baseState.length;
19583        int i = N - 1;
19584        while (i >= 0 && baseState[i] == 0) {
19585            i--;
19586        }
19587        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19588        return baseState;
19589    }
19590
19591    /**
19592     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19593     * on all Drawable objects associated with this view.
19594     * <p>
19595     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19596     * attached to this view.
19597     */
19598    @CallSuper
19599    public void jumpDrawablesToCurrentState() {
19600        if (mBackground != null) {
19601            mBackground.jumpToCurrentState();
19602        }
19603        if (mStateListAnimator != null) {
19604            mStateListAnimator.jumpToCurrentState();
19605        }
19606        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19607            mForegroundInfo.mDrawable.jumpToCurrentState();
19608        }
19609    }
19610
19611    /**
19612     * Sets the background color for this view.
19613     * @param color the color of the background
19614     */
19615    @RemotableViewMethod
19616    public void setBackgroundColor(@ColorInt int color) {
19617        if (mBackground instanceof ColorDrawable) {
19618            ((ColorDrawable) mBackground.mutate()).setColor(color);
19619            computeOpaqueFlags();
19620            mBackgroundResource = 0;
19621        } else {
19622            setBackground(new ColorDrawable(color));
19623        }
19624    }
19625
19626    /**
19627     * Set the background to a given resource. The resource should refer to
19628     * a Drawable object or 0 to remove the background.
19629     * @param resid The identifier of the resource.
19630     *
19631     * @attr ref android.R.styleable#View_background
19632     */
19633    @RemotableViewMethod
19634    public void setBackgroundResource(@DrawableRes int resid) {
19635        if (resid != 0 && resid == mBackgroundResource) {
19636            return;
19637        }
19638
19639        Drawable d = null;
19640        if (resid != 0) {
19641            d = mContext.getDrawable(resid);
19642        }
19643        setBackground(d);
19644
19645        mBackgroundResource = resid;
19646    }
19647
19648    /**
19649     * Set the background to a given Drawable, or remove the background. If the
19650     * background has padding, this View's padding is set to the background's
19651     * padding. However, when a background is removed, this View's padding isn't
19652     * touched. If setting the padding is desired, please use
19653     * {@link #setPadding(int, int, int, int)}.
19654     *
19655     * @param background The Drawable to use as the background, or null to remove the
19656     *        background
19657     */
19658    public void setBackground(Drawable background) {
19659        //noinspection deprecation
19660        setBackgroundDrawable(background);
19661    }
19662
19663    /**
19664     * @deprecated use {@link #setBackground(Drawable)} instead
19665     */
19666    @Deprecated
19667    public void setBackgroundDrawable(Drawable background) {
19668        computeOpaqueFlags();
19669
19670        if (background == mBackground) {
19671            return;
19672        }
19673
19674        boolean requestLayout = false;
19675
19676        mBackgroundResource = 0;
19677
19678        /*
19679         * Regardless of whether we're setting a new background or not, we want
19680         * to clear the previous drawable. setVisible first while we still have the callback set.
19681         */
19682        if (mBackground != null) {
19683            if (isAttachedToWindow()) {
19684                mBackground.setVisible(false, false);
19685            }
19686            mBackground.setCallback(null);
19687            unscheduleDrawable(mBackground);
19688        }
19689
19690        if (background != null) {
19691            Rect padding = sThreadLocal.get();
19692            if (padding == null) {
19693                padding = new Rect();
19694                sThreadLocal.set(padding);
19695            }
19696            resetResolvedDrawablesInternal();
19697            background.setLayoutDirection(getLayoutDirection());
19698            if (background.getPadding(padding)) {
19699                resetResolvedPaddingInternal();
19700                switch (background.getLayoutDirection()) {
19701                    case LAYOUT_DIRECTION_RTL:
19702                        mUserPaddingLeftInitial = padding.right;
19703                        mUserPaddingRightInitial = padding.left;
19704                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19705                        break;
19706                    case LAYOUT_DIRECTION_LTR:
19707                    default:
19708                        mUserPaddingLeftInitial = padding.left;
19709                        mUserPaddingRightInitial = padding.right;
19710                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19711                }
19712                mLeftPaddingDefined = false;
19713                mRightPaddingDefined = false;
19714            }
19715
19716            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19717            // if it has a different minimum size, we should layout again
19718            if (mBackground == null
19719                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19720                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19721                requestLayout = true;
19722            }
19723
19724            // Set mBackground before we set this as the callback and start making other
19725            // background drawable state change calls. In particular, the setVisible call below
19726            // can result in drawables attempting to start animations or otherwise invalidate,
19727            // which requires the view set as the callback (us) to recognize the drawable as
19728            // belonging to it as per verifyDrawable.
19729            mBackground = background;
19730            if (background.isStateful()) {
19731                background.setState(getDrawableState());
19732            }
19733            if (isAttachedToWindow()) {
19734                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19735            }
19736
19737            applyBackgroundTint();
19738
19739            // Set callback last, since the view may still be initializing.
19740            background.setCallback(this);
19741
19742            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19743                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19744                requestLayout = true;
19745            }
19746        } else {
19747            /* Remove the background */
19748            mBackground = null;
19749            if ((mViewFlags & WILL_NOT_DRAW) != 0
19750                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19751                mPrivateFlags |= PFLAG_SKIP_DRAW;
19752            }
19753
19754            /*
19755             * When the background is set, we try to apply its padding to this
19756             * View. When the background is removed, we don't touch this View's
19757             * padding. This is noted in the Javadocs. Hence, we don't need to
19758             * requestLayout(), the invalidate() below is sufficient.
19759             */
19760
19761            // The old background's minimum size could have affected this
19762            // View's layout, so let's requestLayout
19763            requestLayout = true;
19764        }
19765
19766        computeOpaqueFlags();
19767
19768        if (requestLayout) {
19769            requestLayout();
19770        }
19771
19772        mBackgroundSizeChanged = true;
19773        invalidate(true);
19774        invalidateOutline();
19775    }
19776
19777    /**
19778     * Gets the background drawable
19779     *
19780     * @return The drawable used as the background for this view, if any.
19781     *
19782     * @see #setBackground(Drawable)
19783     *
19784     * @attr ref android.R.styleable#View_background
19785     */
19786    public Drawable getBackground() {
19787        return mBackground;
19788    }
19789
19790    /**
19791     * Applies a tint to the background drawable. Does not modify the current tint
19792     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19793     * <p>
19794     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
19795     * mutate the drawable and apply the specified tint and tint mode using
19796     * {@link Drawable#setTintList(ColorStateList)}.
19797     *
19798     * @param tint the tint to apply, may be {@code null} to clear tint
19799     *
19800     * @attr ref android.R.styleable#View_backgroundTint
19801     * @see #getBackgroundTintList()
19802     * @see Drawable#setTintList(ColorStateList)
19803     */
19804    public void setBackgroundTintList(@Nullable ColorStateList tint) {
19805        if (mBackgroundTint == null) {
19806            mBackgroundTint = new TintInfo();
19807        }
19808        mBackgroundTint.mTintList = tint;
19809        mBackgroundTint.mHasTintList = true;
19810
19811        applyBackgroundTint();
19812    }
19813
19814    /**
19815     * Return the tint applied to the background drawable, if specified.
19816     *
19817     * @return the tint applied to the background drawable
19818     * @attr ref android.R.styleable#View_backgroundTint
19819     * @see #setBackgroundTintList(ColorStateList)
19820     */
19821    @Nullable
19822    public ColorStateList getBackgroundTintList() {
19823        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
19824    }
19825
19826    /**
19827     * Specifies the blending mode used to apply the tint specified by
19828     * {@link #setBackgroundTintList(ColorStateList)}} to the background
19829     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19830     *
19831     * @param tintMode the blending mode used to apply the tint, may be
19832     *                 {@code null} to clear tint
19833     * @attr ref android.R.styleable#View_backgroundTintMode
19834     * @see #getBackgroundTintMode()
19835     * @see Drawable#setTintMode(PorterDuff.Mode)
19836     */
19837    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19838        if (mBackgroundTint == null) {
19839            mBackgroundTint = new TintInfo();
19840        }
19841        mBackgroundTint.mTintMode = tintMode;
19842        mBackgroundTint.mHasTintMode = true;
19843
19844        applyBackgroundTint();
19845    }
19846
19847    /**
19848     * Return the blending mode used to apply the tint to the background
19849     * drawable, if specified.
19850     *
19851     * @return the blending mode used to apply the tint to the background
19852     *         drawable
19853     * @attr ref android.R.styleable#View_backgroundTintMode
19854     * @see #setBackgroundTintMode(PorterDuff.Mode)
19855     */
19856    @Nullable
19857    public PorterDuff.Mode getBackgroundTintMode() {
19858        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
19859    }
19860
19861    private void applyBackgroundTint() {
19862        if (mBackground != null && mBackgroundTint != null) {
19863            final TintInfo tintInfo = mBackgroundTint;
19864            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19865                mBackground = mBackground.mutate();
19866
19867                if (tintInfo.mHasTintList) {
19868                    mBackground.setTintList(tintInfo.mTintList);
19869                }
19870
19871                if (tintInfo.mHasTintMode) {
19872                    mBackground.setTintMode(tintInfo.mTintMode);
19873                }
19874
19875                // The drawable (or one of its children) may not have been
19876                // stateful before applying the tint, so let's try again.
19877                if (mBackground.isStateful()) {
19878                    mBackground.setState(getDrawableState());
19879                }
19880            }
19881        }
19882    }
19883
19884    /**
19885     * Returns the drawable used as the foreground of this View. The
19886     * foreground drawable, if non-null, is always drawn on top of the view's content.
19887     *
19888     * @return a Drawable or null if no foreground was set
19889     *
19890     * @see #onDrawForeground(Canvas)
19891     */
19892    public Drawable getForeground() {
19893        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19894    }
19895
19896    /**
19897     * Supply a Drawable that is to be rendered on top of all of the content in the view.
19898     *
19899     * @param foreground the Drawable to be drawn on top of the children
19900     *
19901     * @attr ref android.R.styleable#View_foreground
19902     */
19903    public void setForeground(Drawable foreground) {
19904        if (mForegroundInfo == null) {
19905            if (foreground == null) {
19906                // Nothing to do.
19907                return;
19908            }
19909            mForegroundInfo = new ForegroundInfo();
19910        }
19911
19912        if (foreground == mForegroundInfo.mDrawable) {
19913            // Nothing to do
19914            return;
19915        }
19916
19917        if (mForegroundInfo.mDrawable != null) {
19918            if (isAttachedToWindow()) {
19919                mForegroundInfo.mDrawable.setVisible(false, false);
19920            }
19921            mForegroundInfo.mDrawable.setCallback(null);
19922            unscheduleDrawable(mForegroundInfo.mDrawable);
19923        }
19924
19925        mForegroundInfo.mDrawable = foreground;
19926        mForegroundInfo.mBoundsChanged = true;
19927        if (foreground != null) {
19928            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19929                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19930            }
19931            foreground.setLayoutDirection(getLayoutDirection());
19932            if (foreground.isStateful()) {
19933                foreground.setState(getDrawableState());
19934            }
19935            applyForegroundTint();
19936            if (isAttachedToWindow()) {
19937                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19938            }
19939            // Set callback last, since the view may still be initializing.
19940            foreground.setCallback(this);
19941        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
19942            mPrivateFlags |= PFLAG_SKIP_DRAW;
19943        }
19944        requestLayout();
19945        invalidate();
19946    }
19947
19948    /**
19949     * Magic bit used to support features of framework-internal window decor implementation details.
19950     * This used to live exclusively in FrameLayout.
19951     *
19952     * @return true if the foreground should draw inside the padding region or false
19953     *         if it should draw inset by the view's padding
19954     * @hide internal use only; only used by FrameLayout and internal screen layouts.
19955     */
19956    public boolean isForegroundInsidePadding() {
19957        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
19958    }
19959
19960    /**
19961     * Describes how the foreground is positioned.
19962     *
19963     * @return foreground gravity.
19964     *
19965     * @see #setForegroundGravity(int)
19966     *
19967     * @attr ref android.R.styleable#View_foregroundGravity
19968     */
19969    public int getForegroundGravity() {
19970        return mForegroundInfo != null ? mForegroundInfo.mGravity
19971                : Gravity.START | Gravity.TOP;
19972    }
19973
19974    /**
19975     * Describes how the foreground is positioned. Defaults to START and TOP.
19976     *
19977     * @param gravity see {@link android.view.Gravity}
19978     *
19979     * @see #getForegroundGravity()
19980     *
19981     * @attr ref android.R.styleable#View_foregroundGravity
19982     */
19983    public void setForegroundGravity(int gravity) {
19984        if (mForegroundInfo == null) {
19985            mForegroundInfo = new ForegroundInfo();
19986        }
19987
19988        if (mForegroundInfo.mGravity != gravity) {
19989            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
19990                gravity |= Gravity.START;
19991            }
19992
19993            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
19994                gravity |= Gravity.TOP;
19995            }
19996
19997            mForegroundInfo.mGravity = gravity;
19998            requestLayout();
19999        }
20000    }
20001
20002    /**
20003     * Applies a tint to the foreground drawable. Does not modify the current tint
20004     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20005     * <p>
20006     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20007     * mutate the drawable and apply the specified tint and tint mode using
20008     * {@link Drawable#setTintList(ColorStateList)}.
20009     *
20010     * @param tint the tint to apply, may be {@code null} to clear tint
20011     *
20012     * @attr ref android.R.styleable#View_foregroundTint
20013     * @see #getForegroundTintList()
20014     * @see Drawable#setTintList(ColorStateList)
20015     */
20016    public void setForegroundTintList(@Nullable ColorStateList tint) {
20017        if (mForegroundInfo == null) {
20018            mForegroundInfo = new ForegroundInfo();
20019        }
20020        if (mForegroundInfo.mTintInfo == null) {
20021            mForegroundInfo.mTintInfo = new TintInfo();
20022        }
20023        mForegroundInfo.mTintInfo.mTintList = tint;
20024        mForegroundInfo.mTintInfo.mHasTintList = true;
20025
20026        applyForegroundTint();
20027    }
20028
20029    /**
20030     * Return the tint applied to the foreground drawable, if specified.
20031     *
20032     * @return the tint applied to the foreground drawable
20033     * @attr ref android.R.styleable#View_foregroundTint
20034     * @see #setForegroundTintList(ColorStateList)
20035     */
20036    @Nullable
20037    public ColorStateList getForegroundTintList() {
20038        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20039                ? mForegroundInfo.mTintInfo.mTintList : null;
20040    }
20041
20042    /**
20043     * Specifies the blending mode used to apply the tint specified by
20044     * {@link #setForegroundTintList(ColorStateList)}} to the background
20045     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20046     *
20047     * @param tintMode the blending mode used to apply the tint, may be
20048     *                 {@code null} to clear tint
20049     * @attr ref android.R.styleable#View_foregroundTintMode
20050     * @see #getForegroundTintMode()
20051     * @see Drawable#setTintMode(PorterDuff.Mode)
20052     */
20053    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20054        if (mForegroundInfo == null) {
20055            mForegroundInfo = new ForegroundInfo();
20056        }
20057        if (mForegroundInfo.mTintInfo == null) {
20058            mForegroundInfo.mTintInfo = new TintInfo();
20059        }
20060        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20061        mForegroundInfo.mTintInfo.mHasTintMode = true;
20062
20063        applyForegroundTint();
20064    }
20065
20066    /**
20067     * Return the blending mode used to apply the tint to the foreground
20068     * drawable, if specified.
20069     *
20070     * @return the blending mode used to apply the tint to the foreground
20071     *         drawable
20072     * @attr ref android.R.styleable#View_foregroundTintMode
20073     * @see #setForegroundTintMode(PorterDuff.Mode)
20074     */
20075    @Nullable
20076    public PorterDuff.Mode getForegroundTintMode() {
20077        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20078                ? mForegroundInfo.mTintInfo.mTintMode : null;
20079    }
20080
20081    private void applyForegroundTint() {
20082        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20083                && mForegroundInfo.mTintInfo != null) {
20084            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20085            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20086                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20087
20088                if (tintInfo.mHasTintList) {
20089                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20090                }
20091
20092                if (tintInfo.mHasTintMode) {
20093                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20094                }
20095
20096                // The drawable (or one of its children) may not have been
20097                // stateful before applying the tint, so let's try again.
20098                if (mForegroundInfo.mDrawable.isStateful()) {
20099                    mForegroundInfo.mDrawable.setState(getDrawableState());
20100                }
20101            }
20102        }
20103    }
20104
20105    /**
20106     * Draw any foreground content for this view.
20107     *
20108     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20109     * drawable or other view-specific decorations. The foreground is drawn on top of the
20110     * primary view content.</p>
20111     *
20112     * @param canvas canvas to draw into
20113     */
20114    public void onDrawForeground(Canvas canvas) {
20115        onDrawScrollIndicators(canvas);
20116        onDrawScrollBars(canvas);
20117
20118        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20119        if (foreground != null) {
20120            if (mForegroundInfo.mBoundsChanged) {
20121                mForegroundInfo.mBoundsChanged = false;
20122                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20123                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20124
20125                if (mForegroundInfo.mInsidePadding) {
20126                    selfBounds.set(0, 0, getWidth(), getHeight());
20127                } else {
20128                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20129                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20130                }
20131
20132                final int ld = getLayoutDirection();
20133                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20134                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20135                foreground.setBounds(overlayBounds);
20136            }
20137
20138            foreground.draw(canvas);
20139        }
20140    }
20141
20142    /**
20143     * Sets the padding. The view may add on the space required to display
20144     * the scrollbars, depending on the style and visibility of the scrollbars.
20145     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20146     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20147     * from the values set in this call.
20148     *
20149     * @attr ref android.R.styleable#View_padding
20150     * @attr ref android.R.styleable#View_paddingBottom
20151     * @attr ref android.R.styleable#View_paddingLeft
20152     * @attr ref android.R.styleable#View_paddingRight
20153     * @attr ref android.R.styleable#View_paddingTop
20154     * @param left the left padding in pixels
20155     * @param top the top padding in pixels
20156     * @param right the right padding in pixels
20157     * @param bottom the bottom padding in pixels
20158     */
20159    public void setPadding(int left, int top, int right, int bottom) {
20160        resetResolvedPaddingInternal();
20161
20162        mUserPaddingStart = UNDEFINED_PADDING;
20163        mUserPaddingEnd = UNDEFINED_PADDING;
20164
20165        mUserPaddingLeftInitial = left;
20166        mUserPaddingRightInitial = right;
20167
20168        mLeftPaddingDefined = true;
20169        mRightPaddingDefined = true;
20170
20171        internalSetPadding(left, top, right, bottom);
20172    }
20173
20174    /**
20175     * @hide
20176     */
20177    protected void internalSetPadding(int left, int top, int right, int bottom) {
20178        mUserPaddingLeft = left;
20179        mUserPaddingRight = right;
20180        mUserPaddingBottom = bottom;
20181
20182        final int viewFlags = mViewFlags;
20183        boolean changed = false;
20184
20185        // Common case is there are no scroll bars.
20186        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20187            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20188                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20189                        ? 0 : getVerticalScrollbarWidth();
20190                switch (mVerticalScrollbarPosition) {
20191                    case SCROLLBAR_POSITION_DEFAULT:
20192                        if (isLayoutRtl()) {
20193                            left += offset;
20194                        } else {
20195                            right += offset;
20196                        }
20197                        break;
20198                    case SCROLLBAR_POSITION_RIGHT:
20199                        right += offset;
20200                        break;
20201                    case SCROLLBAR_POSITION_LEFT:
20202                        left += offset;
20203                        break;
20204                }
20205            }
20206            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20207                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20208                        ? 0 : getHorizontalScrollbarHeight();
20209            }
20210        }
20211
20212        if (mPaddingLeft != left) {
20213            changed = true;
20214            mPaddingLeft = left;
20215        }
20216        if (mPaddingTop != top) {
20217            changed = true;
20218            mPaddingTop = top;
20219        }
20220        if (mPaddingRight != right) {
20221            changed = true;
20222            mPaddingRight = right;
20223        }
20224        if (mPaddingBottom != bottom) {
20225            changed = true;
20226            mPaddingBottom = bottom;
20227        }
20228
20229        if (changed) {
20230            requestLayout();
20231            invalidateOutline();
20232        }
20233    }
20234
20235    /**
20236     * Sets the relative padding. The view may add on the space required to display
20237     * the scrollbars, depending on the style and visibility of the scrollbars.
20238     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20239     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20240     * from the values set in this call.
20241     *
20242     * @attr ref android.R.styleable#View_padding
20243     * @attr ref android.R.styleable#View_paddingBottom
20244     * @attr ref android.R.styleable#View_paddingStart
20245     * @attr ref android.R.styleable#View_paddingEnd
20246     * @attr ref android.R.styleable#View_paddingTop
20247     * @param start the start padding in pixels
20248     * @param top the top padding in pixels
20249     * @param end the end padding in pixels
20250     * @param bottom the bottom padding in pixels
20251     */
20252    public void setPaddingRelative(int start, int top, int end, int bottom) {
20253        resetResolvedPaddingInternal();
20254
20255        mUserPaddingStart = start;
20256        mUserPaddingEnd = end;
20257        mLeftPaddingDefined = true;
20258        mRightPaddingDefined = true;
20259
20260        switch(getLayoutDirection()) {
20261            case LAYOUT_DIRECTION_RTL:
20262                mUserPaddingLeftInitial = end;
20263                mUserPaddingRightInitial = start;
20264                internalSetPadding(end, top, start, bottom);
20265                break;
20266            case LAYOUT_DIRECTION_LTR:
20267            default:
20268                mUserPaddingLeftInitial = start;
20269                mUserPaddingRightInitial = end;
20270                internalSetPadding(start, top, end, bottom);
20271        }
20272    }
20273
20274    /**
20275     * Returns the top padding of this view.
20276     *
20277     * @return the top padding in pixels
20278     */
20279    public int getPaddingTop() {
20280        return mPaddingTop;
20281    }
20282
20283    /**
20284     * Returns the bottom padding of this view. If there are inset and enabled
20285     * scrollbars, this value may include the space required to display the
20286     * scrollbars as well.
20287     *
20288     * @return the bottom padding in pixels
20289     */
20290    public int getPaddingBottom() {
20291        return mPaddingBottom;
20292    }
20293
20294    /**
20295     * Returns the left padding of this view. If there are inset and enabled
20296     * scrollbars, this value may include the space required to display the
20297     * scrollbars as well.
20298     *
20299     * @return the left padding in pixels
20300     */
20301    public int getPaddingLeft() {
20302        if (!isPaddingResolved()) {
20303            resolvePadding();
20304        }
20305        return mPaddingLeft;
20306    }
20307
20308    /**
20309     * Returns the start padding of this view depending on its resolved layout direction.
20310     * If there are inset and enabled scrollbars, this value may include the space
20311     * required to display the scrollbars as well.
20312     *
20313     * @return the start padding in pixels
20314     */
20315    public int getPaddingStart() {
20316        if (!isPaddingResolved()) {
20317            resolvePadding();
20318        }
20319        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20320                mPaddingRight : mPaddingLeft;
20321    }
20322
20323    /**
20324     * Returns the right padding of this view. If there are inset and enabled
20325     * scrollbars, this value may include the space required to display the
20326     * scrollbars as well.
20327     *
20328     * @return the right padding in pixels
20329     */
20330    public int getPaddingRight() {
20331        if (!isPaddingResolved()) {
20332            resolvePadding();
20333        }
20334        return mPaddingRight;
20335    }
20336
20337    /**
20338     * Returns the end padding of this view depending on its resolved layout direction.
20339     * If there are inset and enabled scrollbars, this value may include the space
20340     * required to display the scrollbars as well.
20341     *
20342     * @return the end padding in pixels
20343     */
20344    public int getPaddingEnd() {
20345        if (!isPaddingResolved()) {
20346            resolvePadding();
20347        }
20348        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20349                mPaddingLeft : mPaddingRight;
20350    }
20351
20352    /**
20353     * Return if the padding has been set through relative values
20354     * {@link #setPaddingRelative(int, int, int, int)} or through
20355     * @attr ref android.R.styleable#View_paddingStart or
20356     * @attr ref android.R.styleable#View_paddingEnd
20357     *
20358     * @return true if the padding is relative or false if it is not.
20359     */
20360    public boolean isPaddingRelative() {
20361        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20362    }
20363
20364    Insets computeOpticalInsets() {
20365        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20366    }
20367
20368    /**
20369     * @hide
20370     */
20371    public void resetPaddingToInitialValues() {
20372        if (isRtlCompatibilityMode()) {
20373            mPaddingLeft = mUserPaddingLeftInitial;
20374            mPaddingRight = mUserPaddingRightInitial;
20375            return;
20376        }
20377        if (isLayoutRtl()) {
20378            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20379            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20380        } else {
20381            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20382            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20383        }
20384    }
20385
20386    /**
20387     * @hide
20388     */
20389    public Insets getOpticalInsets() {
20390        if (mLayoutInsets == null) {
20391            mLayoutInsets = computeOpticalInsets();
20392        }
20393        return mLayoutInsets;
20394    }
20395
20396    /**
20397     * Set this view's optical insets.
20398     *
20399     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20400     * property. Views that compute their own optical insets should call it as part of measurement.
20401     * This method does not request layout. If you are setting optical insets outside of
20402     * measure/layout itself you will want to call requestLayout() yourself.
20403     * </p>
20404     * @hide
20405     */
20406    public void setOpticalInsets(Insets insets) {
20407        mLayoutInsets = insets;
20408    }
20409
20410    /**
20411     * Changes the selection state of this view. A view can be selected or not.
20412     * Note that selection is not the same as focus. Views are typically
20413     * selected in the context of an AdapterView like ListView or GridView;
20414     * the selected view is the view that is highlighted.
20415     *
20416     * @param selected true if the view must be selected, false otherwise
20417     */
20418    public void setSelected(boolean selected) {
20419        //noinspection DoubleNegation
20420        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20421            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20422            if (!selected) resetPressedState();
20423            invalidate(true);
20424            refreshDrawableState();
20425            dispatchSetSelected(selected);
20426            if (selected) {
20427                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20428            } else {
20429                notifyViewAccessibilityStateChangedIfNeeded(
20430                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20431            }
20432        }
20433    }
20434
20435    /**
20436     * Dispatch setSelected to all of this View's children.
20437     *
20438     * @see #setSelected(boolean)
20439     *
20440     * @param selected The new selected state
20441     */
20442    protected void dispatchSetSelected(boolean selected) {
20443    }
20444
20445    /**
20446     * Indicates the selection state of this view.
20447     *
20448     * @return true if the view is selected, false otherwise
20449     */
20450    @ViewDebug.ExportedProperty
20451    public boolean isSelected() {
20452        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20453    }
20454
20455    /**
20456     * Changes the activated state of this view. A view can be activated or not.
20457     * Note that activation is not the same as selection.  Selection is
20458     * a transient property, representing the view (hierarchy) the user is
20459     * currently interacting with.  Activation is a longer-term state that the
20460     * user can move views in and out of.  For example, in a list view with
20461     * single or multiple selection enabled, the views in the current selection
20462     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20463     * here.)  The activated state is propagated down to children of the view it
20464     * is set on.
20465     *
20466     * @param activated true if the view must be activated, false otherwise
20467     */
20468    public void setActivated(boolean activated) {
20469        //noinspection DoubleNegation
20470        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20471            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20472            invalidate(true);
20473            refreshDrawableState();
20474            dispatchSetActivated(activated);
20475        }
20476    }
20477
20478    /**
20479     * Dispatch setActivated to all of this View's children.
20480     *
20481     * @see #setActivated(boolean)
20482     *
20483     * @param activated The new activated state
20484     */
20485    protected void dispatchSetActivated(boolean activated) {
20486    }
20487
20488    /**
20489     * Indicates the activation state of this view.
20490     *
20491     * @return true if the view is activated, false otherwise
20492     */
20493    @ViewDebug.ExportedProperty
20494    public boolean isActivated() {
20495        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20496    }
20497
20498    /**
20499     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20500     * observer can be used to get notifications when global events, like
20501     * layout, happen.
20502     *
20503     * The returned ViewTreeObserver observer is not guaranteed to remain
20504     * valid for the lifetime of this View. If the caller of this method keeps
20505     * a long-lived reference to ViewTreeObserver, it should always check for
20506     * the return value of {@link ViewTreeObserver#isAlive()}.
20507     *
20508     * @return The ViewTreeObserver for this view's hierarchy.
20509     */
20510    public ViewTreeObserver getViewTreeObserver() {
20511        if (mAttachInfo != null) {
20512            return mAttachInfo.mTreeObserver;
20513        }
20514        if (mFloatingTreeObserver == null) {
20515            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20516        }
20517        return mFloatingTreeObserver;
20518    }
20519
20520    /**
20521     * <p>Finds the topmost view in the current view hierarchy.</p>
20522     *
20523     * @return the topmost view containing this view
20524     */
20525    public View getRootView() {
20526        if (mAttachInfo != null) {
20527            final View v = mAttachInfo.mRootView;
20528            if (v != null) {
20529                return v;
20530            }
20531        }
20532
20533        View parent = this;
20534
20535        while (parent.mParent != null && parent.mParent instanceof View) {
20536            parent = (View) parent.mParent;
20537        }
20538
20539        return parent;
20540    }
20541
20542    /**
20543     * Transforms a motion event from view-local coordinates to on-screen
20544     * coordinates.
20545     *
20546     * @param ev the view-local motion event
20547     * @return false if the transformation could not be applied
20548     * @hide
20549     */
20550    public boolean toGlobalMotionEvent(MotionEvent ev) {
20551        final AttachInfo info = mAttachInfo;
20552        if (info == null) {
20553            return false;
20554        }
20555
20556        final Matrix m = info.mTmpMatrix;
20557        m.set(Matrix.IDENTITY_MATRIX);
20558        transformMatrixToGlobal(m);
20559        ev.transform(m);
20560        return true;
20561    }
20562
20563    /**
20564     * Transforms a motion event from on-screen coordinates to view-local
20565     * coordinates.
20566     *
20567     * @param ev the on-screen motion event
20568     * @return false if the transformation could not be applied
20569     * @hide
20570     */
20571    public boolean toLocalMotionEvent(MotionEvent ev) {
20572        final AttachInfo info = mAttachInfo;
20573        if (info == null) {
20574            return false;
20575        }
20576
20577        final Matrix m = info.mTmpMatrix;
20578        m.set(Matrix.IDENTITY_MATRIX);
20579        transformMatrixToLocal(m);
20580        ev.transform(m);
20581        return true;
20582    }
20583
20584    /**
20585     * Modifies the input matrix such that it maps view-local coordinates to
20586     * on-screen coordinates.
20587     *
20588     * @param m input matrix to modify
20589     * @hide
20590     */
20591    public void transformMatrixToGlobal(Matrix m) {
20592        final ViewParent parent = mParent;
20593        if (parent instanceof View) {
20594            final View vp = (View) parent;
20595            vp.transformMatrixToGlobal(m);
20596            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20597        } else if (parent instanceof ViewRootImpl) {
20598            final ViewRootImpl vr = (ViewRootImpl) parent;
20599            vr.transformMatrixToGlobal(m);
20600            m.preTranslate(0, -vr.mCurScrollY);
20601        }
20602
20603        m.preTranslate(mLeft, mTop);
20604
20605        if (!hasIdentityMatrix()) {
20606            m.preConcat(getMatrix());
20607        }
20608    }
20609
20610    /**
20611     * Modifies the input matrix such that it maps on-screen coordinates to
20612     * view-local coordinates.
20613     *
20614     * @param m input matrix to modify
20615     * @hide
20616     */
20617    public void transformMatrixToLocal(Matrix m) {
20618        final ViewParent parent = mParent;
20619        if (parent instanceof View) {
20620            final View vp = (View) parent;
20621            vp.transformMatrixToLocal(m);
20622            m.postTranslate(vp.mScrollX, vp.mScrollY);
20623        } else if (parent instanceof ViewRootImpl) {
20624            final ViewRootImpl vr = (ViewRootImpl) parent;
20625            vr.transformMatrixToLocal(m);
20626            m.postTranslate(0, vr.mCurScrollY);
20627        }
20628
20629        m.postTranslate(-mLeft, -mTop);
20630
20631        if (!hasIdentityMatrix()) {
20632            m.postConcat(getInverseMatrix());
20633        }
20634    }
20635
20636    /**
20637     * @hide
20638     */
20639    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20640            @ViewDebug.IntToString(from = 0, to = "x"),
20641            @ViewDebug.IntToString(from = 1, to = "y")
20642    })
20643    public int[] getLocationOnScreen() {
20644        int[] location = new int[2];
20645        getLocationOnScreen(location);
20646        return location;
20647    }
20648
20649    /**
20650     * <p>Computes the coordinates of this view on the screen. The argument
20651     * must be an array of two integers. After the method returns, the array
20652     * contains the x and y location in that order.</p>
20653     *
20654     * @param outLocation an array of two integers in which to hold the coordinates
20655     */
20656    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20657        getLocationInWindow(outLocation);
20658
20659        final AttachInfo info = mAttachInfo;
20660        if (info != null) {
20661            outLocation[0] += info.mWindowLeft;
20662            outLocation[1] += info.mWindowTop;
20663        }
20664    }
20665
20666    /**
20667     * <p>Computes the coordinates of this view in its window. The argument
20668     * must be an array of two integers. After the method returns, the array
20669     * contains the x and y location in that order.</p>
20670     *
20671     * @param outLocation an array of two integers in which to hold the coordinates
20672     */
20673    public void getLocationInWindow(@Size(2) int[] outLocation) {
20674        if (outLocation == null || outLocation.length < 2) {
20675            throw new IllegalArgumentException("outLocation must be an array of two integers");
20676        }
20677
20678        outLocation[0] = 0;
20679        outLocation[1] = 0;
20680
20681        transformFromViewToWindowSpace(outLocation);
20682    }
20683
20684    /** @hide */
20685    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20686        if (inOutLocation == null || inOutLocation.length < 2) {
20687            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20688        }
20689
20690        if (mAttachInfo == null) {
20691            // When the view is not attached to a window, this method does not make sense
20692            inOutLocation[0] = inOutLocation[1] = 0;
20693            return;
20694        }
20695
20696        float position[] = mAttachInfo.mTmpTransformLocation;
20697        position[0] = inOutLocation[0];
20698        position[1] = inOutLocation[1];
20699
20700        if (!hasIdentityMatrix()) {
20701            getMatrix().mapPoints(position);
20702        }
20703
20704        position[0] += mLeft;
20705        position[1] += mTop;
20706
20707        ViewParent viewParent = mParent;
20708        while (viewParent instanceof View) {
20709            final View view = (View) viewParent;
20710
20711            position[0] -= view.mScrollX;
20712            position[1] -= view.mScrollY;
20713
20714            if (!view.hasIdentityMatrix()) {
20715                view.getMatrix().mapPoints(position);
20716            }
20717
20718            position[0] += view.mLeft;
20719            position[1] += view.mTop;
20720
20721            viewParent = view.mParent;
20722         }
20723
20724        if (viewParent instanceof ViewRootImpl) {
20725            // *cough*
20726            final ViewRootImpl vr = (ViewRootImpl) viewParent;
20727            position[1] -= vr.mCurScrollY;
20728        }
20729
20730        inOutLocation[0] = Math.round(position[0]);
20731        inOutLocation[1] = Math.round(position[1]);
20732    }
20733
20734    /**
20735     * @param id the id of the view to be found
20736     * @return the view of the specified id, null if cannot be found
20737     * @hide
20738     */
20739    protected <T extends View> T findViewTraversal(@IdRes int id) {
20740        if (id == mID) {
20741            return (T) this;
20742        }
20743        return null;
20744    }
20745
20746    /**
20747     * @param tag the tag of the view to be found
20748     * @return the view of specified tag, null if cannot be found
20749     * @hide
20750     */
20751    protected <T extends View> T findViewWithTagTraversal(Object tag) {
20752        if (tag != null && tag.equals(mTag)) {
20753            return (T) this;
20754        }
20755        return null;
20756    }
20757
20758    /**
20759     * @param predicate The predicate to evaluate.
20760     * @param childToSkip If not null, ignores this child during the recursive traversal.
20761     * @return The first view that matches the predicate or null.
20762     * @hide
20763     */
20764    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
20765            View childToSkip) {
20766        if (predicate.test(this)) {
20767            return (T) this;
20768        }
20769        return null;
20770    }
20771
20772    /**
20773     * Look for a child view with the given id.  If this view has the given
20774     * id, return this view.
20775     *
20776     * @param id The id to search for.
20777     * @return The view that has the given id in the hierarchy or null
20778     */
20779    @Nullable
20780    public final <T extends View> T findViewById(@IdRes int id) {
20781        if (id < 0) {
20782            return null;
20783        }
20784        return findViewTraversal(id);
20785    }
20786
20787    /**
20788     * Finds a view by its unuque and stable accessibility id.
20789     *
20790     * @param accessibilityId The searched accessibility id.
20791     * @return The found view.
20792     */
20793    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
20794        if (accessibilityId < 0) {
20795            return null;
20796        }
20797        T view = findViewByAccessibilityIdTraversal(accessibilityId);
20798        if (view != null) {
20799            return view.includeForAccessibility() ? view : null;
20800        }
20801        return null;
20802    }
20803
20804    /**
20805     * Performs the traversal to find a view by its unuque and stable accessibility id.
20806     *
20807     * <strong>Note:</strong>This method does not stop at the root namespace
20808     * boundary since the user can touch the screen at an arbitrary location
20809     * potentially crossing the root namespace bounday which will send an
20810     * accessibility event to accessibility services and they should be able
20811     * to obtain the event source. Also accessibility ids are guaranteed to be
20812     * unique in the window.
20813     *
20814     * @param accessibilityId The accessibility id.
20815     * @return The found view.
20816     * @hide
20817     */
20818    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
20819        if (getAccessibilityViewId() == accessibilityId) {
20820            return (T) this;
20821        }
20822        return null;
20823    }
20824
20825    /**
20826     * Look for a child view with the given tag.  If this view has the given
20827     * tag, return this view.
20828     *
20829     * @param tag The tag to search for, using "tag.equals(getTag())".
20830     * @return The View that has the given tag in the hierarchy or null
20831     */
20832    public final <T extends View> T findViewWithTag(Object tag) {
20833        if (tag == null) {
20834            return null;
20835        }
20836        return findViewWithTagTraversal(tag);
20837    }
20838
20839    /**
20840     * Look for a child view that matches the specified predicate.
20841     * If this view matches the predicate, return this view.
20842     *
20843     * @param predicate The predicate to evaluate.
20844     * @return The first view that matches the predicate or null.
20845     * @hide
20846     */
20847    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
20848        return findViewByPredicateTraversal(predicate, null);
20849    }
20850
20851    /**
20852     * Look for a child view that matches the specified predicate,
20853     * starting with the specified view and its descendents and then
20854     * recusively searching the ancestors and siblings of that view
20855     * until this view is reached.
20856     *
20857     * This method is useful in cases where the predicate does not match
20858     * a single unique view (perhaps multiple views use the same id)
20859     * and we are trying to find the view that is "closest" in scope to the
20860     * starting view.
20861     *
20862     * @param start The view to start from.
20863     * @param predicate The predicate to evaluate.
20864     * @return The first view that matches the predicate or null.
20865     * @hide
20866     */
20867    public final <T extends View> T findViewByPredicateInsideOut(
20868            View start, Predicate<View> predicate) {
20869        View childToSkip = null;
20870        for (;;) {
20871            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
20872            if (view != null || start == this) {
20873                return view;
20874            }
20875
20876            ViewParent parent = start.getParent();
20877            if (parent == null || !(parent instanceof View)) {
20878                return null;
20879            }
20880
20881            childToSkip = start;
20882            start = (View) parent;
20883        }
20884    }
20885
20886    /**
20887     * Sets the identifier for this view. The identifier does not have to be
20888     * unique in this view's hierarchy. The identifier should be a positive
20889     * number.
20890     *
20891     * @see #NO_ID
20892     * @see #getId()
20893     * @see #findViewById(int)
20894     *
20895     * @param id a number used to identify the view
20896     *
20897     * @attr ref android.R.styleable#View_id
20898     */
20899    public void setId(@IdRes int id) {
20900        mID = id;
20901        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
20902            mID = generateViewId();
20903        }
20904    }
20905
20906    /**
20907     * {@hide}
20908     *
20909     * @param isRoot true if the view belongs to the root namespace, false
20910     *        otherwise
20911     */
20912    public void setIsRootNamespace(boolean isRoot) {
20913        if (isRoot) {
20914            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
20915        } else {
20916            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
20917        }
20918    }
20919
20920    /**
20921     * {@hide}
20922     *
20923     * @return true if the view belongs to the root namespace, false otherwise
20924     */
20925    public boolean isRootNamespace() {
20926        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
20927    }
20928
20929    /**
20930     * Returns this view's identifier.
20931     *
20932     * @return a positive integer used to identify the view or {@link #NO_ID}
20933     *         if the view has no ID
20934     *
20935     * @see #setId(int)
20936     * @see #findViewById(int)
20937     * @attr ref android.R.styleable#View_id
20938     */
20939    @IdRes
20940    @ViewDebug.CapturedViewProperty
20941    public int getId() {
20942        return mID;
20943    }
20944
20945    /**
20946     * Returns this view's tag.
20947     *
20948     * @return the Object stored in this view as a tag, or {@code null} if not
20949     *         set
20950     *
20951     * @see #setTag(Object)
20952     * @see #getTag(int)
20953     */
20954    @ViewDebug.ExportedProperty
20955    public Object getTag() {
20956        return mTag;
20957    }
20958
20959    /**
20960     * Sets the tag associated with this view. A tag can be used to mark
20961     * a view in its hierarchy and does not have to be unique within the
20962     * hierarchy. Tags can also be used to store data within a view without
20963     * resorting to another data structure.
20964     *
20965     * @param tag an Object to tag the view with
20966     *
20967     * @see #getTag()
20968     * @see #setTag(int, Object)
20969     */
20970    public void setTag(final Object tag) {
20971        mTag = tag;
20972    }
20973
20974    /**
20975     * Returns the tag associated with this view and the specified key.
20976     *
20977     * @param key The key identifying the tag
20978     *
20979     * @return the Object stored in this view as a tag, or {@code null} if not
20980     *         set
20981     *
20982     * @see #setTag(int, Object)
20983     * @see #getTag()
20984     */
20985    public Object getTag(int key) {
20986        if (mKeyedTags != null) return mKeyedTags.get(key);
20987        return null;
20988    }
20989
20990    /**
20991     * Sets a tag associated with this view and a key. A tag can be used
20992     * to mark a view in its hierarchy and does not have to be unique within
20993     * the hierarchy. Tags can also be used to store data within a view
20994     * without resorting to another data structure.
20995     *
20996     * The specified key should be an id declared in the resources of the
20997     * application to ensure it is unique (see the <a
20998     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
20999     * Keys identified as belonging to
21000     * the Android framework or not associated with any package will cause
21001     * an {@link IllegalArgumentException} to be thrown.
21002     *
21003     * @param key The key identifying the tag
21004     * @param tag An Object to tag the view with
21005     *
21006     * @throws IllegalArgumentException If they specified key is not valid
21007     *
21008     * @see #setTag(Object)
21009     * @see #getTag(int)
21010     */
21011    public void setTag(int key, final Object tag) {
21012        // If the package id is 0x00 or 0x01, it's either an undefined package
21013        // or a framework id
21014        if ((key >>> 24) < 2) {
21015            throw new IllegalArgumentException("The key must be an application-specific "
21016                    + "resource id.");
21017        }
21018
21019        setKeyedTag(key, tag);
21020    }
21021
21022    /**
21023     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21024     * framework id.
21025     *
21026     * @hide
21027     */
21028    public void setTagInternal(int key, Object tag) {
21029        if ((key >>> 24) != 0x1) {
21030            throw new IllegalArgumentException("The key must be a framework-specific "
21031                    + "resource id.");
21032        }
21033
21034        setKeyedTag(key, tag);
21035    }
21036
21037    private void setKeyedTag(int key, Object tag) {
21038        if (mKeyedTags == null) {
21039            mKeyedTags = new SparseArray<Object>(2);
21040        }
21041
21042        mKeyedTags.put(key, tag);
21043    }
21044
21045    /**
21046     * Prints information about this view in the log output, with the tag
21047     * {@link #VIEW_LOG_TAG}.
21048     *
21049     * @hide
21050     */
21051    public void debug() {
21052        debug(0);
21053    }
21054
21055    /**
21056     * Prints information about this view in the log output, with the tag
21057     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21058     * indentation defined by the <code>depth</code>.
21059     *
21060     * @param depth the indentation level
21061     *
21062     * @hide
21063     */
21064    protected void debug(int depth) {
21065        String output = debugIndent(depth - 1);
21066
21067        output += "+ " + this;
21068        int id = getId();
21069        if (id != -1) {
21070            output += " (id=" + id + ")";
21071        }
21072        Object tag = getTag();
21073        if (tag != null) {
21074            output += " (tag=" + tag + ")";
21075        }
21076        Log.d(VIEW_LOG_TAG, output);
21077
21078        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21079            output = debugIndent(depth) + " FOCUSED";
21080            Log.d(VIEW_LOG_TAG, output);
21081        }
21082
21083        output = debugIndent(depth);
21084        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21085                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21086                + "} ";
21087        Log.d(VIEW_LOG_TAG, output);
21088
21089        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21090                || mPaddingBottom != 0) {
21091            output = debugIndent(depth);
21092            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21093                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21094            Log.d(VIEW_LOG_TAG, output);
21095        }
21096
21097        output = debugIndent(depth);
21098        output += "mMeasureWidth=" + mMeasuredWidth +
21099                " mMeasureHeight=" + mMeasuredHeight;
21100        Log.d(VIEW_LOG_TAG, output);
21101
21102        output = debugIndent(depth);
21103        if (mLayoutParams == null) {
21104            output += "BAD! no layout params";
21105        } else {
21106            output = mLayoutParams.debug(output);
21107        }
21108        Log.d(VIEW_LOG_TAG, output);
21109
21110        output = debugIndent(depth);
21111        output += "flags={";
21112        output += View.printFlags(mViewFlags);
21113        output += "}";
21114        Log.d(VIEW_LOG_TAG, output);
21115
21116        output = debugIndent(depth);
21117        output += "privateFlags={";
21118        output += View.printPrivateFlags(mPrivateFlags);
21119        output += "}";
21120        Log.d(VIEW_LOG_TAG, output);
21121    }
21122
21123    /**
21124     * Creates a string of whitespaces used for indentation.
21125     *
21126     * @param depth the indentation level
21127     * @return a String containing (depth * 2 + 3) * 2 white spaces
21128     *
21129     * @hide
21130     */
21131    protected static String debugIndent(int depth) {
21132        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21133        for (int i = 0; i < (depth * 2) + 3; i++) {
21134            spaces.append(' ').append(' ');
21135        }
21136        return spaces.toString();
21137    }
21138
21139    /**
21140     * <p>Return the offset of the widget's text baseline from the widget's top
21141     * boundary. If this widget does not support baseline alignment, this
21142     * method returns -1. </p>
21143     *
21144     * @return the offset of the baseline within the widget's bounds or -1
21145     *         if baseline alignment is not supported
21146     */
21147    @ViewDebug.ExportedProperty(category = "layout")
21148    public int getBaseline() {
21149        return -1;
21150    }
21151
21152    /**
21153     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21154     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21155     * a layout pass.
21156     *
21157     * @return whether the view hierarchy is currently undergoing a layout pass
21158     */
21159    public boolean isInLayout() {
21160        ViewRootImpl viewRoot = getViewRootImpl();
21161        return (viewRoot != null && viewRoot.isInLayout());
21162    }
21163
21164    /**
21165     * Call this when something has changed which has invalidated the
21166     * layout of this view. This will schedule a layout pass of the view
21167     * tree. This should not be called while the view hierarchy is currently in a layout
21168     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21169     * end of the current layout pass (and then layout will run again) or after the current
21170     * frame is drawn and the next layout occurs.
21171     *
21172     * <p>Subclasses which override this method should call the superclass method to
21173     * handle possible request-during-layout errors correctly.</p>
21174     */
21175    @CallSuper
21176    public void requestLayout() {
21177        if (mMeasureCache != null) mMeasureCache.clear();
21178
21179        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21180            // Only trigger request-during-layout logic if this is the view requesting it,
21181            // not the views in its parent hierarchy
21182            ViewRootImpl viewRoot = getViewRootImpl();
21183            if (viewRoot != null && viewRoot.isInLayout()) {
21184                if (!viewRoot.requestLayoutDuringLayout(this)) {
21185                    return;
21186                }
21187            }
21188            mAttachInfo.mViewRequestingLayout = this;
21189        }
21190
21191        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21192        mPrivateFlags |= PFLAG_INVALIDATED;
21193
21194        if (mParent != null && !mParent.isLayoutRequested()) {
21195            mParent.requestLayout();
21196        }
21197        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21198            mAttachInfo.mViewRequestingLayout = null;
21199        }
21200    }
21201
21202    /**
21203     * Forces this view to be laid out during the next layout pass.
21204     * This method does not call requestLayout() or forceLayout()
21205     * on the parent.
21206     */
21207    public void forceLayout() {
21208        if (mMeasureCache != null) mMeasureCache.clear();
21209
21210        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21211        mPrivateFlags |= PFLAG_INVALIDATED;
21212    }
21213
21214    /**
21215     * <p>
21216     * This is called to find out how big a view should be. The parent
21217     * supplies constraint information in the width and height parameters.
21218     * </p>
21219     *
21220     * <p>
21221     * The actual measurement work of a view is performed in
21222     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21223     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21224     * </p>
21225     *
21226     *
21227     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21228     *        parent
21229     * @param heightMeasureSpec Vertical space requirements as imposed by the
21230     *        parent
21231     *
21232     * @see #onMeasure(int, int)
21233     */
21234    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21235        boolean optical = isLayoutModeOptical(this);
21236        if (optical != isLayoutModeOptical(mParent)) {
21237            Insets insets = getOpticalInsets();
21238            int oWidth  = insets.left + insets.right;
21239            int oHeight = insets.top  + insets.bottom;
21240            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21241            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21242        }
21243
21244        // Suppress sign extension for the low bytes
21245        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21246        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21247
21248        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21249
21250        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21251        // already measured as the correct size. In API 23 and below, this
21252        // extra pass is required to make LinearLayout re-distribute weight.
21253        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21254                || heightMeasureSpec != mOldHeightMeasureSpec;
21255        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21256                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21257        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21258                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21259        final boolean needsLayout = specChanged
21260                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21261
21262        if (forceLayout || needsLayout) {
21263            // first clears the measured dimension flag
21264            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21265
21266            resolveRtlPropertiesIfNeeded();
21267
21268            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21269            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21270                // measure ourselves, this should set the measured dimension flag back
21271                onMeasure(widthMeasureSpec, heightMeasureSpec);
21272                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21273            } else {
21274                long value = mMeasureCache.valueAt(cacheIndex);
21275                // Casting a long to int drops the high 32 bits, no mask needed
21276                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21277                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21278            }
21279
21280            // flag not set, setMeasuredDimension() was not invoked, we raise
21281            // an exception to warn the developer
21282            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21283                throw new IllegalStateException("View with id " + getId() + ": "
21284                        + getClass().getName() + "#onMeasure() did not set the"
21285                        + " measured dimension by calling"
21286                        + " setMeasuredDimension()");
21287            }
21288
21289            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21290        }
21291
21292        mOldWidthMeasureSpec = widthMeasureSpec;
21293        mOldHeightMeasureSpec = heightMeasureSpec;
21294
21295        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21296                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21297    }
21298
21299    /**
21300     * <p>
21301     * Measure the view and its content to determine the measured width and the
21302     * measured height. This method is invoked by {@link #measure(int, int)} and
21303     * should be overridden by subclasses to provide accurate and efficient
21304     * measurement of their contents.
21305     * </p>
21306     *
21307     * <p>
21308     * <strong>CONTRACT:</strong> When overriding this method, you
21309     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21310     * measured width and height of this view. Failure to do so will trigger an
21311     * <code>IllegalStateException</code>, thrown by
21312     * {@link #measure(int, int)}. Calling the superclass'
21313     * {@link #onMeasure(int, int)} is a valid use.
21314     * </p>
21315     *
21316     * <p>
21317     * The base class implementation of measure defaults to the background size,
21318     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21319     * override {@link #onMeasure(int, int)} to provide better measurements of
21320     * their content.
21321     * </p>
21322     *
21323     * <p>
21324     * If this method is overridden, it is the subclass's responsibility to make
21325     * sure the measured height and width are at least the view's minimum height
21326     * and width ({@link #getSuggestedMinimumHeight()} and
21327     * {@link #getSuggestedMinimumWidth()}).
21328     * </p>
21329     *
21330     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21331     *                         The requirements are encoded with
21332     *                         {@link android.view.View.MeasureSpec}.
21333     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21334     *                         The requirements are encoded with
21335     *                         {@link android.view.View.MeasureSpec}.
21336     *
21337     * @see #getMeasuredWidth()
21338     * @see #getMeasuredHeight()
21339     * @see #setMeasuredDimension(int, int)
21340     * @see #getSuggestedMinimumHeight()
21341     * @see #getSuggestedMinimumWidth()
21342     * @see android.view.View.MeasureSpec#getMode(int)
21343     * @see android.view.View.MeasureSpec#getSize(int)
21344     */
21345    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21346        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21347                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21348    }
21349
21350    /**
21351     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21352     * measured width and measured height. Failing to do so will trigger an
21353     * exception at measurement time.</p>
21354     *
21355     * @param measuredWidth The measured width of this view.  May be a complex
21356     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21357     * {@link #MEASURED_STATE_TOO_SMALL}.
21358     * @param measuredHeight The measured height of this view.  May be a complex
21359     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21360     * {@link #MEASURED_STATE_TOO_SMALL}.
21361     */
21362    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21363        boolean optical = isLayoutModeOptical(this);
21364        if (optical != isLayoutModeOptical(mParent)) {
21365            Insets insets = getOpticalInsets();
21366            int opticalWidth  = insets.left + insets.right;
21367            int opticalHeight = insets.top  + insets.bottom;
21368
21369            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21370            measuredHeight += optical ? opticalHeight : -opticalHeight;
21371        }
21372        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21373    }
21374
21375    /**
21376     * Sets the measured dimension without extra processing for things like optical bounds.
21377     * Useful for reapplying consistent values that have already been cooked with adjustments
21378     * for optical bounds, etc. such as those from the measurement cache.
21379     *
21380     * @param measuredWidth The measured width of this view.  May be a complex
21381     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21382     * {@link #MEASURED_STATE_TOO_SMALL}.
21383     * @param measuredHeight The measured height of this view.  May be a complex
21384     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21385     * {@link #MEASURED_STATE_TOO_SMALL}.
21386     */
21387    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21388        mMeasuredWidth = measuredWidth;
21389        mMeasuredHeight = measuredHeight;
21390
21391        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21392    }
21393
21394    /**
21395     * Merge two states as returned by {@link #getMeasuredState()}.
21396     * @param curState The current state as returned from a view or the result
21397     * of combining multiple views.
21398     * @param newState The new view state to combine.
21399     * @return Returns a new integer reflecting the combination of the two
21400     * states.
21401     */
21402    public static int combineMeasuredStates(int curState, int newState) {
21403        return curState | newState;
21404    }
21405
21406    /**
21407     * Version of {@link #resolveSizeAndState(int, int, int)}
21408     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21409     */
21410    public static int resolveSize(int size, int measureSpec) {
21411        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21412    }
21413
21414    /**
21415     * Utility to reconcile a desired size and state, with constraints imposed
21416     * by a MeasureSpec. Will take the desired size, unless a different size
21417     * is imposed by the constraints. The returned value is a compound integer,
21418     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21419     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21420     * resulting size is smaller than the size the view wants to be.
21421     *
21422     * @param size How big the view wants to be.
21423     * @param measureSpec Constraints imposed by the parent.
21424     * @param childMeasuredState Size information bit mask for the view's
21425     *                           children.
21426     * @return Size information bit mask as defined by
21427     *         {@link #MEASURED_SIZE_MASK} and
21428     *         {@link #MEASURED_STATE_TOO_SMALL}.
21429     */
21430    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21431        final int specMode = MeasureSpec.getMode(measureSpec);
21432        final int specSize = MeasureSpec.getSize(measureSpec);
21433        final int result;
21434        switch (specMode) {
21435            case MeasureSpec.AT_MOST:
21436                if (specSize < size) {
21437                    result = specSize | MEASURED_STATE_TOO_SMALL;
21438                } else {
21439                    result = size;
21440                }
21441                break;
21442            case MeasureSpec.EXACTLY:
21443                result = specSize;
21444                break;
21445            case MeasureSpec.UNSPECIFIED:
21446            default:
21447                result = size;
21448        }
21449        return result | (childMeasuredState & MEASURED_STATE_MASK);
21450    }
21451
21452    /**
21453     * Utility to return a default size. Uses the supplied size if the
21454     * MeasureSpec imposed no constraints. Will get larger if allowed
21455     * by the MeasureSpec.
21456     *
21457     * @param size Default size for this view
21458     * @param measureSpec Constraints imposed by the parent
21459     * @return The size this view should be.
21460     */
21461    public static int getDefaultSize(int size, int measureSpec) {
21462        int result = size;
21463        int specMode = MeasureSpec.getMode(measureSpec);
21464        int specSize = MeasureSpec.getSize(measureSpec);
21465
21466        switch (specMode) {
21467        case MeasureSpec.UNSPECIFIED:
21468            result = size;
21469            break;
21470        case MeasureSpec.AT_MOST:
21471        case MeasureSpec.EXACTLY:
21472            result = specSize;
21473            break;
21474        }
21475        return result;
21476    }
21477
21478    /**
21479     * Returns the suggested minimum height that the view should use. This
21480     * returns the maximum of the view's minimum height
21481     * and the background's minimum height
21482     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21483     * <p>
21484     * When being used in {@link #onMeasure(int, int)}, the caller should still
21485     * ensure the returned height is within the requirements of the parent.
21486     *
21487     * @return The suggested minimum height of the view.
21488     */
21489    protected int getSuggestedMinimumHeight() {
21490        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21491
21492    }
21493
21494    /**
21495     * Returns the suggested minimum width that the view should use. This
21496     * returns the maximum of the view's minimum width
21497     * and the background's minimum width
21498     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21499     * <p>
21500     * When being used in {@link #onMeasure(int, int)}, the caller should still
21501     * ensure the returned width is within the requirements of the parent.
21502     *
21503     * @return The suggested minimum width of the view.
21504     */
21505    protected int getSuggestedMinimumWidth() {
21506        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21507    }
21508
21509    /**
21510     * Returns the minimum height of the view.
21511     *
21512     * @return the minimum height the view will try to be, in pixels
21513     *
21514     * @see #setMinimumHeight(int)
21515     *
21516     * @attr ref android.R.styleable#View_minHeight
21517     */
21518    public int getMinimumHeight() {
21519        return mMinHeight;
21520    }
21521
21522    /**
21523     * Sets the minimum height of the view. It is not guaranteed the view will
21524     * be able to achieve this minimum height (for example, if its parent layout
21525     * constrains it with less available height).
21526     *
21527     * @param minHeight The minimum height the view will try to be, in pixels
21528     *
21529     * @see #getMinimumHeight()
21530     *
21531     * @attr ref android.R.styleable#View_minHeight
21532     */
21533    @RemotableViewMethod
21534    public void setMinimumHeight(int minHeight) {
21535        mMinHeight = minHeight;
21536        requestLayout();
21537    }
21538
21539    /**
21540     * Returns the minimum width of the view.
21541     *
21542     * @return the minimum width the view will try to be, in pixels
21543     *
21544     * @see #setMinimumWidth(int)
21545     *
21546     * @attr ref android.R.styleable#View_minWidth
21547     */
21548    public int getMinimumWidth() {
21549        return mMinWidth;
21550    }
21551
21552    /**
21553     * Sets the minimum width of the view. It is not guaranteed the view will
21554     * be able to achieve this minimum width (for example, if its parent layout
21555     * constrains it with less available width).
21556     *
21557     * @param minWidth The minimum width the view will try to be, in pixels
21558     *
21559     * @see #getMinimumWidth()
21560     *
21561     * @attr ref android.R.styleable#View_minWidth
21562     */
21563    public void setMinimumWidth(int minWidth) {
21564        mMinWidth = minWidth;
21565        requestLayout();
21566
21567    }
21568
21569    /**
21570     * Get the animation currently associated with this view.
21571     *
21572     * @return The animation that is currently playing or
21573     *         scheduled to play for this view.
21574     */
21575    public Animation getAnimation() {
21576        return mCurrentAnimation;
21577    }
21578
21579    /**
21580     * Start the specified animation now.
21581     *
21582     * @param animation the animation to start now
21583     */
21584    public void startAnimation(Animation animation) {
21585        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21586        setAnimation(animation);
21587        invalidateParentCaches();
21588        invalidate(true);
21589    }
21590
21591    /**
21592     * Cancels any animations for this view.
21593     */
21594    public void clearAnimation() {
21595        if (mCurrentAnimation != null) {
21596            mCurrentAnimation.detach();
21597        }
21598        mCurrentAnimation = null;
21599        invalidateParentIfNeeded();
21600    }
21601
21602    /**
21603     * Sets the next animation to play for this view.
21604     * If you want the animation to play immediately, use
21605     * {@link #startAnimation(android.view.animation.Animation)} instead.
21606     * This method provides allows fine-grained
21607     * control over the start time and invalidation, but you
21608     * must make sure that 1) the animation has a start time set, and
21609     * 2) the view's parent (which controls animations on its children)
21610     * will be invalidated when the animation is supposed to
21611     * start.
21612     *
21613     * @param animation The next animation, or null.
21614     */
21615    public void setAnimation(Animation animation) {
21616        mCurrentAnimation = animation;
21617
21618        if (animation != null) {
21619            // If the screen is off assume the animation start time is now instead of
21620            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21621            // would cause the animation to start when the screen turns back on
21622            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21623                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21624                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21625            }
21626            animation.reset();
21627        }
21628    }
21629
21630    /**
21631     * Invoked by a parent ViewGroup to notify the start of the animation
21632     * currently associated with this view. If you override this method,
21633     * always call super.onAnimationStart();
21634     *
21635     * @see #setAnimation(android.view.animation.Animation)
21636     * @see #getAnimation()
21637     */
21638    @CallSuper
21639    protected void onAnimationStart() {
21640        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21641    }
21642
21643    /**
21644     * Invoked by a parent ViewGroup to notify the end of the animation
21645     * currently associated with this view. If you override this method,
21646     * always call super.onAnimationEnd();
21647     *
21648     * @see #setAnimation(android.view.animation.Animation)
21649     * @see #getAnimation()
21650     */
21651    @CallSuper
21652    protected void onAnimationEnd() {
21653        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21654    }
21655
21656    /**
21657     * Invoked if there is a Transform that involves alpha. Subclass that can
21658     * draw themselves with the specified alpha should return true, and then
21659     * respect that alpha when their onDraw() is called. If this returns false
21660     * then the view may be redirected to draw into an offscreen buffer to
21661     * fulfill the request, which will look fine, but may be slower than if the
21662     * subclass handles it internally. The default implementation returns false.
21663     *
21664     * @param alpha The alpha (0..255) to apply to the view's drawing
21665     * @return true if the view can draw with the specified alpha.
21666     */
21667    protected boolean onSetAlpha(int alpha) {
21668        return false;
21669    }
21670
21671    /**
21672     * This is used by the RootView to perform an optimization when
21673     * the view hierarchy contains one or several SurfaceView.
21674     * SurfaceView is always considered transparent, but its children are not,
21675     * therefore all View objects remove themselves from the global transparent
21676     * region (passed as a parameter to this function).
21677     *
21678     * @param region The transparent region for this ViewAncestor (window).
21679     *
21680     * @return Returns true if the effective visibility of the view at this
21681     * point is opaque, regardless of the transparent region; returns false
21682     * if it is possible for underlying windows to be seen behind the view.
21683     *
21684     * {@hide}
21685     */
21686    public boolean gatherTransparentRegion(Region region) {
21687        final AttachInfo attachInfo = mAttachInfo;
21688        if (region != null && attachInfo != null) {
21689            final int pflags = mPrivateFlags;
21690            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
21691                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
21692                // remove it from the transparent region.
21693                final int[] location = attachInfo.mTransparentLocation;
21694                getLocationInWindow(location);
21695                // When a view has Z value, then it will be better to leave some area below the view
21696                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
21697                // the bottom part needs more offset than the left, top and right parts due to the
21698                // spot light effects.
21699                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
21700                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
21701                        location[0] + mRight - mLeft + shadowOffset,
21702                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
21703            } else {
21704                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
21705                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
21706                    // the background drawable's non-transparent parts from this transparent region.
21707                    applyDrawableToTransparentRegion(mBackground, region);
21708                }
21709                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
21710                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
21711                    // Similarly, we remove the foreground drawable's non-transparent parts.
21712                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
21713                }
21714            }
21715        }
21716        return true;
21717    }
21718
21719    /**
21720     * Play a sound effect for this view.
21721     *
21722     * <p>The framework will play sound effects for some built in actions, such as
21723     * clicking, but you may wish to play these effects in your widget,
21724     * for instance, for internal navigation.
21725     *
21726     * <p>The sound effect will only be played if sound effects are enabled by the user, and
21727     * {@link #isSoundEffectsEnabled()} is true.
21728     *
21729     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
21730     */
21731    public void playSoundEffect(int soundConstant) {
21732        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
21733            return;
21734        }
21735        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
21736    }
21737
21738    /**
21739     * BZZZTT!!1!
21740     *
21741     * <p>Provide haptic feedback to the user for this view.
21742     *
21743     * <p>The framework will provide haptic feedback for some built in actions,
21744     * such as long presses, but you may wish to provide feedback for your
21745     * own widget.
21746     *
21747     * <p>The feedback will only be performed if
21748     * {@link #isHapticFeedbackEnabled()} is true.
21749     *
21750     * @param feedbackConstant One of the constants defined in
21751     * {@link HapticFeedbackConstants}
21752     */
21753    public boolean performHapticFeedback(int feedbackConstant) {
21754        return performHapticFeedback(feedbackConstant, 0);
21755    }
21756
21757    /**
21758     * BZZZTT!!1!
21759     *
21760     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
21761     *
21762     * @param feedbackConstant One of the constants defined in
21763     * {@link HapticFeedbackConstants}
21764     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
21765     */
21766    public boolean performHapticFeedback(int feedbackConstant, int flags) {
21767        if (mAttachInfo == null) {
21768            return false;
21769        }
21770        //noinspection SimplifiableIfStatement
21771        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
21772                && !isHapticFeedbackEnabled()) {
21773            return false;
21774        }
21775        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
21776                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
21777    }
21778
21779    /**
21780     * Request that the visibility of the status bar or other screen/window
21781     * decorations be changed.
21782     *
21783     * <p>This method is used to put the over device UI into temporary modes
21784     * where the user's attention is focused more on the application content,
21785     * by dimming or hiding surrounding system affordances.  This is typically
21786     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
21787     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
21788     * to be placed behind the action bar (and with these flags other system
21789     * affordances) so that smooth transitions between hiding and showing them
21790     * can be done.
21791     *
21792     * <p>Two representative examples of the use of system UI visibility is
21793     * implementing a content browsing application (like a magazine reader)
21794     * and a video playing application.
21795     *
21796     * <p>The first code shows a typical implementation of a View in a content
21797     * browsing application.  In this implementation, the application goes
21798     * into a content-oriented mode by hiding the status bar and action bar,
21799     * and putting the navigation elements into lights out mode.  The user can
21800     * then interact with content while in this mode.  Such an application should
21801     * provide an easy way for the user to toggle out of the mode (such as to
21802     * check information in the status bar or access notifications).  In the
21803     * implementation here, this is done simply by tapping on the content.
21804     *
21805     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
21806     *      content}
21807     *
21808     * <p>This second code sample shows a typical implementation of a View
21809     * in a video playing application.  In this situation, while the video is
21810     * playing the application would like to go into a complete full-screen mode,
21811     * to use as much of the display as possible for the video.  When in this state
21812     * the user can not interact with the application; the system intercepts
21813     * touching on the screen to pop the UI out of full screen mode.  See
21814     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
21815     *
21816     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
21817     *      content}
21818     *
21819     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21820     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21821     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21822     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21823     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21824     */
21825    public void setSystemUiVisibility(int visibility) {
21826        if (visibility != mSystemUiVisibility) {
21827            mSystemUiVisibility = visibility;
21828            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21829                mParent.recomputeViewAttributes(this);
21830            }
21831        }
21832    }
21833
21834    /**
21835     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
21836     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21837     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21838     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21839     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21840     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21841     */
21842    public int getSystemUiVisibility() {
21843        return mSystemUiVisibility;
21844    }
21845
21846    /**
21847     * Returns the current system UI visibility that is currently set for
21848     * the entire window.  This is the combination of the
21849     * {@link #setSystemUiVisibility(int)} values supplied by all of the
21850     * views in the window.
21851     */
21852    public int getWindowSystemUiVisibility() {
21853        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
21854    }
21855
21856    /**
21857     * Override to find out when the window's requested system UI visibility
21858     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
21859     * This is different from the callbacks received through
21860     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
21861     * in that this is only telling you about the local request of the window,
21862     * not the actual values applied by the system.
21863     */
21864    public void onWindowSystemUiVisibilityChanged(int visible) {
21865    }
21866
21867    /**
21868     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
21869     * the view hierarchy.
21870     */
21871    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
21872        onWindowSystemUiVisibilityChanged(visible);
21873    }
21874
21875    /**
21876     * Set a listener to receive callbacks when the visibility of the system bar changes.
21877     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
21878     */
21879    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
21880        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
21881        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21882            mParent.recomputeViewAttributes(this);
21883        }
21884    }
21885
21886    /**
21887     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
21888     * the view hierarchy.
21889     */
21890    public void dispatchSystemUiVisibilityChanged(int visibility) {
21891        ListenerInfo li = mListenerInfo;
21892        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
21893            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
21894                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
21895        }
21896    }
21897
21898    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
21899        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
21900        if (val != mSystemUiVisibility) {
21901            setSystemUiVisibility(val);
21902            return true;
21903        }
21904        return false;
21905    }
21906
21907    /** @hide */
21908    public void setDisabledSystemUiVisibility(int flags) {
21909        if (mAttachInfo != null) {
21910            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
21911                mAttachInfo.mDisabledSystemUiVisibility = flags;
21912                if (mParent != null) {
21913                    mParent.recomputeViewAttributes(this);
21914                }
21915            }
21916        }
21917    }
21918
21919    /**
21920     * Creates an image that the system displays during the drag and drop
21921     * operation. This is called a &quot;drag shadow&quot;. The default implementation
21922     * for a DragShadowBuilder based on a View returns an image that has exactly the same
21923     * appearance as the given View. The default also positions the center of the drag shadow
21924     * directly under the touch point. If no View is provided (the constructor with no parameters
21925     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
21926     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
21927     * default is an invisible drag shadow.
21928     * <p>
21929     * You are not required to use the View you provide to the constructor as the basis of the
21930     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
21931     * anything you want as the drag shadow.
21932     * </p>
21933     * <p>
21934     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
21935     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
21936     *  size and position of the drag shadow. It uses this data to construct a
21937     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
21938     *  so that your application can draw the shadow image in the Canvas.
21939     * </p>
21940     *
21941     * <div class="special reference">
21942     * <h3>Developer Guides</h3>
21943     * <p>For a guide to implementing drag and drop features, read the
21944     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21945     * </div>
21946     */
21947    public static class DragShadowBuilder {
21948        private final WeakReference<View> mView;
21949
21950        /**
21951         * Constructs a shadow image builder based on a View. By default, the resulting drag
21952         * shadow will have the same appearance and dimensions as the View, with the touch point
21953         * over the center of the View.
21954         * @param view A View. Any View in scope can be used.
21955         */
21956        public DragShadowBuilder(View view) {
21957            mView = new WeakReference<View>(view);
21958        }
21959
21960        /**
21961         * Construct a shadow builder object with no associated View.  This
21962         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
21963         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
21964         * to supply the drag shadow's dimensions and appearance without
21965         * reference to any View object. If they are not overridden, then the result is an
21966         * invisible drag shadow.
21967         */
21968        public DragShadowBuilder() {
21969            mView = new WeakReference<View>(null);
21970        }
21971
21972        /**
21973         * Returns the View object that had been passed to the
21974         * {@link #View.DragShadowBuilder(View)}
21975         * constructor.  If that View parameter was {@code null} or if the
21976         * {@link #View.DragShadowBuilder()}
21977         * constructor was used to instantiate the builder object, this method will return
21978         * null.
21979         *
21980         * @return The View object associate with this builder object.
21981         */
21982        @SuppressWarnings({"JavadocReference"})
21983        final public View getView() {
21984            return mView.get();
21985        }
21986
21987        /**
21988         * Provides the metrics for the shadow image. These include the dimensions of
21989         * the shadow image, and the point within that shadow that should
21990         * be centered under the touch location while dragging.
21991         * <p>
21992         * The default implementation sets the dimensions of the shadow to be the
21993         * same as the dimensions of the View itself and centers the shadow under
21994         * the touch point.
21995         * </p>
21996         *
21997         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
21998         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
21999         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22000         * image.
22001         *
22002         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22003         * shadow image that should be underneath the touch point during the drag and drop
22004         * operation. Your application must set {@link android.graphics.Point#x} to the
22005         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22006         */
22007        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22008            final View view = mView.get();
22009            if (view != null) {
22010                outShadowSize.set(view.getWidth(), view.getHeight());
22011                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22012            } else {
22013                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22014            }
22015        }
22016
22017        /**
22018         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22019         * based on the dimensions it received from the
22020         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22021         *
22022         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22023         */
22024        public void onDrawShadow(Canvas canvas) {
22025            final View view = mView.get();
22026            if (view != null) {
22027                view.draw(canvas);
22028            } else {
22029                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22030            }
22031        }
22032    }
22033
22034    /**
22035     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22036     * startDragAndDrop()} for newer platform versions.
22037     */
22038    @Deprecated
22039    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22040                                   Object myLocalState, int flags) {
22041        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22042    }
22043
22044    /**
22045     * Starts a drag and drop operation. When your application calls this method, it passes a
22046     * {@link android.view.View.DragShadowBuilder} object to the system. The
22047     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22048     * to get metrics for the drag shadow, and then calls the object's
22049     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22050     * <p>
22051     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22052     *  drag events to all the View objects in your application that are currently visible. It does
22053     *  this either by calling the View object's drag listener (an implementation of
22054     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22055     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22056     *  Both are passed a {@link android.view.DragEvent} object that has a
22057     *  {@link android.view.DragEvent#getAction()} value of
22058     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22059     * </p>
22060     * <p>
22061     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22062     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22063     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22064     * to the View the user selected for dragging.
22065     * </p>
22066     * @param data A {@link android.content.ClipData} object pointing to the data to be
22067     * transferred by the drag and drop operation.
22068     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22069     * drag shadow.
22070     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22071     * drop operation. When dispatching drag events to views in the same activity this object
22072     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22073     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22074     * will return null).
22075     * <p>
22076     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22077     * to the target Views. For example, it can contain flags that differentiate between a
22078     * a copy operation and a move operation.
22079     * </p>
22080     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22081     * flags, or any combination of the following:
22082     *     <ul>
22083     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22084     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22085     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22086     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22087     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22088     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22089     *     </ul>
22090     * @return {@code true} if the method completes successfully, or
22091     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22092     * do a drag, and so no drag operation is in progress.
22093     */
22094    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22095            Object myLocalState, int flags) {
22096        if (ViewDebug.DEBUG_DRAG) {
22097            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22098        }
22099        if (mAttachInfo == null) {
22100            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22101            return false;
22102        }
22103
22104        if (data != null) {
22105            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22106        }
22107
22108        boolean okay = false;
22109
22110        Point shadowSize = new Point();
22111        Point shadowTouchPoint = new Point();
22112        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22113
22114        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22115                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22116            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22117        }
22118
22119        if (ViewDebug.DEBUG_DRAG) {
22120            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22121                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22122        }
22123        if (mAttachInfo.mDragSurface != null) {
22124            mAttachInfo.mDragSurface.release();
22125        }
22126        mAttachInfo.mDragSurface = new Surface();
22127        try {
22128            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22129                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22130            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22131                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22132            if (mAttachInfo.mDragToken != null) {
22133                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22134                try {
22135                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22136                    shadowBuilder.onDrawShadow(canvas);
22137                } finally {
22138                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22139                }
22140
22141                final ViewRootImpl root = getViewRootImpl();
22142
22143                // Cache the local state object for delivery with DragEvents
22144                root.setLocalDragState(myLocalState);
22145
22146                // repurpose 'shadowSize' for the last touch point
22147                root.getLastTouchPoint(shadowSize);
22148
22149                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22150                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22151                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22152                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22153            }
22154        } catch (Exception e) {
22155            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22156            mAttachInfo.mDragSurface.destroy();
22157            mAttachInfo.mDragSurface = null;
22158        }
22159
22160        return okay;
22161    }
22162
22163    /**
22164     * Cancels an ongoing drag and drop operation.
22165     * <p>
22166     * A {@link android.view.DragEvent} object with
22167     * {@link android.view.DragEvent#getAction()} value of
22168     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22169     * {@link android.view.DragEvent#getResult()} value of {@code false}
22170     * will be sent to every
22171     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22172     * even if they are not currently visible.
22173     * </p>
22174     * <p>
22175     * This method can be called on any View in the same window as the View on which
22176     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22177     * was called.
22178     * </p>
22179     */
22180    public final void cancelDragAndDrop() {
22181        if (ViewDebug.DEBUG_DRAG) {
22182            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22183        }
22184        if (mAttachInfo == null) {
22185            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22186            return;
22187        }
22188        if (mAttachInfo.mDragToken != null) {
22189            try {
22190                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22191            } catch (Exception e) {
22192                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22193            }
22194            mAttachInfo.mDragToken = null;
22195        } else {
22196            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22197        }
22198    }
22199
22200    /**
22201     * Updates the drag shadow for the ongoing drag and drop operation.
22202     *
22203     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22204     * new drag shadow.
22205     */
22206    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22207        if (ViewDebug.DEBUG_DRAG) {
22208            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22209        }
22210        if (mAttachInfo == null) {
22211            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22212            return;
22213        }
22214        if (mAttachInfo.mDragToken != null) {
22215            try {
22216                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22217                try {
22218                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22219                    shadowBuilder.onDrawShadow(canvas);
22220                } finally {
22221                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22222                }
22223            } catch (Exception e) {
22224                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22225            }
22226        } else {
22227            Log.e(VIEW_LOG_TAG, "No active drag");
22228        }
22229    }
22230
22231    /**
22232     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22233     * between {startX, startY} and the new cursor positon.
22234     * @param startX horizontal coordinate where the move started.
22235     * @param startY vertical coordinate where the move started.
22236     * @return whether moving was started successfully.
22237     * @hide
22238     */
22239    public final boolean startMovingTask(float startX, float startY) {
22240        if (ViewDebug.DEBUG_POSITIONING) {
22241            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22242        }
22243        try {
22244            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22245        } catch (RemoteException e) {
22246            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22247        }
22248        return false;
22249    }
22250
22251    /**
22252     * Handles drag events sent by the system following a call to
22253     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22254     * startDragAndDrop()}.
22255     *<p>
22256     * When the system calls this method, it passes a
22257     * {@link android.view.DragEvent} object. A call to
22258     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22259     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22260     * operation.
22261     * @param event The {@link android.view.DragEvent} sent by the system.
22262     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22263     * in DragEvent, indicating the type of drag event represented by this object.
22264     * @return {@code true} if the method was successful, otherwise {@code false}.
22265     * <p>
22266     *  The method should return {@code true} in response to an action type of
22267     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22268     *  operation.
22269     * </p>
22270     * <p>
22271     *  The method should also return {@code true} in response to an action type of
22272     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22273     *  {@code false} if it didn't.
22274     * </p>
22275     * <p>
22276     *  For all other events, the return value is ignored.
22277     * </p>
22278     */
22279    public boolean onDragEvent(DragEvent event) {
22280        return false;
22281    }
22282
22283    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22284    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22285        return callDragEventHandler(event);
22286    }
22287
22288    /**
22289     * Detects if this View is enabled and has a drag event listener.
22290     * If both are true, then it calls the drag event listener with the
22291     * {@link android.view.DragEvent} it received. If the drag event listener returns
22292     * {@code true}, then dispatchDragEvent() returns {@code true}.
22293     * <p>
22294     * For all other cases, the method calls the
22295     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22296     * method and returns its result.
22297     * </p>
22298     * <p>
22299     * This ensures that a drag event is always consumed, even if the View does not have a drag
22300     * event listener. However, if the View has a listener and the listener returns true, then
22301     * onDragEvent() is not called.
22302     * </p>
22303     */
22304    public boolean dispatchDragEvent(DragEvent event) {
22305        event.mEventHandlerWasCalled = true;
22306        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22307            event.mAction == DragEvent.ACTION_DROP) {
22308            // About to deliver an event with coordinates to this view. Notify that now this view
22309            // has drag focus. This will send exit/enter events as needed.
22310            getViewRootImpl().setDragFocus(this, event);
22311        }
22312        return callDragEventHandler(event);
22313    }
22314
22315    final boolean callDragEventHandler(DragEvent event) {
22316        final boolean result;
22317
22318        ListenerInfo li = mListenerInfo;
22319        //noinspection SimplifiableIfStatement
22320        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22321                && li.mOnDragListener.onDrag(this, event)) {
22322            result = true;
22323        } else {
22324            result = onDragEvent(event);
22325        }
22326
22327        switch (event.mAction) {
22328            case DragEvent.ACTION_DRAG_ENTERED: {
22329                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22330                refreshDrawableState();
22331            } break;
22332            case DragEvent.ACTION_DRAG_EXITED: {
22333                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22334                refreshDrawableState();
22335            } break;
22336            case DragEvent.ACTION_DRAG_ENDED: {
22337                mPrivateFlags2 &= ~View.DRAG_MASK;
22338                refreshDrawableState();
22339            } break;
22340        }
22341
22342        return result;
22343    }
22344
22345    boolean canAcceptDrag() {
22346        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22347    }
22348
22349    /**
22350     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22351     * it is ever exposed at all.
22352     * @hide
22353     */
22354    public void onCloseSystemDialogs(String reason) {
22355    }
22356
22357    /**
22358     * Given a Drawable whose bounds have been set to draw into this view,
22359     * update a Region being computed for
22360     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22361     * that any non-transparent parts of the Drawable are removed from the
22362     * given transparent region.
22363     *
22364     * @param dr The Drawable whose transparency is to be applied to the region.
22365     * @param region A Region holding the current transparency information,
22366     * where any parts of the region that are set are considered to be
22367     * transparent.  On return, this region will be modified to have the
22368     * transparency information reduced by the corresponding parts of the
22369     * Drawable that are not transparent.
22370     * {@hide}
22371     */
22372    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22373        if (DBG) {
22374            Log.i("View", "Getting transparent region for: " + this);
22375        }
22376        final Region r = dr.getTransparentRegion();
22377        final Rect db = dr.getBounds();
22378        final AttachInfo attachInfo = mAttachInfo;
22379        if (r != null && attachInfo != null) {
22380            final int w = getRight()-getLeft();
22381            final int h = getBottom()-getTop();
22382            if (db.left > 0) {
22383                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22384                r.op(0, 0, db.left, h, Region.Op.UNION);
22385            }
22386            if (db.right < w) {
22387                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22388                r.op(db.right, 0, w, h, Region.Op.UNION);
22389            }
22390            if (db.top > 0) {
22391                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22392                r.op(0, 0, w, db.top, Region.Op.UNION);
22393            }
22394            if (db.bottom < h) {
22395                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22396                r.op(0, db.bottom, w, h, Region.Op.UNION);
22397            }
22398            final int[] location = attachInfo.mTransparentLocation;
22399            getLocationInWindow(location);
22400            r.translate(location[0], location[1]);
22401            region.op(r, Region.Op.INTERSECT);
22402        } else {
22403            region.op(db, Region.Op.DIFFERENCE);
22404        }
22405    }
22406
22407    private void checkForLongClick(int delayOffset, float x, float y) {
22408        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22409            mHasPerformedLongPress = false;
22410
22411            if (mPendingCheckForLongPress == null) {
22412                mPendingCheckForLongPress = new CheckForLongPress();
22413            }
22414            mPendingCheckForLongPress.setAnchor(x, y);
22415            mPendingCheckForLongPress.rememberWindowAttachCount();
22416            mPendingCheckForLongPress.rememberPressedState();
22417            postDelayed(mPendingCheckForLongPress,
22418                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22419        }
22420    }
22421
22422    /**
22423     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22424     * LayoutInflater} class, which provides a full range of options for view inflation.
22425     *
22426     * @param context The Context object for your activity or application.
22427     * @param resource The resource ID to inflate
22428     * @param root A view group that will be the parent.  Used to properly inflate the
22429     * layout_* parameters.
22430     * @see LayoutInflater
22431     */
22432    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22433        LayoutInflater factory = LayoutInflater.from(context);
22434        return factory.inflate(resource, root);
22435    }
22436
22437    /**
22438     * Scroll the view with standard behavior for scrolling beyond the normal
22439     * content boundaries. Views that call this method should override
22440     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22441     * results of an over-scroll operation.
22442     *
22443     * Views can use this method to handle any touch or fling-based scrolling.
22444     *
22445     * @param deltaX Change in X in pixels
22446     * @param deltaY Change in Y in pixels
22447     * @param scrollX Current X scroll value in pixels before applying deltaX
22448     * @param scrollY Current Y scroll value in pixels before applying deltaY
22449     * @param scrollRangeX Maximum content scroll range along the X axis
22450     * @param scrollRangeY Maximum content scroll range along the Y axis
22451     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22452     *          along the X axis.
22453     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22454     *          along the Y axis.
22455     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22456     * @return true if scrolling was clamped to an over-scroll boundary along either
22457     *          axis, false otherwise.
22458     */
22459    @SuppressWarnings({"UnusedParameters"})
22460    protected boolean overScrollBy(int deltaX, int deltaY,
22461            int scrollX, int scrollY,
22462            int scrollRangeX, int scrollRangeY,
22463            int maxOverScrollX, int maxOverScrollY,
22464            boolean isTouchEvent) {
22465        final int overScrollMode = mOverScrollMode;
22466        final boolean canScrollHorizontal =
22467                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22468        final boolean canScrollVertical =
22469                computeVerticalScrollRange() > computeVerticalScrollExtent();
22470        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22471                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22472        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22473                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22474
22475        int newScrollX = scrollX + deltaX;
22476        if (!overScrollHorizontal) {
22477            maxOverScrollX = 0;
22478        }
22479
22480        int newScrollY = scrollY + deltaY;
22481        if (!overScrollVertical) {
22482            maxOverScrollY = 0;
22483        }
22484
22485        // Clamp values if at the limits and record
22486        final int left = -maxOverScrollX;
22487        final int right = maxOverScrollX + scrollRangeX;
22488        final int top = -maxOverScrollY;
22489        final int bottom = maxOverScrollY + scrollRangeY;
22490
22491        boolean clampedX = false;
22492        if (newScrollX > right) {
22493            newScrollX = right;
22494            clampedX = true;
22495        } else if (newScrollX < left) {
22496            newScrollX = left;
22497            clampedX = true;
22498        }
22499
22500        boolean clampedY = false;
22501        if (newScrollY > bottom) {
22502            newScrollY = bottom;
22503            clampedY = true;
22504        } else if (newScrollY < top) {
22505            newScrollY = top;
22506            clampedY = true;
22507        }
22508
22509        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22510
22511        return clampedX || clampedY;
22512    }
22513
22514    /**
22515     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22516     * respond to the results of an over-scroll operation.
22517     *
22518     * @param scrollX New X scroll value in pixels
22519     * @param scrollY New Y scroll value in pixels
22520     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22521     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22522     */
22523    protected void onOverScrolled(int scrollX, int scrollY,
22524            boolean clampedX, boolean clampedY) {
22525        // Intentionally empty.
22526    }
22527
22528    /**
22529     * Returns the over-scroll mode for this view. The result will be
22530     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22531     * (allow over-scrolling only if the view content is larger than the container),
22532     * or {@link #OVER_SCROLL_NEVER}.
22533     *
22534     * @return This view's over-scroll mode.
22535     */
22536    public int getOverScrollMode() {
22537        return mOverScrollMode;
22538    }
22539
22540    /**
22541     * Set the over-scroll mode for this view. Valid over-scroll modes are
22542     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22543     * (allow over-scrolling only if the view content is larger than the container),
22544     * or {@link #OVER_SCROLL_NEVER}.
22545     *
22546     * Setting the over-scroll mode of a view will have an effect only if the
22547     * view is capable of scrolling.
22548     *
22549     * @param overScrollMode The new over-scroll mode for this view.
22550     */
22551    public void setOverScrollMode(int overScrollMode) {
22552        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22553                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22554                overScrollMode != OVER_SCROLL_NEVER) {
22555            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22556        }
22557        mOverScrollMode = overScrollMode;
22558    }
22559
22560    /**
22561     * Enable or disable nested scrolling for this view.
22562     *
22563     * <p>If this property is set to true the view will be permitted to initiate nested
22564     * scrolling operations with a compatible parent view in the current hierarchy. If this
22565     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22566     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22567     * the nested scroll.</p>
22568     *
22569     * @param enabled true to enable nested scrolling, false to disable
22570     *
22571     * @see #isNestedScrollingEnabled()
22572     */
22573    public void setNestedScrollingEnabled(boolean enabled) {
22574        if (enabled) {
22575            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22576        } else {
22577            stopNestedScroll();
22578            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22579        }
22580    }
22581
22582    /**
22583     * Returns true if nested scrolling is enabled for this view.
22584     *
22585     * <p>If nested scrolling is enabled and this View class implementation supports it,
22586     * this view will act as a nested scrolling child view when applicable, forwarding data
22587     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22588     * parent.</p>
22589     *
22590     * @return true if nested scrolling is enabled
22591     *
22592     * @see #setNestedScrollingEnabled(boolean)
22593     */
22594    public boolean isNestedScrollingEnabled() {
22595        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22596                PFLAG3_NESTED_SCROLLING_ENABLED;
22597    }
22598
22599    /**
22600     * Begin a nestable scroll operation along the given axes.
22601     *
22602     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22603     *
22604     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22605     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22606     * In the case of touch scrolling the nested scroll will be terminated automatically in
22607     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22608     * In the event of programmatic scrolling the caller must explicitly call
22609     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22610     *
22611     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22612     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22613     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22614     *
22615     * <p>At each incremental step of the scroll the caller should invoke
22616     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22617     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22618     * parent at least partially consumed the scroll and the caller should adjust the amount it
22619     * scrolls by.</p>
22620     *
22621     * <p>After applying the remainder of the scroll delta the caller should invoke
22622     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22623     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22624     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22625     * </p>
22626     *
22627     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22628     *             {@link #SCROLL_AXIS_VERTICAL}.
22629     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22630     *         the current gesture.
22631     *
22632     * @see #stopNestedScroll()
22633     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22634     * @see #dispatchNestedScroll(int, int, int, int, int[])
22635     */
22636    public boolean startNestedScroll(int axes) {
22637        if (hasNestedScrollingParent()) {
22638            // Already in progress
22639            return true;
22640        }
22641        if (isNestedScrollingEnabled()) {
22642            ViewParent p = getParent();
22643            View child = this;
22644            while (p != null) {
22645                try {
22646                    if (p.onStartNestedScroll(child, this, axes)) {
22647                        mNestedScrollingParent = p;
22648                        p.onNestedScrollAccepted(child, this, axes);
22649                        return true;
22650                    }
22651                } catch (AbstractMethodError e) {
22652                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22653                            "method onStartNestedScroll", e);
22654                    // Allow the search upward to continue
22655                }
22656                if (p instanceof View) {
22657                    child = (View) p;
22658                }
22659                p = p.getParent();
22660            }
22661        }
22662        return false;
22663    }
22664
22665    /**
22666     * Stop a nested scroll in progress.
22667     *
22668     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22669     *
22670     * @see #startNestedScroll(int)
22671     */
22672    public void stopNestedScroll() {
22673        if (mNestedScrollingParent != null) {
22674            mNestedScrollingParent.onStopNestedScroll(this);
22675            mNestedScrollingParent = null;
22676        }
22677    }
22678
22679    /**
22680     * Returns true if this view has a nested scrolling parent.
22681     *
22682     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22683     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22684     *
22685     * @return whether this view has a nested scrolling parent
22686     */
22687    public boolean hasNestedScrollingParent() {
22688        return mNestedScrollingParent != null;
22689    }
22690
22691    /**
22692     * Dispatch one step of a nested scroll in progress.
22693     *
22694     * <p>Implementations of views that support nested scrolling should call this to report
22695     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
22696     * is not currently in progress or nested scrolling is not
22697     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
22698     *
22699     * <p>Compatible View implementations should also call
22700     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
22701     * consuming a component of the scroll event themselves.</p>
22702     *
22703     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
22704     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
22705     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
22706     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
22707     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22708     *                       in local view coordinates of this view from before this operation
22709     *                       to after it completes. View implementations may use this to adjust
22710     *                       expected input coordinate tracking.
22711     * @return true if the event was dispatched, false if it could not be dispatched.
22712     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22713     */
22714    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
22715            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
22716        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22717            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
22718                int startX = 0;
22719                int startY = 0;
22720                if (offsetInWindow != null) {
22721                    getLocationInWindow(offsetInWindow);
22722                    startX = offsetInWindow[0];
22723                    startY = offsetInWindow[1];
22724                }
22725
22726                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
22727                        dxUnconsumed, dyUnconsumed);
22728
22729                if (offsetInWindow != null) {
22730                    getLocationInWindow(offsetInWindow);
22731                    offsetInWindow[0] -= startX;
22732                    offsetInWindow[1] -= startY;
22733                }
22734                return true;
22735            } else if (offsetInWindow != null) {
22736                // No motion, no dispatch. Keep offsetInWindow up to date.
22737                offsetInWindow[0] = 0;
22738                offsetInWindow[1] = 0;
22739            }
22740        }
22741        return false;
22742    }
22743
22744    /**
22745     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
22746     *
22747     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
22748     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
22749     * scrolling operation to consume some or all of the scroll operation before the child view
22750     * consumes it.</p>
22751     *
22752     * @param dx Horizontal scroll distance in pixels
22753     * @param dy Vertical scroll distance in pixels
22754     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
22755     *                 and consumed[1] the consumed dy.
22756     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22757     *                       in local view coordinates of this view from before this operation
22758     *                       to after it completes. View implementations may use this to adjust
22759     *                       expected input coordinate tracking.
22760     * @return true if the parent consumed some or all of the scroll delta
22761     * @see #dispatchNestedScroll(int, int, int, int, int[])
22762     */
22763    public boolean dispatchNestedPreScroll(int dx, int dy,
22764            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
22765        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22766            if (dx != 0 || dy != 0) {
22767                int startX = 0;
22768                int startY = 0;
22769                if (offsetInWindow != null) {
22770                    getLocationInWindow(offsetInWindow);
22771                    startX = offsetInWindow[0];
22772                    startY = offsetInWindow[1];
22773                }
22774
22775                if (consumed == null) {
22776                    if (mTempNestedScrollConsumed == null) {
22777                        mTempNestedScrollConsumed = new int[2];
22778                    }
22779                    consumed = mTempNestedScrollConsumed;
22780                }
22781                consumed[0] = 0;
22782                consumed[1] = 0;
22783                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
22784
22785                if (offsetInWindow != null) {
22786                    getLocationInWindow(offsetInWindow);
22787                    offsetInWindow[0] -= startX;
22788                    offsetInWindow[1] -= startY;
22789                }
22790                return consumed[0] != 0 || consumed[1] != 0;
22791            } else if (offsetInWindow != null) {
22792                offsetInWindow[0] = 0;
22793                offsetInWindow[1] = 0;
22794            }
22795        }
22796        return false;
22797    }
22798
22799    /**
22800     * Dispatch a fling to a nested scrolling parent.
22801     *
22802     * <p>This method should be used to indicate that a nested scrolling child has detected
22803     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
22804     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
22805     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
22806     * along a scrollable axis.</p>
22807     *
22808     * <p>If a nested scrolling child view would normally fling but it is at the edge of
22809     * its own content, it can use this method to delegate the fling to its nested scrolling
22810     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
22811     *
22812     * @param velocityX Horizontal fling velocity in pixels per second
22813     * @param velocityY Vertical fling velocity in pixels per second
22814     * @param consumed true if the child consumed the fling, false otherwise
22815     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
22816     */
22817    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
22818        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22819            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
22820        }
22821        return false;
22822    }
22823
22824    /**
22825     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
22826     *
22827     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
22828     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
22829     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
22830     * before the child view consumes it. If this method returns <code>true</code>, a nested
22831     * parent view consumed the fling and this view should not scroll as a result.</p>
22832     *
22833     * <p>For a better user experience, only one view in a nested scrolling chain should consume
22834     * the fling at a time. If a parent view consumed the fling this method will return false.
22835     * Custom view implementations should account for this in two ways:</p>
22836     *
22837     * <ul>
22838     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
22839     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
22840     *     position regardless.</li>
22841     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
22842     *     even to settle back to a valid idle position.</li>
22843     * </ul>
22844     *
22845     * <p>Views should also not offer fling velocities to nested parent views along an axis
22846     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
22847     * should not offer a horizontal fling velocity to its parents since scrolling along that
22848     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
22849     *
22850     * @param velocityX Horizontal fling velocity in pixels per second
22851     * @param velocityY Vertical fling velocity in pixels per second
22852     * @return true if a nested scrolling parent consumed the fling
22853     */
22854    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
22855        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22856            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
22857        }
22858        return false;
22859    }
22860
22861    /**
22862     * Gets a scale factor that determines the distance the view should scroll
22863     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
22864     * @return The vertical scroll scale factor.
22865     * @hide
22866     */
22867    protected float getVerticalScrollFactor() {
22868        if (mVerticalScrollFactor == 0) {
22869            TypedValue outValue = new TypedValue();
22870            if (!mContext.getTheme().resolveAttribute(
22871                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
22872                throw new IllegalStateException(
22873                        "Expected theme to define listPreferredItemHeight.");
22874            }
22875            mVerticalScrollFactor = outValue.getDimension(
22876                    mContext.getResources().getDisplayMetrics());
22877        }
22878        return mVerticalScrollFactor;
22879    }
22880
22881    /**
22882     * Gets a scale factor that determines the distance the view should scroll
22883     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
22884     * @return The horizontal scroll scale factor.
22885     * @hide
22886     */
22887    protected float getHorizontalScrollFactor() {
22888        // TODO: Should use something else.
22889        return getVerticalScrollFactor();
22890    }
22891
22892    /**
22893     * Return the value specifying the text direction or policy that was set with
22894     * {@link #setTextDirection(int)}.
22895     *
22896     * @return the defined text direction. It can be one of:
22897     *
22898     * {@link #TEXT_DIRECTION_INHERIT},
22899     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22900     * {@link #TEXT_DIRECTION_ANY_RTL},
22901     * {@link #TEXT_DIRECTION_LTR},
22902     * {@link #TEXT_DIRECTION_RTL},
22903     * {@link #TEXT_DIRECTION_LOCALE},
22904     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22905     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22906     *
22907     * @attr ref android.R.styleable#View_textDirection
22908     *
22909     * @hide
22910     */
22911    @ViewDebug.ExportedProperty(category = "text", mapping = {
22912            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22913            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22914            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22915            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22916            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22917            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22918            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22919            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22920    })
22921    public int getRawTextDirection() {
22922        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
22923    }
22924
22925    /**
22926     * Set the text direction.
22927     *
22928     * @param textDirection the direction to set. Should be one of:
22929     *
22930     * {@link #TEXT_DIRECTION_INHERIT},
22931     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22932     * {@link #TEXT_DIRECTION_ANY_RTL},
22933     * {@link #TEXT_DIRECTION_LTR},
22934     * {@link #TEXT_DIRECTION_RTL},
22935     * {@link #TEXT_DIRECTION_LOCALE}
22936     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22937     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
22938     *
22939     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
22940     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
22941     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
22942     *
22943     * @attr ref android.R.styleable#View_textDirection
22944     */
22945    public void setTextDirection(int textDirection) {
22946        if (getRawTextDirection() != textDirection) {
22947            // Reset the current text direction and the resolved one
22948            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
22949            resetResolvedTextDirection();
22950            // Set the new text direction
22951            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
22952            // Do resolution
22953            resolveTextDirection();
22954            // Notify change
22955            onRtlPropertiesChanged(getLayoutDirection());
22956            // Refresh
22957            requestLayout();
22958            invalidate(true);
22959        }
22960    }
22961
22962    /**
22963     * Return the resolved text direction.
22964     *
22965     * @return the resolved text direction. Returns one of:
22966     *
22967     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22968     * {@link #TEXT_DIRECTION_ANY_RTL},
22969     * {@link #TEXT_DIRECTION_LTR},
22970     * {@link #TEXT_DIRECTION_RTL},
22971     * {@link #TEXT_DIRECTION_LOCALE},
22972     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22973     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22974     *
22975     * @attr ref android.R.styleable#View_textDirection
22976     */
22977    @ViewDebug.ExportedProperty(category = "text", mapping = {
22978            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22979            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22980            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22981            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22982            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22983            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22984            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22985            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22986    })
22987    public int getTextDirection() {
22988        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
22989    }
22990
22991    /**
22992     * Resolve the text direction.
22993     *
22994     * @return true if resolution has been done, false otherwise.
22995     *
22996     * @hide
22997     */
22998    public boolean resolveTextDirection() {
22999        // Reset any previous text direction resolution
23000        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23001
23002        if (hasRtlSupport()) {
23003            // Set resolved text direction flag depending on text direction flag
23004            final int textDirection = getRawTextDirection();
23005            switch(textDirection) {
23006                case TEXT_DIRECTION_INHERIT:
23007                    if (!canResolveTextDirection()) {
23008                        // We cannot do the resolution if there is no parent, so use the default one
23009                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23010                        // Resolution will need to happen again later
23011                        return false;
23012                    }
23013
23014                    // Parent has not yet resolved, so we still return the default
23015                    try {
23016                        if (!mParent.isTextDirectionResolved()) {
23017                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23018                            // Resolution will need to happen again later
23019                            return false;
23020                        }
23021                    } catch (AbstractMethodError e) {
23022                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23023                                " does not fully implement ViewParent", e);
23024                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23025                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23026                        return true;
23027                    }
23028
23029                    // Set current resolved direction to the same value as the parent's one
23030                    int parentResolvedDirection;
23031                    try {
23032                        parentResolvedDirection = mParent.getTextDirection();
23033                    } catch (AbstractMethodError e) {
23034                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23035                                " does not fully implement ViewParent", e);
23036                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23037                    }
23038                    switch (parentResolvedDirection) {
23039                        case TEXT_DIRECTION_FIRST_STRONG:
23040                        case TEXT_DIRECTION_ANY_RTL:
23041                        case TEXT_DIRECTION_LTR:
23042                        case TEXT_DIRECTION_RTL:
23043                        case TEXT_DIRECTION_LOCALE:
23044                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23045                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23046                            mPrivateFlags2 |=
23047                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23048                            break;
23049                        default:
23050                            // Default resolved direction is "first strong" heuristic
23051                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23052                    }
23053                    break;
23054                case TEXT_DIRECTION_FIRST_STRONG:
23055                case TEXT_DIRECTION_ANY_RTL:
23056                case TEXT_DIRECTION_LTR:
23057                case TEXT_DIRECTION_RTL:
23058                case TEXT_DIRECTION_LOCALE:
23059                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23060                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23061                    // Resolved direction is the same as text direction
23062                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23063                    break;
23064                default:
23065                    // Default resolved direction is "first strong" heuristic
23066                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23067            }
23068        } else {
23069            // Default resolved direction is "first strong" heuristic
23070            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23071        }
23072
23073        // Set to resolved
23074        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23075        return true;
23076    }
23077
23078    /**
23079     * Check if text direction resolution can be done.
23080     *
23081     * @return true if text direction resolution can be done otherwise return false.
23082     */
23083    public boolean canResolveTextDirection() {
23084        switch (getRawTextDirection()) {
23085            case TEXT_DIRECTION_INHERIT:
23086                if (mParent != null) {
23087                    try {
23088                        return mParent.canResolveTextDirection();
23089                    } catch (AbstractMethodError e) {
23090                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23091                                " does not fully implement ViewParent", e);
23092                    }
23093                }
23094                return false;
23095
23096            default:
23097                return true;
23098        }
23099    }
23100
23101    /**
23102     * Reset resolved text direction. Text direction will be resolved during a call to
23103     * {@link #onMeasure(int, int)}.
23104     *
23105     * @hide
23106     */
23107    public void resetResolvedTextDirection() {
23108        // Reset any previous text direction resolution
23109        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23110        // Set to default value
23111        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23112    }
23113
23114    /**
23115     * @return true if text direction is inherited.
23116     *
23117     * @hide
23118     */
23119    public boolean isTextDirectionInherited() {
23120        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23121    }
23122
23123    /**
23124     * @return true if text direction is resolved.
23125     */
23126    public boolean isTextDirectionResolved() {
23127        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23128    }
23129
23130    /**
23131     * Return the value specifying the text alignment or policy that was set with
23132     * {@link #setTextAlignment(int)}.
23133     *
23134     * @return the defined text alignment. It can be one of:
23135     *
23136     * {@link #TEXT_ALIGNMENT_INHERIT},
23137     * {@link #TEXT_ALIGNMENT_GRAVITY},
23138     * {@link #TEXT_ALIGNMENT_CENTER},
23139     * {@link #TEXT_ALIGNMENT_TEXT_START},
23140     * {@link #TEXT_ALIGNMENT_TEXT_END},
23141     * {@link #TEXT_ALIGNMENT_VIEW_START},
23142     * {@link #TEXT_ALIGNMENT_VIEW_END}
23143     *
23144     * @attr ref android.R.styleable#View_textAlignment
23145     *
23146     * @hide
23147     */
23148    @ViewDebug.ExportedProperty(category = "text", mapping = {
23149            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23150            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23151            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23152            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23153            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23154            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23155            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23156    })
23157    @TextAlignment
23158    public int getRawTextAlignment() {
23159        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23160    }
23161
23162    /**
23163     * Set the text alignment.
23164     *
23165     * @param textAlignment The text alignment to set. Should be one of
23166     *
23167     * {@link #TEXT_ALIGNMENT_INHERIT},
23168     * {@link #TEXT_ALIGNMENT_GRAVITY},
23169     * {@link #TEXT_ALIGNMENT_CENTER},
23170     * {@link #TEXT_ALIGNMENT_TEXT_START},
23171     * {@link #TEXT_ALIGNMENT_TEXT_END},
23172     * {@link #TEXT_ALIGNMENT_VIEW_START},
23173     * {@link #TEXT_ALIGNMENT_VIEW_END}
23174     *
23175     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23176     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23177     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23178     *
23179     * @attr ref android.R.styleable#View_textAlignment
23180     */
23181    public void setTextAlignment(@TextAlignment int textAlignment) {
23182        if (textAlignment != getRawTextAlignment()) {
23183            // Reset the current and resolved text alignment
23184            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23185            resetResolvedTextAlignment();
23186            // Set the new text alignment
23187            mPrivateFlags2 |=
23188                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23189            // Do resolution
23190            resolveTextAlignment();
23191            // Notify change
23192            onRtlPropertiesChanged(getLayoutDirection());
23193            // Refresh
23194            requestLayout();
23195            invalidate(true);
23196        }
23197    }
23198
23199    /**
23200     * Return the resolved text alignment.
23201     *
23202     * @return the resolved text alignment. Returns one of:
23203     *
23204     * {@link #TEXT_ALIGNMENT_GRAVITY},
23205     * {@link #TEXT_ALIGNMENT_CENTER},
23206     * {@link #TEXT_ALIGNMENT_TEXT_START},
23207     * {@link #TEXT_ALIGNMENT_TEXT_END},
23208     * {@link #TEXT_ALIGNMENT_VIEW_START},
23209     * {@link #TEXT_ALIGNMENT_VIEW_END}
23210     *
23211     * @attr ref android.R.styleable#View_textAlignment
23212     */
23213    @ViewDebug.ExportedProperty(category = "text", mapping = {
23214            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23215            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23216            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23217            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23218            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23219            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23220            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23221    })
23222    @TextAlignment
23223    public int getTextAlignment() {
23224        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23225                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23226    }
23227
23228    /**
23229     * Resolve the text alignment.
23230     *
23231     * @return true if resolution has been done, false otherwise.
23232     *
23233     * @hide
23234     */
23235    public boolean resolveTextAlignment() {
23236        // Reset any previous text alignment resolution
23237        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23238
23239        if (hasRtlSupport()) {
23240            // Set resolved text alignment flag depending on text alignment flag
23241            final int textAlignment = getRawTextAlignment();
23242            switch (textAlignment) {
23243                case TEXT_ALIGNMENT_INHERIT:
23244                    // Check if we can resolve the text alignment
23245                    if (!canResolveTextAlignment()) {
23246                        // We cannot do the resolution if there is no parent so use the default
23247                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23248                        // Resolution will need to happen again later
23249                        return false;
23250                    }
23251
23252                    // Parent has not yet resolved, so we still return the default
23253                    try {
23254                        if (!mParent.isTextAlignmentResolved()) {
23255                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23256                            // Resolution will need to happen again later
23257                            return false;
23258                        }
23259                    } catch (AbstractMethodError e) {
23260                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23261                                " does not fully implement ViewParent", e);
23262                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23263                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23264                        return true;
23265                    }
23266
23267                    int parentResolvedTextAlignment;
23268                    try {
23269                        parentResolvedTextAlignment = mParent.getTextAlignment();
23270                    } catch (AbstractMethodError e) {
23271                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23272                                " does not fully implement ViewParent", e);
23273                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23274                    }
23275                    switch (parentResolvedTextAlignment) {
23276                        case TEXT_ALIGNMENT_GRAVITY:
23277                        case TEXT_ALIGNMENT_TEXT_START:
23278                        case TEXT_ALIGNMENT_TEXT_END:
23279                        case TEXT_ALIGNMENT_CENTER:
23280                        case TEXT_ALIGNMENT_VIEW_START:
23281                        case TEXT_ALIGNMENT_VIEW_END:
23282                            // Resolved text alignment is the same as the parent resolved
23283                            // text alignment
23284                            mPrivateFlags2 |=
23285                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23286                            break;
23287                        default:
23288                            // Use default resolved text alignment
23289                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23290                    }
23291                    break;
23292                case TEXT_ALIGNMENT_GRAVITY:
23293                case TEXT_ALIGNMENT_TEXT_START:
23294                case TEXT_ALIGNMENT_TEXT_END:
23295                case TEXT_ALIGNMENT_CENTER:
23296                case TEXT_ALIGNMENT_VIEW_START:
23297                case TEXT_ALIGNMENT_VIEW_END:
23298                    // Resolved text alignment is the same as text alignment
23299                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23300                    break;
23301                default:
23302                    // Use default resolved text alignment
23303                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23304            }
23305        } else {
23306            // Use default resolved text alignment
23307            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23308        }
23309
23310        // Set the resolved
23311        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23312        return true;
23313    }
23314
23315    /**
23316     * Check if text alignment resolution can be done.
23317     *
23318     * @return true if text alignment resolution can be done otherwise return false.
23319     */
23320    public boolean canResolveTextAlignment() {
23321        switch (getRawTextAlignment()) {
23322            case TEXT_DIRECTION_INHERIT:
23323                if (mParent != null) {
23324                    try {
23325                        return mParent.canResolveTextAlignment();
23326                    } catch (AbstractMethodError e) {
23327                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23328                                " does not fully implement ViewParent", e);
23329                    }
23330                }
23331                return false;
23332
23333            default:
23334                return true;
23335        }
23336    }
23337
23338    /**
23339     * Reset resolved text alignment. Text alignment will be resolved during a call to
23340     * {@link #onMeasure(int, int)}.
23341     *
23342     * @hide
23343     */
23344    public void resetResolvedTextAlignment() {
23345        // Reset any previous text alignment resolution
23346        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23347        // Set to default
23348        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23349    }
23350
23351    /**
23352     * @return true if text alignment is inherited.
23353     *
23354     * @hide
23355     */
23356    public boolean isTextAlignmentInherited() {
23357        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23358    }
23359
23360    /**
23361     * @return true if text alignment is resolved.
23362     */
23363    public boolean isTextAlignmentResolved() {
23364        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23365    }
23366
23367    /**
23368     * Generate a value suitable for use in {@link #setId(int)}.
23369     * This value will not collide with ID values generated at build time by aapt for R.id.
23370     *
23371     * @return a generated ID value
23372     */
23373    public static int generateViewId() {
23374        for (;;) {
23375            final int result = sNextGeneratedId.get();
23376            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23377            int newValue = result + 1;
23378            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23379            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23380                return result;
23381            }
23382        }
23383    }
23384
23385    private static boolean isViewIdGenerated(int id) {
23386        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23387    }
23388
23389    /**
23390     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23391     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23392     *                           a normal View or a ViewGroup with
23393     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23394     * @hide
23395     */
23396    public void captureTransitioningViews(List<View> transitioningViews) {
23397        if (getVisibility() == View.VISIBLE) {
23398            transitioningViews.add(this);
23399        }
23400    }
23401
23402    /**
23403     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23404     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23405     * @hide
23406     */
23407    public void findNamedViews(Map<String, View> namedElements) {
23408        if (getVisibility() == VISIBLE || mGhostView != null) {
23409            String transitionName = getTransitionName();
23410            if (transitionName != null) {
23411                namedElements.put(transitionName, this);
23412            }
23413        }
23414    }
23415
23416    /**
23417     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23418     * The default implementation does not care the location or event types, but some subclasses
23419     * may use it (such as WebViews).
23420     * @param event The MotionEvent from a mouse
23421     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23422     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23423     * @see PointerIcon
23424     */
23425    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23426        final float x = event.getX(pointerIndex);
23427        final float y = event.getY(pointerIndex);
23428        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23429            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23430        }
23431        return mPointerIcon;
23432    }
23433
23434    /**
23435     * Set the pointer icon for the current view.
23436     * Passing {@code null} will restore the pointer icon to its default value.
23437     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23438     */
23439    public void setPointerIcon(PointerIcon pointerIcon) {
23440        mPointerIcon = pointerIcon;
23441        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23442            return;
23443        }
23444        try {
23445            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23446        } catch (RemoteException e) {
23447        }
23448    }
23449
23450    /**
23451     * Gets the pointer icon for the current view.
23452     */
23453    public PointerIcon getPointerIcon() {
23454        return mPointerIcon;
23455    }
23456
23457    /**
23458     * Checks pointer capture status.
23459     *
23460     * @return true if the view has pointer capture.
23461     * @see #requestPointerCapture()
23462     * @see #hasPointerCapture()
23463     */
23464    public boolean hasPointerCapture() {
23465        final ViewRootImpl viewRootImpl = getViewRootImpl();
23466        if (viewRootImpl == null) {
23467            return false;
23468        }
23469        return viewRootImpl.hasPointerCapture();
23470    }
23471
23472    /**
23473     * Requests pointer capture mode.
23474     * <p>
23475     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23476     * change its position. Further mouse will be dispatched with the source
23477     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23478     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23479     * (touchscreens, or stylus) will not be affected.
23480     * <p>
23481     * If the window already has pointer capture, this call does nothing.
23482     * <p>
23483     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23484     * automatically when the window loses focus.
23485     *
23486     * @see #releasePointerCapture()
23487     * @see #hasPointerCapture()
23488     */
23489    public void requestPointerCapture() {
23490        final ViewRootImpl viewRootImpl = getViewRootImpl();
23491        if (viewRootImpl != null) {
23492            viewRootImpl.requestPointerCapture(true);
23493        }
23494    }
23495
23496
23497    /**
23498     * Releases the pointer capture.
23499     * <p>
23500     * If the window does not have pointer capture, this call will do nothing.
23501     * @see #requestPointerCapture()
23502     * @see #hasPointerCapture()
23503     */
23504    public void releasePointerCapture() {
23505        final ViewRootImpl viewRootImpl = getViewRootImpl();
23506        if (viewRootImpl != null) {
23507            viewRootImpl.requestPointerCapture(false);
23508        }
23509    }
23510
23511    /**
23512     * Called when the window has just acquired or lost pointer capture.
23513     *
23514     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23515     */
23516    @CallSuper
23517    public void onPointerCaptureChange(boolean hasCapture) {
23518    }
23519
23520    /**
23521     * @see #onPointerCaptureChange
23522     */
23523    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23524        onPointerCaptureChange(hasCapture);
23525    }
23526
23527    /**
23528     * Implement this method to handle captured pointer events
23529     *
23530     * @param event The captured pointer event.
23531     * @return True if the event was handled, false otherwise.
23532     * @see #requestPointerCapture()
23533     */
23534    public boolean onCapturedPointerEvent(MotionEvent event) {
23535        return false;
23536    }
23537
23538    /**
23539     * Interface definition for a callback to be invoked when a captured pointer event
23540     * is being dispatched this view. The callback will be invoked before the event is
23541     * given to the view.
23542     */
23543    public interface OnCapturedPointerListener {
23544        /**
23545         * Called when a captured pointer event is dispatched to a view.
23546         * @param view The view this event has been dispatched to.
23547         * @param event The captured event.
23548         * @return True if the listener has consumed the event, false otherwise.
23549         */
23550        boolean onCapturedPointer(View view, MotionEvent event);
23551    }
23552
23553    /**
23554     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23555     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23556     */
23557    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23558        getListenerInfo().mOnCapturedPointerListener = l;
23559    }
23560
23561    // Properties
23562    //
23563    /**
23564     * A Property wrapper around the <code>alpha</code> functionality handled by the
23565     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23566     */
23567    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23568        @Override
23569        public void setValue(View object, float value) {
23570            object.setAlpha(value);
23571        }
23572
23573        @Override
23574        public Float get(View object) {
23575            return object.getAlpha();
23576        }
23577    };
23578
23579    /**
23580     * A Property wrapper around the <code>translationX</code> functionality handled by the
23581     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23582     */
23583    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23584        @Override
23585        public void setValue(View object, float value) {
23586            object.setTranslationX(value);
23587        }
23588
23589                @Override
23590        public Float get(View object) {
23591            return object.getTranslationX();
23592        }
23593    };
23594
23595    /**
23596     * A Property wrapper around the <code>translationY</code> functionality handled by the
23597     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23598     */
23599    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23600        @Override
23601        public void setValue(View object, float value) {
23602            object.setTranslationY(value);
23603        }
23604
23605        @Override
23606        public Float get(View object) {
23607            return object.getTranslationY();
23608        }
23609    };
23610
23611    /**
23612     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23613     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23614     */
23615    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23616        @Override
23617        public void setValue(View object, float value) {
23618            object.setTranslationZ(value);
23619        }
23620
23621        @Override
23622        public Float get(View object) {
23623            return object.getTranslationZ();
23624        }
23625    };
23626
23627    /**
23628     * A Property wrapper around the <code>x</code> functionality handled by the
23629     * {@link View#setX(float)} and {@link View#getX()} methods.
23630     */
23631    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23632        @Override
23633        public void setValue(View object, float value) {
23634            object.setX(value);
23635        }
23636
23637        @Override
23638        public Float get(View object) {
23639            return object.getX();
23640        }
23641    };
23642
23643    /**
23644     * A Property wrapper around the <code>y</code> functionality handled by the
23645     * {@link View#setY(float)} and {@link View#getY()} methods.
23646     */
23647    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23648        @Override
23649        public void setValue(View object, float value) {
23650            object.setY(value);
23651        }
23652
23653        @Override
23654        public Float get(View object) {
23655            return object.getY();
23656        }
23657    };
23658
23659    /**
23660     * A Property wrapper around the <code>z</code> functionality handled by the
23661     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23662     */
23663    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23664        @Override
23665        public void setValue(View object, float value) {
23666            object.setZ(value);
23667        }
23668
23669        @Override
23670        public Float get(View object) {
23671            return object.getZ();
23672        }
23673    };
23674
23675    /**
23676     * A Property wrapper around the <code>rotation</code> functionality handled by the
23677     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23678     */
23679    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23680        @Override
23681        public void setValue(View object, float value) {
23682            object.setRotation(value);
23683        }
23684
23685        @Override
23686        public Float get(View object) {
23687            return object.getRotation();
23688        }
23689    };
23690
23691    /**
23692     * A Property wrapper around the <code>rotationX</code> functionality handled by the
23693     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
23694     */
23695    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
23696        @Override
23697        public void setValue(View object, float value) {
23698            object.setRotationX(value);
23699        }
23700
23701        @Override
23702        public Float get(View object) {
23703            return object.getRotationX();
23704        }
23705    };
23706
23707    /**
23708     * A Property wrapper around the <code>rotationY</code> functionality handled by the
23709     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
23710     */
23711    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
23712        @Override
23713        public void setValue(View object, float value) {
23714            object.setRotationY(value);
23715        }
23716
23717        @Override
23718        public Float get(View object) {
23719            return object.getRotationY();
23720        }
23721    };
23722
23723    /**
23724     * A Property wrapper around the <code>scaleX</code> functionality handled by the
23725     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
23726     */
23727    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
23728        @Override
23729        public void setValue(View object, float value) {
23730            object.setScaleX(value);
23731        }
23732
23733        @Override
23734        public Float get(View object) {
23735            return object.getScaleX();
23736        }
23737    };
23738
23739    /**
23740     * A Property wrapper around the <code>scaleY</code> functionality handled by the
23741     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
23742     */
23743    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
23744        @Override
23745        public void setValue(View object, float value) {
23746            object.setScaleY(value);
23747        }
23748
23749        @Override
23750        public Float get(View object) {
23751            return object.getScaleY();
23752        }
23753    };
23754
23755    /**
23756     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
23757     * Each MeasureSpec represents a requirement for either the width or the height.
23758     * A MeasureSpec is comprised of a size and a mode. There are three possible
23759     * modes:
23760     * <dl>
23761     * <dt>UNSPECIFIED</dt>
23762     * <dd>
23763     * The parent has not imposed any constraint on the child. It can be whatever size
23764     * it wants.
23765     * </dd>
23766     *
23767     * <dt>EXACTLY</dt>
23768     * <dd>
23769     * The parent has determined an exact size for the child. The child is going to be
23770     * given those bounds regardless of how big it wants to be.
23771     * </dd>
23772     *
23773     * <dt>AT_MOST</dt>
23774     * <dd>
23775     * The child can be as large as it wants up to the specified size.
23776     * </dd>
23777     * </dl>
23778     *
23779     * MeasureSpecs are implemented as ints to reduce object allocation. This class
23780     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
23781     */
23782    public static class MeasureSpec {
23783        private static final int MODE_SHIFT = 30;
23784        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
23785
23786        /** @hide */
23787        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
23788        @Retention(RetentionPolicy.SOURCE)
23789        public @interface MeasureSpecMode {}
23790
23791        /**
23792         * Measure specification mode: The parent has not imposed any constraint
23793         * on the child. It can be whatever size it wants.
23794         */
23795        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
23796
23797        /**
23798         * Measure specification mode: The parent has determined an exact size
23799         * for the child. The child is going to be given those bounds regardless
23800         * of how big it wants to be.
23801         */
23802        public static final int EXACTLY     = 1 << MODE_SHIFT;
23803
23804        /**
23805         * Measure specification mode: The child can be as large as it wants up
23806         * to the specified size.
23807         */
23808        public static final int AT_MOST     = 2 << MODE_SHIFT;
23809
23810        /**
23811         * Creates a measure specification based on the supplied size and mode.
23812         *
23813         * The mode must always be one of the following:
23814         * <ul>
23815         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
23816         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
23817         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
23818         * </ul>
23819         *
23820         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
23821         * implementation was such that the order of arguments did not matter
23822         * and overflow in either value could impact the resulting MeasureSpec.
23823         * {@link android.widget.RelativeLayout} was affected by this bug.
23824         * Apps targeting API levels greater than 17 will get the fixed, more strict
23825         * behavior.</p>
23826         *
23827         * @param size the size of the measure specification
23828         * @param mode the mode of the measure specification
23829         * @return the measure specification based on size and mode
23830         */
23831        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
23832                                          @MeasureSpecMode int mode) {
23833            if (sUseBrokenMakeMeasureSpec) {
23834                return size + mode;
23835            } else {
23836                return (size & ~MODE_MASK) | (mode & MODE_MASK);
23837            }
23838        }
23839
23840        /**
23841         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
23842         * will automatically get a size of 0. Older apps expect this.
23843         *
23844         * @hide internal use only for compatibility with system widgets and older apps
23845         */
23846        public static int makeSafeMeasureSpec(int size, int mode) {
23847            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
23848                return 0;
23849            }
23850            return makeMeasureSpec(size, mode);
23851        }
23852
23853        /**
23854         * Extracts the mode from the supplied measure specification.
23855         *
23856         * @param measureSpec the measure specification to extract the mode from
23857         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
23858         *         {@link android.view.View.MeasureSpec#AT_MOST} or
23859         *         {@link android.view.View.MeasureSpec#EXACTLY}
23860         */
23861        @MeasureSpecMode
23862        public static int getMode(int measureSpec) {
23863            //noinspection ResourceType
23864            return (measureSpec & MODE_MASK);
23865        }
23866
23867        /**
23868         * Extracts the size from the supplied measure specification.
23869         *
23870         * @param measureSpec the measure specification to extract the size from
23871         * @return the size in pixels defined in the supplied measure specification
23872         */
23873        public static int getSize(int measureSpec) {
23874            return (measureSpec & ~MODE_MASK);
23875        }
23876
23877        static int adjust(int measureSpec, int delta) {
23878            final int mode = getMode(measureSpec);
23879            int size = getSize(measureSpec);
23880            if (mode == UNSPECIFIED) {
23881                // No need to adjust size for UNSPECIFIED mode.
23882                return makeMeasureSpec(size, UNSPECIFIED);
23883            }
23884            size += delta;
23885            if (size < 0) {
23886                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
23887                        ") spec: " + toString(measureSpec) + " delta: " + delta);
23888                size = 0;
23889            }
23890            return makeMeasureSpec(size, mode);
23891        }
23892
23893        /**
23894         * Returns a String representation of the specified measure
23895         * specification.
23896         *
23897         * @param measureSpec the measure specification to convert to a String
23898         * @return a String with the following format: "MeasureSpec: MODE SIZE"
23899         */
23900        public static String toString(int measureSpec) {
23901            int mode = getMode(measureSpec);
23902            int size = getSize(measureSpec);
23903
23904            StringBuilder sb = new StringBuilder("MeasureSpec: ");
23905
23906            if (mode == UNSPECIFIED)
23907                sb.append("UNSPECIFIED ");
23908            else if (mode == EXACTLY)
23909                sb.append("EXACTLY ");
23910            else if (mode == AT_MOST)
23911                sb.append("AT_MOST ");
23912            else
23913                sb.append(mode).append(" ");
23914
23915            sb.append(size);
23916            return sb.toString();
23917        }
23918    }
23919
23920    private final class CheckForLongPress implements Runnable {
23921        private int mOriginalWindowAttachCount;
23922        private float mX;
23923        private float mY;
23924        private boolean mOriginalPressedState;
23925
23926        @Override
23927        public void run() {
23928            if ((mOriginalPressedState == isPressed()) && (mParent != null)
23929                    && mOriginalWindowAttachCount == mWindowAttachCount) {
23930                if (performLongClick(mX, mY)) {
23931                    mHasPerformedLongPress = true;
23932                }
23933            }
23934        }
23935
23936        public void setAnchor(float x, float y) {
23937            mX = x;
23938            mY = y;
23939        }
23940
23941        public void rememberWindowAttachCount() {
23942            mOriginalWindowAttachCount = mWindowAttachCount;
23943        }
23944
23945        public void rememberPressedState() {
23946            mOriginalPressedState = isPressed();
23947        }
23948    }
23949
23950    private final class CheckForTap implements Runnable {
23951        public float x;
23952        public float y;
23953
23954        @Override
23955        public void run() {
23956            mPrivateFlags &= ~PFLAG_PREPRESSED;
23957            setPressed(true, x, y);
23958            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
23959        }
23960    }
23961
23962    private final class PerformClick implements Runnable {
23963        @Override
23964        public void run() {
23965            performClick();
23966        }
23967    }
23968
23969    /**
23970     * This method returns a ViewPropertyAnimator object, which can be used to animate
23971     * specific properties on this View.
23972     *
23973     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
23974     */
23975    public ViewPropertyAnimator animate() {
23976        if (mAnimator == null) {
23977            mAnimator = new ViewPropertyAnimator(this);
23978        }
23979        return mAnimator;
23980    }
23981
23982    /**
23983     * Sets the name of the View to be used to identify Views in Transitions.
23984     * Names should be unique in the View hierarchy.
23985     *
23986     * @param transitionName The name of the View to uniquely identify it for Transitions.
23987     */
23988    public final void setTransitionName(String transitionName) {
23989        mTransitionName = transitionName;
23990    }
23991
23992    /**
23993     * Returns the name of the View to be used to identify Views in Transitions.
23994     * Names should be unique in the View hierarchy.
23995     *
23996     * <p>This returns null if the View has not been given a name.</p>
23997     *
23998     * @return The name used of the View to be used to identify Views in Transitions or null
23999     * if no name has been given.
24000     */
24001    @ViewDebug.ExportedProperty
24002    public String getTransitionName() {
24003        return mTransitionName;
24004    }
24005
24006    /**
24007     * @hide
24008     */
24009    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24010        // Do nothing.
24011    }
24012
24013    /**
24014     * Interface definition for a callback to be invoked when a hardware key event is
24015     * dispatched to this view. The callback will be invoked before the key event is
24016     * given to the view. This is only useful for hardware keyboards; a software input
24017     * method has no obligation to trigger this listener.
24018     */
24019    public interface OnKeyListener {
24020        /**
24021         * Called when a hardware key is dispatched to a view. This allows listeners to
24022         * get a chance to respond before the target view.
24023         * <p>Key presses in software keyboards will generally NOT trigger this method,
24024         * although some may elect to do so in some situations. Do not assume a
24025         * software input method has to be key-based; even if it is, it may use key presses
24026         * in a different way than you expect, so there is no way to reliably catch soft
24027         * input key presses.
24028         *
24029         * @param v The view the key has been dispatched to.
24030         * @param keyCode The code for the physical key that was pressed
24031         * @param event The KeyEvent object containing full information about
24032         *        the event.
24033         * @return True if the listener has consumed the event, false otherwise.
24034         */
24035        boolean onKey(View v, int keyCode, KeyEvent event);
24036    }
24037
24038    /**
24039     * Interface definition for a callback to be invoked when a touch event is
24040     * dispatched to this view. The callback will be invoked before the touch
24041     * event is given to the view.
24042     */
24043    public interface OnTouchListener {
24044        /**
24045         * Called when a touch event is dispatched to a view. This allows listeners to
24046         * get a chance to respond before the target view.
24047         *
24048         * @param v The view the touch event has been dispatched to.
24049         * @param event The MotionEvent object containing full information about
24050         *        the event.
24051         * @return True if the listener has consumed the event, false otherwise.
24052         */
24053        boolean onTouch(View v, MotionEvent event);
24054    }
24055
24056    /**
24057     * Interface definition for a callback to be invoked when a hover event is
24058     * dispatched to this view. The callback will be invoked before the hover
24059     * event is given to the view.
24060     */
24061    public interface OnHoverListener {
24062        /**
24063         * Called when a hover event is dispatched to a view. This allows listeners to
24064         * get a chance to respond before the target view.
24065         *
24066         * @param v The view the hover event has been dispatched to.
24067         * @param event The MotionEvent object containing full information about
24068         *        the event.
24069         * @return True if the listener has consumed the event, false otherwise.
24070         */
24071        boolean onHover(View v, MotionEvent event);
24072    }
24073
24074    /**
24075     * Interface definition for a callback to be invoked when a generic motion event is
24076     * dispatched to this view. The callback will be invoked before the generic motion
24077     * event is given to the view.
24078     */
24079    public interface OnGenericMotionListener {
24080        /**
24081         * Called when a generic motion event is dispatched to a view. This allows listeners to
24082         * get a chance to respond before the target view.
24083         *
24084         * @param v The view the generic motion event has been dispatched to.
24085         * @param event The MotionEvent object containing full information about
24086         *        the event.
24087         * @return True if the listener has consumed the event, false otherwise.
24088         */
24089        boolean onGenericMotion(View v, MotionEvent event);
24090    }
24091
24092    /**
24093     * Interface definition for a callback to be invoked when a view has been clicked and held.
24094     */
24095    public interface OnLongClickListener {
24096        /**
24097         * Called when a view has been clicked and held.
24098         *
24099         * @param v The view that was clicked and held.
24100         *
24101         * @return true if the callback consumed the long click, false otherwise.
24102         */
24103        boolean onLongClick(View v);
24104    }
24105
24106    /**
24107     * Interface definition for a callback to be invoked when a drag is being dispatched
24108     * to this view.  The callback will be invoked before the hosting view's own
24109     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24110     * onDrag(event) behavior, it should return 'false' from this callback.
24111     *
24112     * <div class="special reference">
24113     * <h3>Developer Guides</h3>
24114     * <p>For a guide to implementing drag and drop features, read the
24115     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24116     * </div>
24117     */
24118    public interface OnDragListener {
24119        /**
24120         * Called when a drag event is dispatched to a view. This allows listeners
24121         * to get a chance to override base View behavior.
24122         *
24123         * @param v The View that received the drag event.
24124         * @param event The {@link android.view.DragEvent} object for the drag event.
24125         * @return {@code true} if the drag event was handled successfully, or {@code false}
24126         * if the drag event was not handled. Note that {@code false} will trigger the View
24127         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24128         */
24129        boolean onDrag(View v, DragEvent event);
24130    }
24131
24132    /**
24133     * Interface definition for a callback to be invoked when the focus state of
24134     * a view changed.
24135     */
24136    public interface OnFocusChangeListener {
24137        /**
24138         * Called when the focus state of a view has changed.
24139         *
24140         * @param v The view whose state has changed.
24141         * @param hasFocus The new focus state of v.
24142         */
24143        void onFocusChange(View v, boolean hasFocus);
24144    }
24145
24146    /**
24147     * Interface definition for a callback to be invoked when a view is clicked.
24148     */
24149    public interface OnClickListener {
24150        /**
24151         * Called when a view has been clicked.
24152         *
24153         * @param v The view that was clicked.
24154         */
24155        void onClick(View v);
24156    }
24157
24158    /**
24159     * Interface definition for a callback to be invoked when a view is context clicked.
24160     */
24161    public interface OnContextClickListener {
24162        /**
24163         * Called when a view is context clicked.
24164         *
24165         * @param v The view that has been context clicked.
24166         * @return true if the callback consumed the context click, false otherwise.
24167         */
24168        boolean onContextClick(View v);
24169    }
24170
24171    /**
24172     * Interface definition for a callback to be invoked when the context menu
24173     * for this view is being built.
24174     */
24175    public interface OnCreateContextMenuListener {
24176        /**
24177         * Called when the context menu for this view is being built. It is not
24178         * safe to hold onto the menu after this method returns.
24179         *
24180         * @param menu The context menu that is being built
24181         * @param v The view for which the context menu is being built
24182         * @param menuInfo Extra information about the item for which the
24183         *            context menu should be shown. This information will vary
24184         *            depending on the class of v.
24185         */
24186        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24187    }
24188
24189    /**
24190     * Interface definition for a callback to be invoked when the status bar changes
24191     * visibility.  This reports <strong>global</strong> changes to the system UI
24192     * state, not what the application is requesting.
24193     *
24194     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24195     */
24196    public interface OnSystemUiVisibilityChangeListener {
24197        /**
24198         * Called when the status bar changes visibility because of a call to
24199         * {@link View#setSystemUiVisibility(int)}.
24200         *
24201         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24202         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24203         * This tells you the <strong>global</strong> state of these UI visibility
24204         * flags, not what your app is currently applying.
24205         */
24206        public void onSystemUiVisibilityChange(int visibility);
24207    }
24208
24209    /**
24210     * Interface definition for a callback to be invoked when this view is attached
24211     * or detached from its window.
24212     */
24213    public interface OnAttachStateChangeListener {
24214        /**
24215         * Called when the view is attached to a window.
24216         * @param v The view that was attached
24217         */
24218        public void onViewAttachedToWindow(View v);
24219        /**
24220         * Called when the view is detached from a window.
24221         * @param v The view that was detached
24222         */
24223        public void onViewDetachedFromWindow(View v);
24224    }
24225
24226    /**
24227     * Listener for applying window insets on a view in a custom way.
24228     *
24229     * <p>Apps may choose to implement this interface if they want to apply custom policy
24230     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24231     * is set, its
24232     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24233     * method will be called instead of the View's own
24234     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24235     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24236     * the View's normal behavior as part of its own.</p>
24237     */
24238    public interface OnApplyWindowInsetsListener {
24239        /**
24240         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24241         * on a View, this listener method will be called instead of the view's own
24242         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24243         *
24244         * @param v The view applying window insets
24245         * @param insets The insets to apply
24246         * @return The insets supplied, minus any insets that were consumed
24247         */
24248        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24249    }
24250
24251    private final class UnsetPressedState implements Runnable {
24252        @Override
24253        public void run() {
24254            setPressed(false);
24255        }
24256    }
24257
24258    /**
24259     * Base class for derived classes that want to save and restore their own
24260     * state in {@link android.view.View#onSaveInstanceState()}.
24261     */
24262    public static class BaseSavedState extends AbsSavedState {
24263        String mStartActivityRequestWhoSaved;
24264
24265        /**
24266         * Constructor used when reading from a parcel. Reads the state of the superclass.
24267         *
24268         * @param source parcel to read from
24269         */
24270        public BaseSavedState(Parcel source) {
24271            this(source, null);
24272        }
24273
24274        /**
24275         * Constructor used when reading from a parcel using a given class loader.
24276         * Reads the state of the superclass.
24277         *
24278         * @param source parcel to read from
24279         * @param loader ClassLoader to use for reading
24280         */
24281        public BaseSavedState(Parcel source, ClassLoader loader) {
24282            super(source, loader);
24283            mStartActivityRequestWhoSaved = source.readString();
24284        }
24285
24286        /**
24287         * Constructor called by derived classes when creating their SavedState objects
24288         *
24289         * @param superState The state of the superclass of this view
24290         */
24291        public BaseSavedState(Parcelable superState) {
24292            super(superState);
24293        }
24294
24295        @Override
24296        public void writeToParcel(Parcel out, int flags) {
24297            super.writeToParcel(out, flags);
24298            out.writeString(mStartActivityRequestWhoSaved);
24299        }
24300
24301        public static final Parcelable.Creator<BaseSavedState> CREATOR
24302                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24303            @Override
24304            public BaseSavedState createFromParcel(Parcel in) {
24305                return new BaseSavedState(in);
24306            }
24307
24308            @Override
24309            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24310                return new BaseSavedState(in, loader);
24311            }
24312
24313            @Override
24314            public BaseSavedState[] newArray(int size) {
24315                return new BaseSavedState[size];
24316            }
24317        };
24318    }
24319
24320    /**
24321     * A set of information given to a view when it is attached to its parent
24322     * window.
24323     */
24324    final static class AttachInfo {
24325        interface Callbacks {
24326            void playSoundEffect(int effectId);
24327            boolean performHapticFeedback(int effectId, boolean always);
24328        }
24329
24330        /**
24331         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24332         * to a Handler. This class contains the target (View) to invalidate and
24333         * the coordinates of the dirty rectangle.
24334         *
24335         * For performance purposes, this class also implements a pool of up to
24336         * POOL_LIMIT objects that get reused. This reduces memory allocations
24337         * whenever possible.
24338         */
24339        static class InvalidateInfo {
24340            private static final int POOL_LIMIT = 10;
24341
24342            private static final SynchronizedPool<InvalidateInfo> sPool =
24343                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24344
24345            View target;
24346
24347            int left;
24348            int top;
24349            int right;
24350            int bottom;
24351
24352            public static InvalidateInfo obtain() {
24353                InvalidateInfo instance = sPool.acquire();
24354                return (instance != null) ? instance : new InvalidateInfo();
24355            }
24356
24357            public void recycle() {
24358                target = null;
24359                sPool.release(this);
24360            }
24361        }
24362
24363        final IWindowSession mSession;
24364
24365        final IWindow mWindow;
24366
24367        final IBinder mWindowToken;
24368
24369        Display mDisplay;
24370
24371        final Callbacks mRootCallbacks;
24372
24373        IWindowId mIWindowId;
24374        WindowId mWindowId;
24375
24376        /**
24377         * The top view of the hierarchy.
24378         */
24379        View mRootView;
24380
24381        IBinder mPanelParentWindowToken;
24382
24383        boolean mHardwareAccelerated;
24384        boolean mHardwareAccelerationRequested;
24385        ThreadedRenderer mThreadedRenderer;
24386        List<RenderNode> mPendingAnimatingRenderNodes;
24387
24388        /**
24389         * The state of the display to which the window is attached, as reported
24390         * by {@link Display#getState()}.  Note that the display state constants
24391         * declared by {@link Display} do not exactly line up with the screen state
24392         * constants declared by {@link View} (there are more display states than
24393         * screen states).
24394         */
24395        int mDisplayState = Display.STATE_UNKNOWN;
24396
24397        /**
24398         * Scale factor used by the compatibility mode
24399         */
24400        float mApplicationScale;
24401
24402        /**
24403         * Indicates whether the application is in compatibility mode
24404         */
24405        boolean mScalingRequired;
24406
24407        /**
24408         * Left position of this view's window
24409         */
24410        int mWindowLeft;
24411
24412        /**
24413         * Top position of this view's window
24414         */
24415        int mWindowTop;
24416
24417        /**
24418         * Indicates whether views need to use 32-bit drawing caches
24419         */
24420        boolean mUse32BitDrawingCache;
24421
24422        /**
24423         * For windows that are full-screen but using insets to layout inside
24424         * of the screen areas, these are the current insets to appear inside
24425         * the overscan area of the display.
24426         */
24427        final Rect mOverscanInsets = new Rect();
24428
24429        /**
24430         * For windows that are full-screen but using insets to layout inside
24431         * of the screen decorations, these are the current insets for the
24432         * content of the window.
24433         */
24434        final Rect mContentInsets = new Rect();
24435
24436        /**
24437         * For windows that are full-screen but using insets to layout inside
24438         * of the screen decorations, these are the current insets for the
24439         * actual visible parts of the window.
24440         */
24441        final Rect mVisibleInsets = new Rect();
24442
24443        /**
24444         * For windows that are full-screen but using insets to layout inside
24445         * of the screen decorations, these are the current insets for the
24446         * stable system windows.
24447         */
24448        final Rect mStableInsets = new Rect();
24449
24450        /**
24451         * For windows that include areas that are not covered by real surface these are the outsets
24452         * for real surface.
24453         */
24454        final Rect mOutsets = new Rect();
24455
24456        /**
24457         * In multi-window we force show the navigation bar. Because we don't want that the surface
24458         * size changes in this mode, we instead have a flag whether the navigation bar size should
24459         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24460         */
24461        boolean mAlwaysConsumeNavBar;
24462
24463        /**
24464         * The internal insets given by this window.  This value is
24465         * supplied by the client (through
24466         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24467         * be given to the window manager when changed to be used in laying
24468         * out windows behind it.
24469         */
24470        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24471                = new ViewTreeObserver.InternalInsetsInfo();
24472
24473        /**
24474         * Set to true when mGivenInternalInsets is non-empty.
24475         */
24476        boolean mHasNonEmptyGivenInternalInsets;
24477
24478        /**
24479         * All views in the window's hierarchy that serve as scroll containers,
24480         * used to determine if the window can be resized or must be panned
24481         * to adjust for a soft input area.
24482         */
24483        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24484
24485        final KeyEvent.DispatcherState mKeyDispatchState
24486                = new KeyEvent.DispatcherState();
24487
24488        /**
24489         * Indicates whether the view's window currently has the focus.
24490         */
24491        boolean mHasWindowFocus;
24492
24493        /**
24494         * The current visibility of the window.
24495         */
24496        int mWindowVisibility;
24497
24498        /**
24499         * Indicates the time at which drawing started to occur.
24500         */
24501        long mDrawingTime;
24502
24503        /**
24504         * Indicates whether or not ignoring the DIRTY_MASK flags.
24505         */
24506        boolean mIgnoreDirtyState;
24507
24508        /**
24509         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24510         * to avoid clearing that flag prematurely.
24511         */
24512        boolean mSetIgnoreDirtyState = false;
24513
24514        /**
24515         * Indicates whether the view's window is currently in touch mode.
24516         */
24517        boolean mInTouchMode;
24518
24519        /**
24520         * Indicates whether the view has requested unbuffered input dispatching for the current
24521         * event stream.
24522         */
24523        boolean mUnbufferedDispatchRequested;
24524
24525        /**
24526         * Indicates that ViewAncestor should trigger a global layout change
24527         * the next time it performs a traversal
24528         */
24529        boolean mRecomputeGlobalAttributes;
24530
24531        /**
24532         * Always report new attributes at next traversal.
24533         */
24534        boolean mForceReportNewAttributes;
24535
24536        /**
24537         * Set during a traveral if any views want to keep the screen on.
24538         */
24539        boolean mKeepScreenOn;
24540
24541        /**
24542         * Set during a traveral if the light center needs to be updated.
24543         */
24544        boolean mNeedsUpdateLightCenter;
24545
24546        /**
24547         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24548         */
24549        int mSystemUiVisibility;
24550
24551        /**
24552         * Hack to force certain system UI visibility flags to be cleared.
24553         */
24554        int mDisabledSystemUiVisibility;
24555
24556        /**
24557         * Last global system UI visibility reported by the window manager.
24558         */
24559        int mGlobalSystemUiVisibility = -1;
24560
24561        /**
24562         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24563         * attached.
24564         */
24565        boolean mHasSystemUiListeners;
24566
24567        /**
24568         * Set if the window has requested to extend into the overscan region
24569         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24570         */
24571        boolean mOverscanRequested;
24572
24573        /**
24574         * Set if the visibility of any views has changed.
24575         */
24576        boolean mViewVisibilityChanged;
24577
24578        /**
24579         * Set to true if a view has been scrolled.
24580         */
24581        boolean mViewScrollChanged;
24582
24583        /**
24584         * Set to true if high contrast mode enabled
24585         */
24586        boolean mHighContrastText;
24587
24588        /**
24589         * Set to true if a pointer event is currently being handled.
24590         */
24591        boolean mHandlingPointerEvent;
24592
24593        /**
24594         * Global to the view hierarchy used as a temporary for dealing with
24595         * x/y points in the transparent region computations.
24596         */
24597        final int[] mTransparentLocation = new int[2];
24598
24599        /**
24600         * Global to the view hierarchy used as a temporary for dealing with
24601         * x/y points in the ViewGroup.invalidateChild implementation.
24602         */
24603        final int[] mInvalidateChildLocation = new int[2];
24604
24605        /**
24606         * Global to the view hierarchy used as a temporary for dealing with
24607         * computing absolute on-screen location.
24608         */
24609        final int[] mTmpLocation = new int[2];
24610
24611        /**
24612         * Global to the view hierarchy used as a temporary for dealing with
24613         * x/y location when view is transformed.
24614         */
24615        final float[] mTmpTransformLocation = new float[2];
24616
24617        /**
24618         * The view tree observer used to dispatch global events like
24619         * layout, pre-draw, touch mode change, etc.
24620         */
24621        final ViewTreeObserver mTreeObserver;
24622
24623        /**
24624         * A Canvas used by the view hierarchy to perform bitmap caching.
24625         */
24626        Canvas mCanvas;
24627
24628        /**
24629         * The view root impl.
24630         */
24631        final ViewRootImpl mViewRootImpl;
24632
24633        /**
24634         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24635         * handler can be used to pump events in the UI events queue.
24636         */
24637        final Handler mHandler;
24638
24639        /**
24640         * Temporary for use in computing invalidate rectangles while
24641         * calling up the hierarchy.
24642         */
24643        final Rect mTmpInvalRect = new Rect();
24644
24645        /**
24646         * Temporary for use in computing hit areas with transformed views
24647         */
24648        final RectF mTmpTransformRect = new RectF();
24649
24650        /**
24651         * Temporary for use in computing hit areas with transformed views
24652         */
24653        final RectF mTmpTransformRect1 = new RectF();
24654
24655        /**
24656         * Temporary list of rectanges.
24657         */
24658        final List<RectF> mTmpRectList = new ArrayList<>();
24659
24660        /**
24661         * Temporary for use in transforming invalidation rect
24662         */
24663        final Matrix mTmpMatrix = new Matrix();
24664
24665        /**
24666         * Temporary for use in transforming invalidation rect
24667         */
24668        final Transformation mTmpTransformation = new Transformation();
24669
24670        /**
24671         * Temporary for use in querying outlines from OutlineProviders
24672         */
24673        final Outline mTmpOutline = new Outline();
24674
24675        /**
24676         * Temporary list for use in collecting focusable descendents of a view.
24677         */
24678        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
24679
24680        /**
24681         * The id of the window for accessibility purposes.
24682         */
24683        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
24684
24685        /**
24686         * Flags related to accessibility processing.
24687         *
24688         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
24689         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
24690         */
24691        int mAccessibilityFetchFlags;
24692
24693        /**
24694         * The drawable for highlighting accessibility focus.
24695         */
24696        Drawable mAccessibilityFocusDrawable;
24697
24698        /**
24699         * Show where the margins, bounds and layout bounds are for each view.
24700         */
24701        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
24702
24703        /**
24704         * Point used to compute visible regions.
24705         */
24706        final Point mPoint = new Point();
24707
24708        /**
24709         * Used to track which View originated a requestLayout() call, used when
24710         * requestLayout() is called during layout.
24711         */
24712        View mViewRequestingLayout;
24713
24714        /**
24715         * Used to track views that need (at least) a partial relayout at their current size
24716         * during the next traversal.
24717         */
24718        List<View> mPartialLayoutViews = new ArrayList<>();
24719
24720        /**
24721         * Swapped with mPartialLayoutViews during layout to avoid concurrent
24722         * modification. Lazily assigned during ViewRootImpl layout.
24723         */
24724        List<View> mEmptyPartialLayoutViews;
24725
24726        /**
24727         * Used to track the identity of the current drag operation.
24728         */
24729        IBinder mDragToken;
24730
24731        /**
24732         * The drag shadow surface for the current drag operation.
24733         */
24734        public Surface mDragSurface;
24735
24736
24737        /**
24738         * The view that currently has a tooltip displayed.
24739         */
24740        View mTooltipHost;
24741
24742        /**
24743         * Creates a new set of attachment information with the specified
24744         * events handler and thread.
24745         *
24746         * @param handler the events handler the view must use
24747         */
24748        AttachInfo(IWindowSession session, IWindow window, Display display,
24749                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
24750                Context context) {
24751            mSession = session;
24752            mWindow = window;
24753            mWindowToken = window.asBinder();
24754            mDisplay = display;
24755            mViewRootImpl = viewRootImpl;
24756            mHandler = handler;
24757            mRootCallbacks = effectPlayer;
24758            mTreeObserver = new ViewTreeObserver(context);
24759        }
24760    }
24761
24762    /**
24763     * <p>ScrollabilityCache holds various fields used by a View when scrolling
24764     * is supported. This avoids keeping too many unused fields in most
24765     * instances of View.</p>
24766     */
24767    private static class ScrollabilityCache implements Runnable {
24768
24769        /**
24770         * Scrollbars are not visible
24771         */
24772        public static final int OFF = 0;
24773
24774        /**
24775         * Scrollbars are visible
24776         */
24777        public static final int ON = 1;
24778
24779        /**
24780         * Scrollbars are fading away
24781         */
24782        public static final int FADING = 2;
24783
24784        public boolean fadeScrollBars;
24785
24786        public int fadingEdgeLength;
24787        public int scrollBarDefaultDelayBeforeFade;
24788        public int scrollBarFadeDuration;
24789
24790        public int scrollBarSize;
24791        public int scrollBarMinTouchTarget;
24792        public ScrollBarDrawable scrollBar;
24793        public float[] interpolatorValues;
24794        public View host;
24795
24796        public final Paint paint;
24797        public final Matrix matrix;
24798        public Shader shader;
24799
24800        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
24801
24802        private static final float[] OPAQUE = { 255 };
24803        private static final float[] TRANSPARENT = { 0.0f };
24804
24805        /**
24806         * When fading should start. This time moves into the future every time
24807         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
24808         */
24809        public long fadeStartTime;
24810
24811
24812        /**
24813         * The current state of the scrollbars: ON, OFF, or FADING
24814         */
24815        public int state = OFF;
24816
24817        private int mLastColor;
24818
24819        public final Rect mScrollBarBounds = new Rect();
24820        public final Rect mScrollBarTouchBounds = new Rect();
24821
24822        public static final int NOT_DRAGGING = 0;
24823        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
24824        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
24825        public int mScrollBarDraggingState = NOT_DRAGGING;
24826
24827        public float mScrollBarDraggingPos = 0;
24828
24829        public ScrollabilityCache(ViewConfiguration configuration, View host) {
24830            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
24831            scrollBarSize = configuration.getScaledScrollBarSize();
24832            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
24833            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
24834            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
24835
24836            paint = new Paint();
24837            matrix = new Matrix();
24838            // use use a height of 1, and then wack the matrix each time we
24839            // actually use it.
24840            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
24841            paint.setShader(shader);
24842            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
24843
24844            this.host = host;
24845        }
24846
24847        public void setFadeColor(int color) {
24848            if (color != mLastColor) {
24849                mLastColor = color;
24850
24851                if (color != 0) {
24852                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
24853                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
24854                    paint.setShader(shader);
24855                    // Restore the default transfer mode (src_over)
24856                    paint.setXfermode(null);
24857                } else {
24858                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
24859                    paint.setShader(shader);
24860                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
24861                }
24862            }
24863        }
24864
24865        public void run() {
24866            long now = AnimationUtils.currentAnimationTimeMillis();
24867            if (now >= fadeStartTime) {
24868
24869                // the animation fades the scrollbars out by changing
24870                // the opacity (alpha) from fully opaque to fully
24871                // transparent
24872                int nextFrame = (int) now;
24873                int framesCount = 0;
24874
24875                Interpolator interpolator = scrollBarInterpolator;
24876
24877                // Start opaque
24878                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
24879
24880                // End transparent
24881                nextFrame += scrollBarFadeDuration;
24882                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
24883
24884                state = FADING;
24885
24886                // Kick off the fade animation
24887                host.invalidate(true);
24888            }
24889        }
24890    }
24891
24892    /**
24893     * Resuable callback for sending
24894     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
24895     */
24896    private class SendViewScrolledAccessibilityEvent implements Runnable {
24897        public volatile boolean mIsPending;
24898
24899        public void run() {
24900            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
24901            mIsPending = false;
24902        }
24903    }
24904
24905    /**
24906     * <p>
24907     * This class represents a delegate that can be registered in a {@link View}
24908     * to enhance accessibility support via composition rather via inheritance.
24909     * It is specifically targeted to widget developers that extend basic View
24910     * classes i.e. classes in package android.view, that would like their
24911     * applications to be backwards compatible.
24912     * </p>
24913     * <div class="special reference">
24914     * <h3>Developer Guides</h3>
24915     * <p>For more information about making applications accessible, read the
24916     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
24917     * developer guide.</p>
24918     * </div>
24919     * <p>
24920     * A scenario in which a developer would like to use an accessibility delegate
24921     * is overriding a method introduced in a later API version than the minimal API
24922     * version supported by the application. For example, the method
24923     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
24924     * in API version 4 when the accessibility APIs were first introduced. If a
24925     * developer would like his application to run on API version 4 devices (assuming
24926     * all other APIs used by the application are version 4 or lower) and take advantage
24927     * of this method, instead of overriding the method which would break the application's
24928     * backwards compatibility, he can override the corresponding method in this
24929     * delegate and register the delegate in the target View if the API version of
24930     * the system is high enough, i.e. the API version is the same as or higher than the API
24931     * version that introduced
24932     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
24933     * </p>
24934     * <p>
24935     * Here is an example implementation:
24936     * </p>
24937     * <code><pre><p>
24938     * if (Build.VERSION.SDK_INT >= 14) {
24939     *     // If the API version is equal of higher than the version in
24940     *     // which onInitializeAccessibilityNodeInfo was introduced we
24941     *     // register a delegate with a customized implementation.
24942     *     View view = findViewById(R.id.view_id);
24943     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
24944     *         public void onInitializeAccessibilityNodeInfo(View host,
24945     *                 AccessibilityNodeInfo info) {
24946     *             // Let the default implementation populate the info.
24947     *             super.onInitializeAccessibilityNodeInfo(host, info);
24948     *             // Set some other information.
24949     *             info.setEnabled(host.isEnabled());
24950     *         }
24951     *     });
24952     * }
24953     * </code></pre></p>
24954     * <p>
24955     * This delegate contains methods that correspond to the accessibility methods
24956     * in View. If a delegate has been specified the implementation in View hands
24957     * off handling to the corresponding method in this delegate. The default
24958     * implementation the delegate methods behaves exactly as the corresponding
24959     * method in View for the case of no accessibility delegate been set. Hence,
24960     * to customize the behavior of a View method, clients can override only the
24961     * corresponding delegate method without altering the behavior of the rest
24962     * accessibility related methods of the host view.
24963     * </p>
24964     * <p>
24965     * <strong>Note:</strong> On platform versions prior to
24966     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
24967     * views in the {@code android.widget.*} package are called <i>before</i>
24968     * host methods. This prevents certain properties such as class name from
24969     * being modified by overriding
24970     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
24971     * as any changes will be overwritten by the host class.
24972     * <p>
24973     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
24974     * methods are called <i>after</i> host methods, which all properties to be
24975     * modified without being overwritten by the host class.
24976     */
24977    public static class AccessibilityDelegate {
24978
24979        /**
24980         * Sends an accessibility event of the given type. If accessibility is not
24981         * enabled this method has no effect.
24982         * <p>
24983         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
24984         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
24985         * been set.
24986         * </p>
24987         *
24988         * @param host The View hosting the delegate.
24989         * @param eventType The type of the event to send.
24990         *
24991         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
24992         */
24993        public void sendAccessibilityEvent(View host, int eventType) {
24994            host.sendAccessibilityEventInternal(eventType);
24995        }
24996
24997        /**
24998         * Performs the specified accessibility action on the view. For
24999         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25000         * <p>
25001         * The default implementation behaves as
25002         * {@link View#performAccessibilityAction(int, Bundle)
25003         *  View#performAccessibilityAction(int, Bundle)} for the case of
25004         *  no accessibility delegate been set.
25005         * </p>
25006         *
25007         * @param action The action to perform.
25008         * @return Whether the action was performed.
25009         *
25010         * @see View#performAccessibilityAction(int, Bundle)
25011         *      View#performAccessibilityAction(int, Bundle)
25012         */
25013        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25014            return host.performAccessibilityActionInternal(action, args);
25015        }
25016
25017        /**
25018         * Sends an accessibility event. This method behaves exactly as
25019         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25020         * empty {@link AccessibilityEvent} and does not perform a check whether
25021         * accessibility is enabled.
25022         * <p>
25023         * The default implementation behaves as
25024         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25025         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25026         * the case of no accessibility delegate been set.
25027         * </p>
25028         *
25029         * @param host The View hosting the delegate.
25030         * @param event The event to send.
25031         *
25032         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25033         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25034         */
25035        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25036            host.sendAccessibilityEventUncheckedInternal(event);
25037        }
25038
25039        /**
25040         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25041         * to its children for adding their text content to the event.
25042         * <p>
25043         * The default implementation behaves as
25044         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25045         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25046         * the case of no accessibility delegate been set.
25047         * </p>
25048         *
25049         * @param host The View hosting the delegate.
25050         * @param event The event.
25051         * @return True if the event population was completed.
25052         *
25053         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25054         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25055         */
25056        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25057            return host.dispatchPopulateAccessibilityEventInternal(event);
25058        }
25059
25060        /**
25061         * Gives a chance to the host View to populate the accessibility event with its
25062         * text content.
25063         * <p>
25064         * The default implementation behaves as
25065         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25066         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25067         * the case of no accessibility delegate been set.
25068         * </p>
25069         *
25070         * @param host The View hosting the delegate.
25071         * @param event The accessibility event which to populate.
25072         *
25073         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25074         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25075         */
25076        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25077            host.onPopulateAccessibilityEventInternal(event);
25078        }
25079
25080        /**
25081         * Initializes an {@link AccessibilityEvent} with information about the
25082         * the host View which is the event source.
25083         * <p>
25084         * The default implementation behaves as
25085         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25086         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25087         * the case of no accessibility delegate been set.
25088         * </p>
25089         *
25090         * @param host The View hosting the delegate.
25091         * @param event The event to initialize.
25092         *
25093         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25094         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25095         */
25096        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25097            host.onInitializeAccessibilityEventInternal(event);
25098        }
25099
25100        /**
25101         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25102         * <p>
25103         * The default implementation behaves as
25104         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25105         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25106         * the case of no accessibility delegate been set.
25107         * </p>
25108         *
25109         * @param host The View hosting the delegate.
25110         * @param info The instance to initialize.
25111         *
25112         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25113         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25114         */
25115        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25116            host.onInitializeAccessibilityNodeInfoInternal(info);
25117        }
25118
25119        /**
25120         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25121         * additional data.
25122         * <p>
25123         * This method only needs to be implemented if the View offers to provide additional data.
25124         * </p>
25125         * <p>
25126         * The default implementation behaves as
25127         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25128         * the case where no accessibility delegate is set.
25129         * </p>
25130         *
25131         * @param host The View hosting the delegate. Never {@code null}.
25132         * @param info The info to which to add the extra data. Never {@code null}.
25133         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25134         *                     extra data should be added to the {@link Bundle} returned by
25135         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25136         *                     {@code null}.
25137         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25138         *                  May be {@code null} if the if the service provided no arguments.
25139         *
25140         * @see AccessibilityNodeInfo#setExtraAvailableData
25141         */
25142        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25143                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25144                @Nullable Bundle arguments) {
25145            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25146        }
25147
25148        /**
25149         * Called when a child of the host View has requested sending an
25150         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25151         * to augment the event.
25152         * <p>
25153         * The default implementation behaves as
25154         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25155         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25156         * the case of no accessibility delegate been set.
25157         * </p>
25158         *
25159         * @param host The View hosting the delegate.
25160         * @param child The child which requests sending the event.
25161         * @param event The event to be sent.
25162         * @return True if the event should be sent
25163         *
25164         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25165         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25166         */
25167        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25168                AccessibilityEvent event) {
25169            return host.onRequestSendAccessibilityEventInternal(child, event);
25170        }
25171
25172        /**
25173         * Gets the provider for managing a virtual view hierarchy rooted at this View
25174         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25175         * that explore the window content.
25176         * <p>
25177         * The default implementation behaves as
25178         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25179         * the case of no accessibility delegate been set.
25180         * </p>
25181         *
25182         * @return The provider.
25183         *
25184         * @see AccessibilityNodeProvider
25185         */
25186        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25187            return null;
25188        }
25189
25190        /**
25191         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25192         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25193         * This method is responsible for obtaining an accessibility node info from a
25194         * pool of reusable instances and calling
25195         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25196         * view to initialize the former.
25197         * <p>
25198         * <strong>Note:</strong> The client is responsible for recycling the obtained
25199         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25200         * creation.
25201         * </p>
25202         * <p>
25203         * The default implementation behaves as
25204         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25205         * the case of no accessibility delegate been set.
25206         * </p>
25207         * @return A populated {@link AccessibilityNodeInfo}.
25208         *
25209         * @see AccessibilityNodeInfo
25210         *
25211         * @hide
25212         */
25213        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25214            return host.createAccessibilityNodeInfoInternal();
25215        }
25216    }
25217
25218    private static class MatchIdPredicate implements Predicate<View> {
25219        public int mId;
25220
25221        @Override
25222        public boolean test(View view) {
25223            return (view.mID == mId);
25224        }
25225    }
25226
25227    private static class MatchLabelForPredicate implements Predicate<View> {
25228        private int mLabeledId;
25229
25230        @Override
25231        public boolean test(View view) {
25232            return (view.mLabelForId == mLabeledId);
25233        }
25234    }
25235
25236    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25237        private int mChangeTypes = 0;
25238        private boolean mPosted;
25239        private boolean mPostedWithDelay;
25240        private long mLastEventTimeMillis;
25241
25242        @Override
25243        public void run() {
25244            mPosted = false;
25245            mPostedWithDelay = false;
25246            mLastEventTimeMillis = SystemClock.uptimeMillis();
25247            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25248                final AccessibilityEvent event = AccessibilityEvent.obtain();
25249                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25250                event.setContentChangeTypes(mChangeTypes);
25251                sendAccessibilityEventUnchecked(event);
25252            }
25253            mChangeTypes = 0;
25254        }
25255
25256        public void runOrPost(int changeType) {
25257            mChangeTypes |= changeType;
25258
25259            // If this is a live region or the child of a live region, collect
25260            // all events from this frame and send them on the next frame.
25261            if (inLiveRegion()) {
25262                // If we're already posted with a delay, remove that.
25263                if (mPostedWithDelay) {
25264                    removeCallbacks(this);
25265                    mPostedWithDelay = false;
25266                }
25267                // Only post if we're not already posted.
25268                if (!mPosted) {
25269                    post(this);
25270                    mPosted = true;
25271                }
25272                return;
25273            }
25274
25275            if (mPosted) {
25276                return;
25277            }
25278
25279            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25280            final long minEventIntevalMillis =
25281                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25282            if (timeSinceLastMillis >= minEventIntevalMillis) {
25283                removeCallbacks(this);
25284                run();
25285            } else {
25286                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25287                mPostedWithDelay = true;
25288            }
25289        }
25290    }
25291
25292    private boolean inLiveRegion() {
25293        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25294            return true;
25295        }
25296
25297        ViewParent parent = getParent();
25298        while (parent instanceof View) {
25299            if (((View) parent).getAccessibilityLiveRegion()
25300                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25301                return true;
25302            }
25303            parent = parent.getParent();
25304        }
25305
25306        return false;
25307    }
25308
25309    /**
25310     * Dump all private flags in readable format, useful for documentation and
25311     * sanity checking.
25312     */
25313    private static void dumpFlags() {
25314        final HashMap<String, String> found = Maps.newHashMap();
25315        try {
25316            for (Field field : View.class.getDeclaredFields()) {
25317                final int modifiers = field.getModifiers();
25318                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25319                    if (field.getType().equals(int.class)) {
25320                        final int value = field.getInt(null);
25321                        dumpFlag(found, field.getName(), value);
25322                    } else if (field.getType().equals(int[].class)) {
25323                        final int[] values = (int[]) field.get(null);
25324                        for (int i = 0; i < values.length; i++) {
25325                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25326                        }
25327                    }
25328                }
25329            }
25330        } catch (IllegalAccessException e) {
25331            throw new RuntimeException(e);
25332        }
25333
25334        final ArrayList<String> keys = Lists.newArrayList();
25335        keys.addAll(found.keySet());
25336        Collections.sort(keys);
25337        for (String key : keys) {
25338            Log.d(VIEW_LOG_TAG, found.get(key));
25339        }
25340    }
25341
25342    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25343        // Sort flags by prefix, then by bits, always keeping unique keys
25344        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25345        final int prefix = name.indexOf('_');
25346        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25347        final String output = bits + " " + name;
25348        found.put(key, output);
25349    }
25350
25351    /** {@hide} */
25352    public void encode(@NonNull ViewHierarchyEncoder stream) {
25353        stream.beginObject(this);
25354        encodeProperties(stream);
25355        stream.endObject();
25356    }
25357
25358    /** {@hide} */
25359    @CallSuper
25360    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25361        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25362        if (resolveId instanceof String) {
25363            stream.addProperty("id", (String) resolveId);
25364        } else {
25365            stream.addProperty("id", mID);
25366        }
25367
25368        stream.addProperty("misc:transformation.alpha",
25369                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25370        stream.addProperty("misc:transitionName", getTransitionName());
25371
25372        // layout
25373        stream.addProperty("layout:left", mLeft);
25374        stream.addProperty("layout:right", mRight);
25375        stream.addProperty("layout:top", mTop);
25376        stream.addProperty("layout:bottom", mBottom);
25377        stream.addProperty("layout:width", getWidth());
25378        stream.addProperty("layout:height", getHeight());
25379        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25380        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25381        stream.addProperty("layout:hasTransientState", hasTransientState());
25382        stream.addProperty("layout:baseline", getBaseline());
25383
25384        // layout params
25385        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25386        if (layoutParams != null) {
25387            stream.addPropertyKey("layoutParams");
25388            layoutParams.encode(stream);
25389        }
25390
25391        // scrolling
25392        stream.addProperty("scrolling:scrollX", mScrollX);
25393        stream.addProperty("scrolling:scrollY", mScrollY);
25394
25395        // padding
25396        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25397        stream.addProperty("padding:paddingRight", mPaddingRight);
25398        stream.addProperty("padding:paddingTop", mPaddingTop);
25399        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25400        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25401        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25402        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25403        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25404        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25405
25406        // measurement
25407        stream.addProperty("measurement:minHeight", mMinHeight);
25408        stream.addProperty("measurement:minWidth", mMinWidth);
25409        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25410        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25411
25412        // drawing
25413        stream.addProperty("drawing:elevation", getElevation());
25414        stream.addProperty("drawing:translationX", getTranslationX());
25415        stream.addProperty("drawing:translationY", getTranslationY());
25416        stream.addProperty("drawing:translationZ", getTranslationZ());
25417        stream.addProperty("drawing:rotation", getRotation());
25418        stream.addProperty("drawing:rotationX", getRotationX());
25419        stream.addProperty("drawing:rotationY", getRotationY());
25420        stream.addProperty("drawing:scaleX", getScaleX());
25421        stream.addProperty("drawing:scaleY", getScaleY());
25422        stream.addProperty("drawing:pivotX", getPivotX());
25423        stream.addProperty("drawing:pivotY", getPivotY());
25424        stream.addProperty("drawing:opaque", isOpaque());
25425        stream.addProperty("drawing:alpha", getAlpha());
25426        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25427        stream.addProperty("drawing:shadow", hasShadow());
25428        stream.addProperty("drawing:solidColor", getSolidColor());
25429        stream.addProperty("drawing:layerType", mLayerType);
25430        stream.addProperty("drawing:willNotDraw", willNotDraw());
25431        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25432        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25433        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25434        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25435
25436        // focus
25437        stream.addProperty("focus:hasFocus", hasFocus());
25438        stream.addProperty("focus:isFocused", isFocused());
25439        stream.addProperty("focus:isFocusable", isFocusable());
25440        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25441
25442        stream.addProperty("misc:clickable", isClickable());
25443        stream.addProperty("misc:pressed", isPressed());
25444        stream.addProperty("misc:selected", isSelected());
25445        stream.addProperty("misc:touchMode", isInTouchMode());
25446        stream.addProperty("misc:hovered", isHovered());
25447        stream.addProperty("misc:activated", isActivated());
25448
25449        stream.addProperty("misc:visibility", getVisibility());
25450        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25451        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25452
25453        stream.addProperty("misc:enabled", isEnabled());
25454        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25455        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25456
25457        // theme attributes
25458        Resources.Theme theme = getContext().getTheme();
25459        if (theme != null) {
25460            stream.addPropertyKey("theme");
25461            theme.encode(stream);
25462        }
25463
25464        // view attribute information
25465        int n = mAttributes != null ? mAttributes.length : 0;
25466        stream.addProperty("meta:__attrCount__", n/2);
25467        for (int i = 0; i < n; i += 2) {
25468            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25469        }
25470
25471        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25472
25473        // text
25474        stream.addProperty("text:textDirection", getTextDirection());
25475        stream.addProperty("text:textAlignment", getTextAlignment());
25476
25477        // accessibility
25478        CharSequence contentDescription = getContentDescription();
25479        stream.addProperty("accessibility:contentDescription",
25480                contentDescription == null ? "" : contentDescription.toString());
25481        stream.addProperty("accessibility:labelFor", getLabelFor());
25482        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25483    }
25484
25485    /**
25486     * Determine if this view is rendered on a round wearable device and is the main view
25487     * on the screen.
25488     */
25489    boolean shouldDrawRoundScrollbar() {
25490        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25491            return false;
25492        }
25493
25494        final View rootView = getRootView();
25495        final WindowInsets insets = getRootWindowInsets();
25496
25497        int height = getHeight();
25498        int width = getWidth();
25499        int displayHeight = rootView.getHeight();
25500        int displayWidth = rootView.getWidth();
25501
25502        if (height != displayHeight || width != displayWidth) {
25503            return false;
25504        }
25505
25506        getLocationInWindow(mAttachInfo.mTmpLocation);
25507        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25508                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25509    }
25510
25511    /**
25512     * Sets the tooltip text which will be displayed in a small popup next to the view.
25513     * <p>
25514     * The tooltip will be displayed:
25515     * <ul>
25516     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
25517     * menu). </li>
25518     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25519     * </ul>
25520     * <p>
25521     * <strong>Note:</strong> Do not override this method, as it will have no
25522     * effect on the text displayed in the tooltip.
25523     *
25524     * @param tooltipText the tooltip text, or null if no tooltip is required
25525     * @see #getTooltipText()
25526     * @attr ref android.R.styleable#View_tooltipText
25527     */
25528    public void setTooltipText(@Nullable CharSequence tooltipText) {
25529        if (TextUtils.isEmpty(tooltipText)) {
25530            setFlags(0, TOOLTIP);
25531            hideTooltip();
25532            mTooltipInfo = null;
25533        } else {
25534            setFlags(TOOLTIP, TOOLTIP);
25535            if (mTooltipInfo == null) {
25536                mTooltipInfo = new TooltipInfo();
25537                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25538                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25539            }
25540            mTooltipInfo.mTooltipText = tooltipText;
25541            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25542                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25543            }
25544        }
25545    }
25546
25547    /**
25548     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25549     */
25550    public void setTooltip(@Nullable CharSequence tooltipText) {
25551        setTooltipText(tooltipText);
25552    }
25553
25554    /**
25555     * Returns the view's tooltip text.
25556     *
25557     * <strong>Note:</strong> Do not override this method, as it will have no
25558     * effect on the text displayed in the tooltip. You must call
25559     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25560     *
25561     * @return the tooltip text
25562     * @see #setTooltipText(CharSequence)
25563     * @attr ref android.R.styleable#View_tooltipText
25564     */
25565    @Nullable
25566    public CharSequence getTooltipText() {
25567        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25568    }
25569
25570    /**
25571     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25572     */
25573    @Nullable
25574    public CharSequence getTooltip() {
25575        return getTooltipText();
25576    }
25577
25578    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25579        if (mAttachInfo == null || mTooltipInfo == null) {
25580            return false;
25581        }
25582        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25583            return false;
25584        }
25585        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25586            return false;
25587        }
25588        hideTooltip();
25589        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25590        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25591        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25592        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25593        mAttachInfo.mTooltipHost = this;
25594        return true;
25595    }
25596
25597    void hideTooltip() {
25598        if (mTooltipInfo == null) {
25599            return;
25600        }
25601        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25602        if (mTooltipInfo.mTooltipPopup == null) {
25603            return;
25604        }
25605        mTooltipInfo.mTooltipPopup.hide();
25606        mTooltipInfo.mTooltipPopup = null;
25607        mTooltipInfo.mTooltipFromLongClick = false;
25608        if (mAttachInfo != null) {
25609            mAttachInfo.mTooltipHost = null;
25610        }
25611    }
25612
25613    private boolean showLongClickTooltip(int x, int y) {
25614        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25615        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25616        return showTooltip(x, y, true);
25617    }
25618
25619    private void showHoverTooltip() {
25620        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25621    }
25622
25623    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25624        if (mTooltipInfo == null) {
25625            return false;
25626        }
25627        switch(event.getAction()) {
25628            case MotionEvent.ACTION_HOVER_MOVE:
25629                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25630                    break;
25631                }
25632                if (!mTooltipInfo.mTooltipFromLongClick) {
25633                    if (mTooltipInfo.mTooltipPopup == null) {
25634                        // Schedule showing the tooltip after a timeout.
25635                        mTooltipInfo.mAnchorX = (int) event.getX();
25636                        mTooltipInfo.mAnchorY = (int) event.getY();
25637                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25638                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25639                                ViewConfiguration.getHoverTooltipShowTimeout());
25640                    }
25641
25642                    // Hide hover-triggered tooltip after a period of inactivity.
25643                    // Match the timeout used by NativeInputManager to hide the mouse pointer
25644                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
25645                    final int timeout;
25646                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
25647                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
25648                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
25649                    } else {
25650                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
25651                    }
25652                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25653                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
25654                }
25655                return true;
25656
25657            case MotionEvent.ACTION_HOVER_EXIT:
25658                if (!mTooltipInfo.mTooltipFromLongClick) {
25659                    hideTooltip();
25660                }
25661                break;
25662        }
25663        return false;
25664    }
25665
25666    void handleTooltipKey(KeyEvent event) {
25667        switch (event.getAction()) {
25668            case KeyEvent.ACTION_DOWN:
25669                if (event.getRepeatCount() == 0) {
25670                    hideTooltip();
25671                }
25672                break;
25673
25674            case KeyEvent.ACTION_UP:
25675                handleTooltipUp();
25676                break;
25677        }
25678    }
25679
25680    private void handleTooltipUp() {
25681        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25682            return;
25683        }
25684        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25685        postDelayed(mTooltipInfo.mHideTooltipRunnable,
25686                ViewConfiguration.getLongPressTooltipHideTimeout());
25687    }
25688
25689    private int getFocusableAttribute(TypedArray attributes) {
25690        TypedValue val = new TypedValue();
25691        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
25692            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
25693                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
25694            } else {
25695                return val.data;
25696            }
25697        } else {
25698            return FOCUSABLE_AUTO;
25699        }
25700    }
25701
25702    /**
25703     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
25704     * is not showing.
25705     * @hide
25706     */
25707    @TestApi
25708    public View getTooltipView() {
25709        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25710            return null;
25711        }
25712        return mTooltipInfo.mTooltipPopup.getContentView();
25713    }
25714}
25715