View.java revision 08cccc17227668651de1b4d4b3f504d66c7e6d37
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     *             11                    PFLAG3_AUTO_FILL_MODE_MASK
2753     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
2754     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2755     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2756     *        1                          PFLAG3_TEMPORARY_DETACH
2757     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2758     * |-------|-------|-------|-------|
2759     */
2760
2761    /**
2762     * Flag indicating that view has a transform animation set on it. This is used to track whether
2763     * an animation is cleared between successive frames, in order to tell the associated
2764     * DisplayList to clear its animation matrix.
2765     */
2766    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2767
2768    /**
2769     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2770     * animation is cleared between successive frames, in order to tell the associated
2771     * DisplayList to restore its alpha value.
2772     */
2773    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2774
2775    /**
2776     * Flag indicating that the view has been through at least one layout since it
2777     * was last attached to a window.
2778     */
2779    static final int PFLAG3_IS_LAID_OUT = 0x4;
2780
2781    /**
2782     * Flag indicating that a call to measure() was skipped and should be done
2783     * instead when layout() is invoked.
2784     */
2785    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2786
2787    /**
2788     * Flag indicating that an overridden method correctly called down to
2789     * the superclass implementation as required by the API spec.
2790     */
2791    static final int PFLAG3_CALLED_SUPER = 0x10;
2792
2793    /**
2794     * Flag indicating that we're in the process of applying window insets.
2795     */
2796    static final int PFLAG3_APPLYING_INSETS = 0x20;
2797
2798    /**
2799     * Flag indicating that we're in the process of fitting system windows using the old method.
2800     */
2801    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2802
2803    /**
2804     * Flag indicating that nested scrolling is enabled for this view.
2805     * The view will optionally cooperate with views up its parent chain to allow for
2806     * integrated nested scrolling along the same axis.
2807     */
2808    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2809
2810    /**
2811     * Flag indicating that the bottom scroll indicator should be displayed
2812     * when this view can scroll up.
2813     */
2814    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2815
2816    /**
2817     * Flag indicating that the bottom scroll indicator should be displayed
2818     * when this view can scroll down.
2819     */
2820    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2821
2822    /**
2823     * Flag indicating that the left scroll indicator should be displayed
2824     * when this view can scroll left.
2825     */
2826    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2827
2828    /**
2829     * Flag indicating that the right scroll indicator should be displayed
2830     * when this view can scroll right.
2831     */
2832    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2833
2834    /**
2835     * Flag indicating that the start scroll indicator should be displayed
2836     * when this view can scroll in the start direction.
2837     */
2838    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2839
2840    /**
2841     * Flag indicating that the end scroll indicator should be displayed
2842     * when this view can scroll in the end direction.
2843     */
2844    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2845
2846    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2847
2848    static final int SCROLL_INDICATORS_NONE = 0x0000;
2849
2850    /**
2851     * Mask for use with setFlags indicating bits used for indicating which
2852     * scroll indicators are enabled.
2853     */
2854    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2855            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2856            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2857            | PFLAG3_SCROLL_INDICATOR_END;
2858
2859    /**
2860     * Left-shift required to translate between public scroll indicator flags
2861     * and internal PFLAGS3 flags. When used as a right-shift, translates
2862     * PFLAGS3 flags to public flags.
2863     */
2864    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2865
2866    /** @hide */
2867    @Retention(RetentionPolicy.SOURCE)
2868    @IntDef(flag = true,
2869            value = {
2870                    SCROLL_INDICATOR_TOP,
2871                    SCROLL_INDICATOR_BOTTOM,
2872                    SCROLL_INDICATOR_LEFT,
2873                    SCROLL_INDICATOR_RIGHT,
2874                    SCROLL_INDICATOR_START,
2875                    SCROLL_INDICATOR_END,
2876            })
2877    public @interface ScrollIndicators {}
2878
2879    /**
2880     * Scroll indicator direction for the top edge of the view.
2881     *
2882     * @see #setScrollIndicators(int)
2883     * @see #setScrollIndicators(int, int)
2884     * @see #getScrollIndicators()
2885     */
2886    public static final int SCROLL_INDICATOR_TOP =
2887            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2888
2889    /**
2890     * Scroll indicator direction for the bottom edge of the view.
2891     *
2892     * @see #setScrollIndicators(int)
2893     * @see #setScrollIndicators(int, int)
2894     * @see #getScrollIndicators()
2895     */
2896    public static final int SCROLL_INDICATOR_BOTTOM =
2897            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2898
2899    /**
2900     * Scroll indicator direction for the left edge of the view.
2901     *
2902     * @see #setScrollIndicators(int)
2903     * @see #setScrollIndicators(int, int)
2904     * @see #getScrollIndicators()
2905     */
2906    public static final int SCROLL_INDICATOR_LEFT =
2907            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2908
2909    /**
2910     * Scroll indicator direction for the right edge of the view.
2911     *
2912     * @see #setScrollIndicators(int)
2913     * @see #setScrollIndicators(int, int)
2914     * @see #getScrollIndicators()
2915     */
2916    public static final int SCROLL_INDICATOR_RIGHT =
2917            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2918
2919    /**
2920     * Scroll indicator direction for the starting edge of the view.
2921     * <p>
2922     * Resolved according to the view's layout direction, see
2923     * {@link #getLayoutDirection()} for more information.
2924     *
2925     * @see #setScrollIndicators(int)
2926     * @see #setScrollIndicators(int, int)
2927     * @see #getScrollIndicators()
2928     */
2929    public static final int SCROLL_INDICATOR_START =
2930            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2931
2932    /**
2933     * Scroll indicator direction for the ending edge of the view.
2934     * <p>
2935     * Resolved according to the view's layout direction, see
2936     * {@link #getLayoutDirection()} for more information.
2937     *
2938     * @see #setScrollIndicators(int)
2939     * @see #setScrollIndicators(int, int)
2940     * @see #getScrollIndicators()
2941     */
2942    public static final int SCROLL_INDICATOR_END =
2943            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2944
2945    /**
2946     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2947     * into this view.<p>
2948     */
2949    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2950
2951    /**
2952     * Flag indicating that the view is a root of a keyboard navigation cluster.
2953     *
2954     * @see #isKeyboardNavigationCluster()
2955     * @see #setKeyboardNavigationCluster(boolean)
2956     */
2957    private static final int PFLAG3_CLUSTER = 0x8000;
2958
2959    /**
2960     * Indicates that the user is currently touching the screen.
2961     * Currently used for the tooltip positioning only.
2962     */
2963    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2964
2965    /**
2966     * Flag indicating that this view is the default-focus view.
2967     *
2968     * @see #isFocusedByDefault()
2969     * @see #setFocusedByDefault(boolean)
2970     */
2971    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2972
2973    /**
2974     * Shift for the place where the autofill mode is stored in the pflags
2975     *
2976     * @see #getAutofillMode()
2977     * @see #setAutofillMode(int)
2978     */
2979    private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
2980
2981    /**
2982     * Mask for autofill modes
2983     *
2984     * @see #getAutofillMode()
2985     * @see #setAutofillMode(int)
2986     */
2987    private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
2988            | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
2989
2990    /**
2991     * Shift for the bits in {@link #mPrivateFlags3} related to the
2992     * "importantForAutofill" attribute.
2993     */
2994    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
2995
2996    /**
2997     * Mask for obtaining the bits which specify how to determine
2998     * whether a view is important for autofill.
2999     */
3000    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3001            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
3002            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3003
3004    /**
3005     * Whether this view has rendered elements that overlap (see {@link
3006     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3007     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3008     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3009     * determined by whatever {@link #hasOverlappingRendering()} returns.
3010     */
3011    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3012
3013    /**
3014     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3015     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3016     */
3017    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3018
3019    /**
3020     * Flag indicating that the view is temporarily detached from the parent view.
3021     *
3022     * @see #onStartTemporaryDetach()
3023     * @see #onFinishTemporaryDetach()
3024     */
3025    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3026
3027    /**
3028     * Flag indicating that the view does not wish to be revealed within its parent
3029     * hierarchy when it gains focus. Expressed in the negative since the historical
3030     * default behavior is to reveal on focus; this flag suppresses that behavior.
3031     *
3032     * @see #setRevealOnFocusHint(boolean)
3033     * @see #getRevealOnFocusHint()
3034     */
3035    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3036
3037    /* End of masks for mPrivateFlags3 */
3038
3039    /**
3040     * Always allow a user to over-scroll this view, provided it is a
3041     * view that can scroll.
3042     *
3043     * @see #getOverScrollMode()
3044     * @see #setOverScrollMode(int)
3045     */
3046    public static final int OVER_SCROLL_ALWAYS = 0;
3047
3048    /**
3049     * Allow a user to over-scroll this view only if the content is large
3050     * enough to meaningfully scroll, provided it is a view that can scroll.
3051     *
3052     * @see #getOverScrollMode()
3053     * @see #setOverScrollMode(int)
3054     */
3055    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3056
3057    /**
3058     * Never allow a user to over-scroll this view.
3059     *
3060     * @see #getOverScrollMode()
3061     * @see #setOverScrollMode(int)
3062     */
3063    public static final int OVER_SCROLL_NEVER = 2;
3064
3065    /**
3066     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3067     * requested the system UI (status bar) to be visible (the default).
3068     *
3069     * @see #setSystemUiVisibility(int)
3070     */
3071    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3072
3073    /**
3074     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3075     * system UI to enter an unobtrusive "low profile" mode.
3076     *
3077     * <p>This is for use in games, book readers, video players, or any other
3078     * "immersive" application where the usual system chrome is deemed too distracting.
3079     *
3080     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3081     *
3082     * @see #setSystemUiVisibility(int)
3083     */
3084    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3085
3086    /**
3087     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3088     * system navigation be temporarily hidden.
3089     *
3090     * <p>This is an even less obtrusive state than that called for by
3091     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3092     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3093     * those to disappear. This is useful (in conjunction with the
3094     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3095     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3096     * window flags) for displaying content using every last pixel on the display.
3097     *
3098     * <p>There is a limitation: because navigation controls are so important, the least user
3099     * interaction will cause them to reappear immediately.  When this happens, both
3100     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3101     * so that both elements reappear at the same time.
3102     *
3103     * @see #setSystemUiVisibility(int)
3104     */
3105    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3106
3107    /**
3108     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3109     * into the normal fullscreen mode so that its content can take over the screen
3110     * while still allowing the user to interact with the application.
3111     *
3112     * <p>This has the same visual effect as
3113     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3114     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3115     * meaning that non-critical screen decorations (such as the status bar) will be
3116     * hidden while the user is in the View's window, focusing the experience on
3117     * that content.  Unlike the window flag, if you are using ActionBar in
3118     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3119     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3120     * hide the action bar.
3121     *
3122     * <p>This approach to going fullscreen is best used over the window flag when
3123     * it is a transient state -- that is, the application does this at certain
3124     * points in its user interaction where it wants to allow the user to focus
3125     * on content, but not as a continuous state.  For situations where the application
3126     * would like to simply stay full screen the entire time (such as a game that
3127     * wants to take over the screen), the
3128     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3129     * is usually a better approach.  The state set here will be removed by the system
3130     * in various situations (such as the user moving to another application) like
3131     * the other system UI states.
3132     *
3133     * <p>When using this flag, the application should provide some easy facility
3134     * for the user to go out of it.  A common example would be in an e-book
3135     * reader, where tapping on the screen brings back whatever screen and UI
3136     * decorations that had been hidden while the user was immersed in reading
3137     * the book.
3138     *
3139     * @see #setSystemUiVisibility(int)
3140     */
3141    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3142
3143    /**
3144     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3145     * flags, we would like a stable view of the content insets given to
3146     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3147     * will always represent the worst case that the application can expect
3148     * as a continuous state.  In the stock Android UI this is the space for
3149     * the system bar, nav bar, and status bar, but not more transient elements
3150     * such as an input method.
3151     *
3152     * The stable layout your UI sees is based on the system UI modes you can
3153     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3154     * then you will get a stable layout for changes of the
3155     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3156     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3157     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3158     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3159     * with a stable layout.  (Note that you should avoid using
3160     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3161     *
3162     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3163     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3164     * then a hidden status bar will be considered a "stable" state for purposes
3165     * here.  This allows your UI to continually hide the status bar, while still
3166     * using the system UI flags to hide the action bar while still retaining
3167     * a stable layout.  Note that changing the window fullscreen flag will never
3168     * provide a stable layout for a clean transition.
3169     *
3170     * <p>If you are using ActionBar in
3171     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3172     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3173     * insets it adds to those given to the application.
3174     */
3175    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3176
3177    /**
3178     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3179     * to be laid out as if it has requested
3180     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3181     * allows it to avoid artifacts when switching in and out of that mode, at
3182     * the expense that some of its user interface may be covered by screen
3183     * decorations when they are shown.  You can perform layout of your inner
3184     * UI elements to account for the navigation system UI through the
3185     * {@link #fitSystemWindows(Rect)} method.
3186     */
3187    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3188
3189    /**
3190     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3191     * to be laid out as if it has requested
3192     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3193     * allows it to avoid artifacts when switching in and out of that mode, at
3194     * the expense that some of its user interface may be covered by screen
3195     * decorations when they are shown.  You can perform layout of your inner
3196     * UI elements to account for non-fullscreen system UI through the
3197     * {@link #fitSystemWindows(Rect)} method.
3198     */
3199    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3200
3201    /**
3202     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3203     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3204     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3205     * user interaction.
3206     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3207     * has an effect when used in combination with that flag.</p>
3208     */
3209    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3210
3211    /**
3212     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3213     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3214     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3215     * experience while also hiding the system bars.  If this flag is not set,
3216     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3217     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3218     * if the user swipes from the top of the screen.
3219     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3220     * system gestures, such as swiping from the top of the screen.  These transient system bars
3221     * will overlay app’s content, may have some degree of transparency, and will automatically
3222     * hide after a short timeout.
3223     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3224     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3225     * with one or both of those flags.</p>
3226     */
3227    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3228
3229    /**
3230     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3231     * is compatible with light status bar backgrounds.
3232     *
3233     * <p>For this to take effect, the window must request
3234     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3235     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3236     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3237     *         FLAG_TRANSLUCENT_STATUS}.
3238     *
3239     * @see android.R.attr#windowLightStatusBar
3240     */
3241    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3242
3243    /**
3244     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3245     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3246     */
3247    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3248
3249    /**
3250     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3251     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3252     */
3253    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3254
3255    /**
3256     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3257     * that is compatible with light navigation bar backgrounds.
3258     *
3259     * <p>For this to take effect, the window must request
3260     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3261     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3262     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3263     *         FLAG_TRANSLUCENT_NAVIGATION}.
3264     */
3265    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3266
3267    /**
3268     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3269     */
3270    @Deprecated
3271    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3272
3273    /**
3274     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3275     */
3276    @Deprecated
3277    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3278
3279    /**
3280     * @hide
3281     *
3282     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3283     * out of the public fields to keep the undefined bits out of the developer's way.
3284     *
3285     * Flag to make the status bar not expandable.  Unless you also
3286     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3287     */
3288    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3289
3290    /**
3291     * @hide
3292     *
3293     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3294     * out of the public fields to keep the undefined bits out of the developer's way.
3295     *
3296     * Flag to hide notification icons and scrolling ticker text.
3297     */
3298    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3299
3300    /**
3301     * @hide
3302     *
3303     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3304     * out of the public fields to keep the undefined bits out of the developer's way.
3305     *
3306     * Flag to disable incoming notification alerts.  This will not block
3307     * icons, but it will block sound, vibrating and other visual or aural notifications.
3308     */
3309    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3310
3311    /**
3312     * @hide
3313     *
3314     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3315     * out of the public fields to keep the undefined bits out of the developer's way.
3316     *
3317     * Flag to hide only the scrolling ticker.  Note that
3318     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3319     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3320     */
3321    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3322
3323    /**
3324     * @hide
3325     *
3326     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3327     * out of the public fields to keep the undefined bits out of the developer's way.
3328     *
3329     * Flag to hide the center system info area.
3330     */
3331    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3332
3333    /**
3334     * @hide
3335     *
3336     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3337     * out of the public fields to keep the undefined bits out of the developer's way.
3338     *
3339     * Flag to hide only the home button.  Don't use this
3340     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3341     */
3342    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3343
3344    /**
3345     * @hide
3346     *
3347     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3348     * out of the public fields to keep the undefined bits out of the developer's way.
3349     *
3350     * Flag to hide only the back button. Don't use this
3351     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3352     */
3353    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3354
3355    /**
3356     * @hide
3357     *
3358     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3359     * out of the public fields to keep the undefined bits out of the developer's way.
3360     *
3361     * Flag to hide only the clock.  You might use this if your activity has
3362     * its own clock making the status bar's clock redundant.
3363     */
3364    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3365
3366    /**
3367     * @hide
3368     *
3369     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3370     * out of the public fields to keep the undefined bits out of the developer's way.
3371     *
3372     * Flag to hide only the recent apps button. Don't use this
3373     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3374     */
3375    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3376
3377    /**
3378     * @hide
3379     *
3380     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3381     * out of the public fields to keep the undefined bits out of the developer's way.
3382     *
3383     * Flag to disable the global search gesture. Don't use this
3384     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3385     */
3386    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3387
3388    /**
3389     * @hide
3390     *
3391     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3392     * out of the public fields to keep the undefined bits out of the developer's way.
3393     *
3394     * Flag to specify that the status bar is displayed in transient mode.
3395     */
3396    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3397
3398    /**
3399     * @hide
3400     *
3401     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3402     * out of the public fields to keep the undefined bits out of the developer's way.
3403     *
3404     * Flag to specify that the navigation bar is displayed in transient mode.
3405     */
3406    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3407
3408    /**
3409     * @hide
3410     *
3411     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3412     * out of the public fields to keep the undefined bits out of the developer's way.
3413     *
3414     * Flag to specify that the hidden status bar would like to be shown.
3415     */
3416    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3417
3418    /**
3419     * @hide
3420     *
3421     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3422     * out of the public fields to keep the undefined bits out of the developer's way.
3423     *
3424     * Flag to specify that the hidden navigation bar would like to be shown.
3425     */
3426    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3427
3428    /**
3429     * @hide
3430     *
3431     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3432     * out of the public fields to keep the undefined bits out of the developer's way.
3433     *
3434     * Flag to specify that the status bar is displayed in translucent mode.
3435     */
3436    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3437
3438    /**
3439     * @hide
3440     *
3441     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3442     * out of the public fields to keep the undefined bits out of the developer's way.
3443     *
3444     * Flag to specify that the navigation bar is displayed in translucent mode.
3445     */
3446    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3447
3448    /**
3449     * @hide
3450     *
3451     * Makes navigation bar transparent (but not the status bar).
3452     */
3453    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3454
3455    /**
3456     * @hide
3457     *
3458     * Makes status bar transparent (but not the navigation bar).
3459     */
3460    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3461
3462    /**
3463     * @hide
3464     *
3465     * Makes both status bar and navigation bar transparent.
3466     */
3467    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3468            | STATUS_BAR_TRANSPARENT;
3469
3470    /**
3471     * @hide
3472     */
3473    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3474
3475    /**
3476     * These are the system UI flags that can be cleared by events outside
3477     * of an application.  Currently this is just the ability to tap on the
3478     * screen while hiding the navigation bar to have it return.
3479     * @hide
3480     */
3481    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3482            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3483            | SYSTEM_UI_FLAG_FULLSCREEN;
3484
3485    /**
3486     * Flags that can impact the layout in relation to system UI.
3487     */
3488    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3489            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3490            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3491
3492    /** @hide */
3493    @IntDef(flag = true,
3494            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3495    @Retention(RetentionPolicy.SOURCE)
3496    public @interface FindViewFlags {}
3497
3498    /**
3499     * Find views that render the specified text.
3500     *
3501     * @see #findViewsWithText(ArrayList, CharSequence, int)
3502     */
3503    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3504
3505    /**
3506     * Find find views that contain the specified content description.
3507     *
3508     * @see #findViewsWithText(ArrayList, CharSequence, int)
3509     */
3510    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3511
3512    /**
3513     * Find views that contain {@link AccessibilityNodeProvider}. Such
3514     * a View is a root of virtual view hierarchy and may contain the searched
3515     * text. If this flag is set Views with providers are automatically
3516     * added and it is a responsibility of the client to call the APIs of
3517     * the provider to determine whether the virtual tree rooted at this View
3518     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3519     * representing the virtual views with this text.
3520     *
3521     * @see #findViewsWithText(ArrayList, CharSequence, int)
3522     *
3523     * @hide
3524     */
3525    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3526
3527    /**
3528     * The undefined cursor position.
3529     *
3530     * @hide
3531     */
3532    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3533
3534    /**
3535     * Indicates that the screen has changed state and is now off.
3536     *
3537     * @see #onScreenStateChanged(int)
3538     */
3539    public static final int SCREEN_STATE_OFF = 0x0;
3540
3541    /**
3542     * Indicates that the screen has changed state and is now on.
3543     *
3544     * @see #onScreenStateChanged(int)
3545     */
3546    public static final int SCREEN_STATE_ON = 0x1;
3547
3548    /**
3549     * Indicates no axis of view scrolling.
3550     */
3551    public static final int SCROLL_AXIS_NONE = 0;
3552
3553    /**
3554     * Indicates scrolling along the horizontal axis.
3555     */
3556    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3557
3558    /**
3559     * Indicates scrolling along the vertical axis.
3560     */
3561    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3562
3563    /**
3564     * Controls the over-scroll mode for this view.
3565     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3566     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3567     * and {@link #OVER_SCROLL_NEVER}.
3568     */
3569    private int mOverScrollMode;
3570
3571    /**
3572     * The parent this view is attached to.
3573     * {@hide}
3574     *
3575     * @see #getParent()
3576     */
3577    protected ViewParent mParent;
3578
3579    /**
3580     * {@hide}
3581     */
3582    AttachInfo mAttachInfo;
3583
3584    /**
3585     * {@hide}
3586     */
3587    @ViewDebug.ExportedProperty(flagMapping = {
3588        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3589                name = "FORCE_LAYOUT"),
3590        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3591                name = "LAYOUT_REQUIRED"),
3592        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3593            name = "DRAWING_CACHE_INVALID", outputIf = false),
3594        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3595        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3596        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3597        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3598    }, formatToHexString = true)
3599
3600    /* @hide */
3601    public int mPrivateFlags;
3602    int mPrivateFlags2;
3603    int mPrivateFlags3;
3604
3605    /**
3606     * This view's request for the visibility of the status bar.
3607     * @hide
3608     */
3609    @ViewDebug.ExportedProperty(flagMapping = {
3610        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3611                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3612                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3613        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3614                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3615                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3616        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3617                                equals = SYSTEM_UI_FLAG_VISIBLE,
3618                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3619    }, formatToHexString = true)
3620    int mSystemUiVisibility;
3621
3622    /**
3623     * Reference count for transient state.
3624     * @see #setHasTransientState(boolean)
3625     */
3626    int mTransientStateCount = 0;
3627
3628    /**
3629     * Count of how many windows this view has been attached to.
3630     */
3631    int mWindowAttachCount;
3632
3633    /**
3634     * The layout parameters associated with this view and used by the parent
3635     * {@link android.view.ViewGroup} to determine how this view should be
3636     * laid out.
3637     * {@hide}
3638     */
3639    protected ViewGroup.LayoutParams mLayoutParams;
3640
3641    /**
3642     * The view flags hold various views states.
3643     * {@hide}
3644     */
3645    @ViewDebug.ExportedProperty(formatToHexString = true)
3646    int mViewFlags;
3647
3648    static class TransformationInfo {
3649        /**
3650         * The transform matrix for the View. This transform is calculated internally
3651         * based on the translation, rotation, and scale properties.
3652         *
3653         * Do *not* use this variable directly; instead call getMatrix(), which will
3654         * load the value from the View's RenderNode.
3655         */
3656        private final Matrix mMatrix = new Matrix();
3657
3658        /**
3659         * The inverse transform matrix for the View. This transform is calculated
3660         * internally based on the translation, rotation, and scale properties.
3661         *
3662         * Do *not* use this variable directly; instead call getInverseMatrix(),
3663         * which will load the value from the View's RenderNode.
3664         */
3665        private Matrix mInverseMatrix;
3666
3667        /**
3668         * The opacity of the View. This is a value from 0 to 1, where 0 means
3669         * completely transparent and 1 means completely opaque.
3670         */
3671        @ViewDebug.ExportedProperty
3672        float mAlpha = 1f;
3673
3674        /**
3675         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3676         * property only used by transitions, which is composited with the other alpha
3677         * values to calculate the final visual alpha value.
3678         */
3679        float mTransitionAlpha = 1f;
3680    }
3681
3682    /** @hide */
3683    public TransformationInfo mTransformationInfo;
3684
3685    /**
3686     * Current clip bounds. to which all drawing of this view are constrained.
3687     */
3688    Rect mClipBounds = null;
3689
3690    private boolean mLastIsOpaque;
3691
3692    /**
3693     * The distance in pixels from the left edge of this view's parent
3694     * to the left edge of this view.
3695     * {@hide}
3696     */
3697    @ViewDebug.ExportedProperty(category = "layout")
3698    protected int mLeft;
3699    /**
3700     * The distance in pixels from the left edge of this view's parent
3701     * to the right edge of this view.
3702     * {@hide}
3703     */
3704    @ViewDebug.ExportedProperty(category = "layout")
3705    protected int mRight;
3706    /**
3707     * The distance in pixels from the top edge of this view's parent
3708     * to the top edge of this view.
3709     * {@hide}
3710     */
3711    @ViewDebug.ExportedProperty(category = "layout")
3712    protected int mTop;
3713    /**
3714     * The distance in pixels from the top edge of this view's parent
3715     * to the bottom edge of this view.
3716     * {@hide}
3717     */
3718    @ViewDebug.ExportedProperty(category = "layout")
3719    protected int mBottom;
3720
3721    /**
3722     * The offset, in pixels, by which the content of this view is scrolled
3723     * horizontally.
3724     * {@hide}
3725     */
3726    @ViewDebug.ExportedProperty(category = "scrolling")
3727    protected int mScrollX;
3728    /**
3729     * The offset, in pixels, by which the content of this view is scrolled
3730     * vertically.
3731     * {@hide}
3732     */
3733    @ViewDebug.ExportedProperty(category = "scrolling")
3734    protected int mScrollY;
3735
3736    /**
3737     * The left padding in pixels, that is the distance in pixels between the
3738     * left edge of this view and the left edge of its content.
3739     * {@hide}
3740     */
3741    @ViewDebug.ExportedProperty(category = "padding")
3742    protected int mPaddingLeft = 0;
3743    /**
3744     * The right padding in pixels, that is the distance in pixels between the
3745     * right edge of this view and the right edge of its content.
3746     * {@hide}
3747     */
3748    @ViewDebug.ExportedProperty(category = "padding")
3749    protected int mPaddingRight = 0;
3750    /**
3751     * The top padding in pixels, that is the distance in pixels between the
3752     * top edge of this view and the top edge of its content.
3753     * {@hide}
3754     */
3755    @ViewDebug.ExportedProperty(category = "padding")
3756    protected int mPaddingTop;
3757    /**
3758     * The bottom padding in pixels, that is the distance in pixels between the
3759     * bottom edge of this view and the bottom edge of its content.
3760     * {@hide}
3761     */
3762    @ViewDebug.ExportedProperty(category = "padding")
3763    protected int mPaddingBottom;
3764
3765    /**
3766     * The layout insets in pixels, that is the distance in pixels between the
3767     * visible edges of this view its bounds.
3768     */
3769    private Insets mLayoutInsets;
3770
3771    /**
3772     * Briefly describes the view and is primarily used for accessibility support.
3773     */
3774    private CharSequence mContentDescription;
3775
3776    /**
3777     * Specifies the id of a view for which this view serves as a label for
3778     * accessibility purposes.
3779     */
3780    private int mLabelForId = View.NO_ID;
3781
3782    /**
3783     * Predicate for matching labeled view id with its label for
3784     * accessibility purposes.
3785     */
3786    private MatchLabelForPredicate mMatchLabelForPredicate;
3787
3788    /**
3789     * Specifies a view before which this one is visited in accessibility traversal.
3790     */
3791    private int mAccessibilityTraversalBeforeId = NO_ID;
3792
3793    /**
3794     * Specifies a view after which this one is visited in accessibility traversal.
3795     */
3796    private int mAccessibilityTraversalAfterId = NO_ID;
3797
3798    /**
3799     * Predicate for matching a view by its id.
3800     */
3801    private MatchIdPredicate mMatchIdPredicate;
3802
3803    /**
3804     * Cache the paddingRight set by the user to append to the scrollbar's size.
3805     *
3806     * @hide
3807     */
3808    @ViewDebug.ExportedProperty(category = "padding")
3809    protected int mUserPaddingRight;
3810
3811    /**
3812     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3813     *
3814     * @hide
3815     */
3816    @ViewDebug.ExportedProperty(category = "padding")
3817    protected int mUserPaddingBottom;
3818
3819    /**
3820     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3821     *
3822     * @hide
3823     */
3824    @ViewDebug.ExportedProperty(category = "padding")
3825    protected int mUserPaddingLeft;
3826
3827    /**
3828     * Cache the paddingStart set by the user to append to the scrollbar's size.
3829     *
3830     */
3831    @ViewDebug.ExportedProperty(category = "padding")
3832    int mUserPaddingStart;
3833
3834    /**
3835     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3836     *
3837     */
3838    @ViewDebug.ExportedProperty(category = "padding")
3839    int mUserPaddingEnd;
3840
3841    /**
3842     * Cache initial left padding.
3843     *
3844     * @hide
3845     */
3846    int mUserPaddingLeftInitial;
3847
3848    /**
3849     * Cache initial right padding.
3850     *
3851     * @hide
3852     */
3853    int mUserPaddingRightInitial;
3854
3855    /**
3856     * Default undefined padding
3857     */
3858    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3859
3860    /**
3861     * Cache if a left padding has been defined
3862     */
3863    private boolean mLeftPaddingDefined = false;
3864
3865    /**
3866     * Cache if a right padding has been defined
3867     */
3868    private boolean mRightPaddingDefined = false;
3869
3870    /**
3871     * @hide
3872     */
3873    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3874    /**
3875     * @hide
3876     */
3877    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3878
3879    private LongSparseLongArray mMeasureCache;
3880
3881    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3882    private Drawable mBackground;
3883    private TintInfo mBackgroundTint;
3884
3885    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3886    private ForegroundInfo mForegroundInfo;
3887
3888    private Drawable mScrollIndicatorDrawable;
3889
3890    /**
3891     * RenderNode used for backgrounds.
3892     * <p>
3893     * When non-null and valid, this is expected to contain an up-to-date copy
3894     * of the background drawable. It is cleared on temporary detach, and reset
3895     * on cleanup.
3896     */
3897    private RenderNode mBackgroundRenderNode;
3898
3899    private int mBackgroundResource;
3900    private boolean mBackgroundSizeChanged;
3901
3902    private String mTransitionName;
3903
3904    static class TintInfo {
3905        ColorStateList mTintList;
3906        PorterDuff.Mode mTintMode;
3907        boolean mHasTintMode;
3908        boolean mHasTintList;
3909    }
3910
3911    private static class ForegroundInfo {
3912        private Drawable mDrawable;
3913        private TintInfo mTintInfo;
3914        private int mGravity = Gravity.FILL;
3915        private boolean mInsidePadding = true;
3916        private boolean mBoundsChanged = true;
3917        private final Rect mSelfBounds = new Rect();
3918        private final Rect mOverlayBounds = new Rect();
3919    }
3920
3921    static class ListenerInfo {
3922        /**
3923         * Listener used to dispatch focus change events.
3924         * This field should be made private, so it is hidden from the SDK.
3925         * {@hide}
3926         */
3927        protected OnFocusChangeListener mOnFocusChangeListener;
3928
3929        /**
3930         * Listeners for layout change events.
3931         */
3932        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3933
3934        protected OnScrollChangeListener mOnScrollChangeListener;
3935
3936        /**
3937         * Listeners for attach events.
3938         */
3939        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3940
3941        /**
3942         * Listener used to dispatch click events.
3943         * This field should be made private, so it is hidden from the SDK.
3944         * {@hide}
3945         */
3946        public OnClickListener mOnClickListener;
3947
3948        /**
3949         * Listener used to dispatch long click events.
3950         * This field should be made private, so it is hidden from the SDK.
3951         * {@hide}
3952         */
3953        protected OnLongClickListener mOnLongClickListener;
3954
3955        /**
3956         * Listener used to dispatch context click events. This field should be made private, so it
3957         * is hidden from the SDK.
3958         * {@hide}
3959         */
3960        protected OnContextClickListener mOnContextClickListener;
3961
3962        /**
3963         * Listener used to build the context menu.
3964         * This field should be made private, so it is hidden from the SDK.
3965         * {@hide}
3966         */
3967        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3968
3969        private OnKeyListener mOnKeyListener;
3970
3971        private OnTouchListener mOnTouchListener;
3972
3973        private OnHoverListener mOnHoverListener;
3974
3975        private OnGenericMotionListener mOnGenericMotionListener;
3976
3977        private OnDragListener mOnDragListener;
3978
3979        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3980
3981        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3982
3983        OnCapturedPointerListener mOnCapturedPointerListener;
3984    }
3985
3986    ListenerInfo mListenerInfo;
3987
3988    private static class TooltipInfo {
3989        /**
3990         * Text to be displayed in a tooltip popup.
3991         */
3992        @Nullable
3993        CharSequence mTooltipText;
3994
3995        /**
3996         * View-relative position of the tooltip anchor point.
3997         */
3998        int mAnchorX;
3999        int mAnchorY;
4000
4001        /**
4002         * The tooltip popup.
4003         */
4004        @Nullable
4005        TooltipPopup mTooltipPopup;
4006
4007        /**
4008         * Set to true if the tooltip was shown as a result of a long click.
4009         */
4010        boolean mTooltipFromLongClick;
4011
4012        /**
4013         * Keep these Runnables so that they can be used to reschedule.
4014         */
4015        Runnable mShowTooltipRunnable;
4016        Runnable mHideTooltipRunnable;
4017    }
4018
4019    TooltipInfo mTooltipInfo;
4020
4021    // Temporary values used to hold (x,y) coordinates when delegating from the
4022    // two-arg performLongClick() method to the legacy no-arg version.
4023    private float mLongClickX = Float.NaN;
4024    private float mLongClickY = Float.NaN;
4025
4026    /**
4027     * The application environment this view lives in.
4028     * This field should be made private, so it is hidden from the SDK.
4029     * {@hide}
4030     */
4031    @ViewDebug.ExportedProperty(deepExport = true)
4032    protected Context mContext;
4033
4034    private final Resources mResources;
4035
4036    private ScrollabilityCache mScrollCache;
4037
4038    private int[] mDrawableState = null;
4039
4040    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4041
4042    /**
4043     * Animator that automatically runs based on state changes.
4044     */
4045    private StateListAnimator mStateListAnimator;
4046
4047    /**
4048     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4049     * the user may specify which view to go to next.
4050     */
4051    private int mNextFocusLeftId = View.NO_ID;
4052
4053    /**
4054     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4055     * the user may specify which view to go to next.
4056     */
4057    private int mNextFocusRightId = View.NO_ID;
4058
4059    /**
4060     * When this view has focus and the next focus is {@link #FOCUS_UP},
4061     * the user may specify which view to go to next.
4062     */
4063    private int mNextFocusUpId = View.NO_ID;
4064
4065    /**
4066     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4067     * the user may specify which view to go to next.
4068     */
4069    private int mNextFocusDownId = View.NO_ID;
4070
4071    /**
4072     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4073     * the user may specify which view to go to next.
4074     */
4075    int mNextFocusForwardId = View.NO_ID;
4076
4077    /**
4078     * User-specified next keyboard navigation cluster.
4079     */
4080    int mNextClusterForwardId = View.NO_ID;
4081
4082    private CheckForLongPress mPendingCheckForLongPress;
4083    private CheckForTap mPendingCheckForTap = null;
4084    private PerformClick mPerformClick;
4085    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4086
4087    private UnsetPressedState mUnsetPressedState;
4088
4089    /**
4090     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4091     * up event while a long press is invoked as soon as the long press duration is reached, so
4092     * a long press could be performed before the tap is checked, in which case the tap's action
4093     * should not be invoked.
4094     */
4095    private boolean mHasPerformedLongPress;
4096
4097    /**
4098     * Whether a context click button is currently pressed down. This is true when the stylus is
4099     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4100     * pressed. This is false once the button is released or if the stylus has been lifted.
4101     */
4102    private boolean mInContextButtonPress;
4103
4104    /**
4105     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4106     * true after a stylus button press has occured, when the next up event should not be recognized
4107     * as a tap.
4108     */
4109    private boolean mIgnoreNextUpEvent;
4110
4111    /**
4112     * The minimum height of the view. We'll try our best to have the height
4113     * of this view to at least this amount.
4114     */
4115    @ViewDebug.ExportedProperty(category = "measurement")
4116    private int mMinHeight;
4117
4118    /**
4119     * The minimum width of the view. We'll try our best to have the width
4120     * of this view to at least this amount.
4121     */
4122    @ViewDebug.ExportedProperty(category = "measurement")
4123    private int mMinWidth;
4124
4125    /**
4126     * The delegate to handle touch events that are physically in this view
4127     * but should be handled by another view.
4128     */
4129    private TouchDelegate mTouchDelegate = null;
4130
4131    /**
4132     * Solid color to use as a background when creating the drawing cache. Enables
4133     * the cache to use 16 bit bitmaps instead of 32 bit.
4134     */
4135    private int mDrawingCacheBackgroundColor = 0;
4136
4137    /**
4138     * Special tree observer used when mAttachInfo is null.
4139     */
4140    private ViewTreeObserver mFloatingTreeObserver;
4141
4142    /**
4143     * Cache the touch slop from the context that created the view.
4144     */
4145    private int mTouchSlop;
4146
4147    /**
4148     * Object that handles automatic animation of view properties.
4149     */
4150    private ViewPropertyAnimator mAnimator = null;
4151
4152    /**
4153     * List of registered FrameMetricsObservers.
4154     */
4155    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4156
4157    /**
4158     * Flag indicating that a drag can cross window boundaries.  When
4159     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4160     * with this flag set, all visible applications with targetSdkVersion >=
4161     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4162     * in the drag operation and receive the dragged content.
4163     *
4164     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4165     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4166     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4167     */
4168    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4169
4170    /**
4171     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4172     * request read access to the content URI(s) contained in the {@link ClipData} object.
4173     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
4174     */
4175    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4176
4177    /**
4178     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4179     * request write access to the content URI(s) contained in the {@link ClipData} object.
4180     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
4181     */
4182    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4183
4184    /**
4185     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4186     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4187     * reboots until explicitly revoked with
4188     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
4189     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4190     */
4191    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4192            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4193
4194    /**
4195     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4196     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4197     * match against the original granted URI.
4198     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
4199     */
4200    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4201            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4202
4203    /**
4204     * Flag indicating that the drag shadow will be opaque.  When
4205     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4206     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4207     */
4208    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4209
4210    /**
4211     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4212     */
4213    private float mVerticalScrollFactor;
4214
4215    /**
4216     * Position of the vertical scroll bar.
4217     */
4218    private int mVerticalScrollbarPosition;
4219
4220    /**
4221     * Position the scroll bar at the default position as determined by the system.
4222     */
4223    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4224
4225    /**
4226     * Position the scroll bar along the left edge.
4227     */
4228    public static final int SCROLLBAR_POSITION_LEFT = 1;
4229
4230    /**
4231     * Position the scroll bar along the right edge.
4232     */
4233    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4234
4235    /**
4236     * Indicates that the view does not have a layer.
4237     *
4238     * @see #getLayerType()
4239     * @see #setLayerType(int, android.graphics.Paint)
4240     * @see #LAYER_TYPE_SOFTWARE
4241     * @see #LAYER_TYPE_HARDWARE
4242     */
4243    public static final int LAYER_TYPE_NONE = 0;
4244
4245    /**
4246     * <p>Indicates that the view has a software layer. A software layer is backed
4247     * by a bitmap and causes the view to be rendered using Android's software
4248     * rendering pipeline, even if hardware acceleration is enabled.</p>
4249     *
4250     * <p>Software layers have various usages:</p>
4251     * <p>When the application is not using hardware acceleration, a software layer
4252     * is useful to apply a specific color filter and/or blending mode and/or
4253     * translucency to a view and all its children.</p>
4254     * <p>When the application is using hardware acceleration, a software layer
4255     * is useful to render drawing primitives not supported by the hardware
4256     * accelerated pipeline. It can also be used to cache a complex view tree
4257     * into a texture and reduce the complexity of drawing operations. For instance,
4258     * when animating a complex view tree with a translation, a software layer can
4259     * be used to render the view tree only once.</p>
4260     * <p>Software layers should be avoided when the affected view tree updates
4261     * often. Every update will require to re-render the software layer, which can
4262     * potentially be slow (particularly when hardware acceleration is turned on
4263     * since the layer will have to be uploaded into a hardware texture after every
4264     * update.)</p>
4265     *
4266     * @see #getLayerType()
4267     * @see #setLayerType(int, android.graphics.Paint)
4268     * @see #LAYER_TYPE_NONE
4269     * @see #LAYER_TYPE_HARDWARE
4270     */
4271    public static final int LAYER_TYPE_SOFTWARE = 1;
4272
4273    /**
4274     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4275     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4276     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4277     * rendering pipeline, but only if hardware acceleration is turned on for the
4278     * view hierarchy. When hardware acceleration is turned off, hardware layers
4279     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4280     *
4281     * <p>A hardware layer is useful to apply a specific color filter and/or
4282     * blending mode and/or translucency to a view and all its children.</p>
4283     * <p>A hardware layer can be used to cache a complex view tree into a
4284     * texture and reduce the complexity of drawing operations. For instance,
4285     * when animating a complex view tree with a translation, a hardware layer can
4286     * be used to render the view tree only once.</p>
4287     * <p>A hardware layer can also be used to increase the rendering quality when
4288     * rotation transformations are applied on a view. It can also be used to
4289     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4290     *
4291     * @see #getLayerType()
4292     * @see #setLayerType(int, android.graphics.Paint)
4293     * @see #LAYER_TYPE_NONE
4294     * @see #LAYER_TYPE_SOFTWARE
4295     */
4296    public static final int LAYER_TYPE_HARDWARE = 2;
4297
4298    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4299            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4300            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4301            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4302    })
4303    int mLayerType = LAYER_TYPE_NONE;
4304    Paint mLayerPaint;
4305
4306    /**
4307     * Set to true when drawing cache is enabled and cannot be created.
4308     *
4309     * @hide
4310     */
4311    public boolean mCachingFailed;
4312    private Bitmap mDrawingCache;
4313    private Bitmap mUnscaledDrawingCache;
4314
4315    /**
4316     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4317     * <p>
4318     * When non-null and valid, this is expected to contain an up-to-date copy
4319     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4320     * cleanup.
4321     */
4322    final RenderNode mRenderNode;
4323
4324    /**
4325     * Set to true when the view is sending hover accessibility events because it
4326     * is the innermost hovered view.
4327     */
4328    private boolean mSendingHoverAccessibilityEvents;
4329
4330    /**
4331     * Delegate for injecting accessibility functionality.
4332     */
4333    AccessibilityDelegate mAccessibilityDelegate;
4334
4335    /**
4336     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4337     * and add/remove objects to/from the overlay directly through the Overlay methods.
4338     */
4339    ViewOverlay mOverlay;
4340
4341    /**
4342     * The currently active parent view for receiving delegated nested scrolling events.
4343     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4344     * by {@link #stopNestedScroll()} at the same point where we clear
4345     * requestDisallowInterceptTouchEvent.
4346     */
4347    private ViewParent mNestedScrollingParent;
4348
4349    /**
4350     * Consistency verifier for debugging purposes.
4351     * @hide
4352     */
4353    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4354            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4355                    new InputEventConsistencyVerifier(this, 0) : null;
4356
4357    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4358
4359    private int[] mTempNestedScrollConsumed;
4360
4361    /**
4362     * An overlay is going to draw this View instead of being drawn as part of this
4363     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4364     * when this view is invalidated.
4365     */
4366    GhostView mGhostView;
4367
4368    /**
4369     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4370     * @hide
4371     */
4372    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4373    public String[] mAttributes;
4374
4375    /**
4376     * Maps a Resource id to its name.
4377     */
4378    private static SparseArray<String> mAttributeMap;
4379
4380    /**
4381     * Queue of pending runnables. Used to postpone calls to post() until this
4382     * view is attached and has a handler.
4383     */
4384    private HandlerActionQueue mRunQueue;
4385
4386    /**
4387     * The pointer icon when the mouse hovers on this view. The default is null.
4388     */
4389    private PointerIcon mPointerIcon;
4390
4391    /**
4392     * @hide
4393     */
4394    String mStartActivityRequestWho;
4395
4396    @Nullable
4397    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4398
4399    /**
4400     * Simple constructor to use when creating a view from code.
4401     *
4402     * @param context The Context the view is running in, through which it can
4403     *        access the current theme, resources, etc.
4404     */
4405    public View(Context context) {
4406        mContext = context;
4407        mResources = context != null ? context.getResources() : null;
4408        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4409        // Set some flags defaults
4410        mPrivateFlags2 =
4411                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4412                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4413                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4414                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4415                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4416                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4417        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4418        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4419        mUserPaddingStart = UNDEFINED_PADDING;
4420        mUserPaddingEnd = UNDEFINED_PADDING;
4421        mRenderNode = RenderNode.create(getClass().getName(), this);
4422
4423        if (!sCompatibilityDone && context != null) {
4424            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4425
4426            // Older apps may need this compatibility hack for measurement.
4427            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4428
4429            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4430            // of whether a layout was requested on that View.
4431            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4432
4433            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4434
4435            // In M and newer, our widgets can pass a "hint" value in the size
4436            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4437            // know what the expected parent size is going to be, so e.g. list items can size
4438            // themselves at 1/3 the size of their container. It breaks older apps though,
4439            // specifically apps that use some popular open source libraries.
4440            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4441
4442            // Old versions of the platform would give different results from
4443            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4444            // modes, so we always need to run an additional EXACTLY pass.
4445            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4446
4447            // Prior to N, layout params could change without requiring a
4448            // subsequent call to setLayoutParams() and they would usually
4449            // work. Partial layout breaks this assumption.
4450            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4451
4452            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4453            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4454            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4455
4456            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4457            // in apps so we target check it to avoid breaking existing apps.
4458            sPreserveMarginParamsInLayoutParamConversion =
4459                    targetSdkVersion >= Build.VERSION_CODES.N;
4460
4461            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4462
4463            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4464
4465            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4466
4467            sCompatibilityDone = true;
4468        }
4469    }
4470
4471    /**
4472     * Constructor that is called when inflating a view from XML. This is called
4473     * when a view is being constructed from an XML file, supplying attributes
4474     * that were specified in the XML file. This version uses a default style of
4475     * 0, so the only attribute values applied are those in the Context's Theme
4476     * and the given AttributeSet.
4477     *
4478     * <p>
4479     * The method onFinishInflate() will be called after all children have been
4480     * added.
4481     *
4482     * @param context The Context the view is running in, through which it can
4483     *        access the current theme, resources, etc.
4484     * @param attrs The attributes of the XML tag that is inflating the view.
4485     * @see #View(Context, AttributeSet, int)
4486     */
4487    public View(Context context, @Nullable AttributeSet attrs) {
4488        this(context, attrs, 0);
4489    }
4490
4491    /**
4492     * Perform inflation from XML and apply a class-specific base style from a
4493     * theme attribute. This constructor of View allows subclasses to use their
4494     * own base style when they are inflating. For example, a Button class's
4495     * constructor would call this version of the super class constructor and
4496     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4497     * allows the theme's button style to modify all of the base view attributes
4498     * (in particular its background) as well as the Button class's attributes.
4499     *
4500     * @param context The Context the view is running in, through which it can
4501     *        access the current theme, resources, etc.
4502     * @param attrs The attributes of the XML tag that is inflating the view.
4503     * @param defStyleAttr An attribute in the current theme that contains a
4504     *        reference to a style resource that supplies default values for
4505     *        the view. Can be 0 to not look for defaults.
4506     * @see #View(Context, AttributeSet)
4507     */
4508    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4509        this(context, attrs, defStyleAttr, 0);
4510    }
4511
4512    /**
4513     * Perform inflation from XML and apply a class-specific base style from a
4514     * theme attribute or style resource. This constructor of View allows
4515     * subclasses to use their own base style when they are inflating.
4516     * <p>
4517     * When determining the final value of a particular attribute, there are
4518     * four inputs that come into play:
4519     * <ol>
4520     * <li>Any attribute values in the given AttributeSet.
4521     * <li>The style resource specified in the AttributeSet (named "style").
4522     * <li>The default style specified by <var>defStyleAttr</var>.
4523     * <li>The default style specified by <var>defStyleRes</var>.
4524     * <li>The base values in this theme.
4525     * </ol>
4526     * <p>
4527     * Each of these inputs is considered in-order, with the first listed taking
4528     * precedence over the following ones. In other words, if in the
4529     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4530     * , then the button's text will <em>always</em> be black, regardless of
4531     * what is specified in any of the styles.
4532     *
4533     * @param context The Context the view is running in, through which it can
4534     *        access the current theme, resources, etc.
4535     * @param attrs The attributes of the XML tag that is inflating the view.
4536     * @param defStyleAttr An attribute in the current theme that contains a
4537     *        reference to a style resource that supplies default values for
4538     *        the view. Can be 0 to not look for defaults.
4539     * @param defStyleRes A resource identifier of a style resource that
4540     *        supplies default values for the view, used only if
4541     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4542     *        to not look for defaults.
4543     * @see #View(Context, AttributeSet, int)
4544     */
4545    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4546        this(context);
4547
4548        final TypedArray a = context.obtainStyledAttributes(
4549                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4550
4551        if (mDebugViewAttributes) {
4552            saveAttributeData(attrs, a);
4553        }
4554
4555        Drawable background = null;
4556
4557        int leftPadding = -1;
4558        int topPadding = -1;
4559        int rightPadding = -1;
4560        int bottomPadding = -1;
4561        int startPadding = UNDEFINED_PADDING;
4562        int endPadding = UNDEFINED_PADDING;
4563
4564        int padding = -1;
4565        int paddingHorizontal = -1;
4566        int paddingVertical = -1;
4567
4568        int viewFlagValues = 0;
4569        int viewFlagMasks = 0;
4570
4571        boolean setScrollContainer = false;
4572
4573        int x = 0;
4574        int y = 0;
4575
4576        float tx = 0;
4577        float ty = 0;
4578        float tz = 0;
4579        float elevation = 0;
4580        float rotation = 0;
4581        float rotationX = 0;
4582        float rotationY = 0;
4583        float sx = 1f;
4584        float sy = 1f;
4585        boolean transformSet = false;
4586
4587        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4588        int overScrollMode = mOverScrollMode;
4589        boolean initializeScrollbars = false;
4590        boolean initializeScrollIndicators = false;
4591
4592        boolean startPaddingDefined = false;
4593        boolean endPaddingDefined = false;
4594        boolean leftPaddingDefined = false;
4595        boolean rightPaddingDefined = false;
4596
4597        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4598
4599        // Set default values.
4600        viewFlagValues |= FOCUSABLE_AUTO;
4601        viewFlagMasks |= FOCUSABLE_AUTO;
4602
4603        final int N = a.getIndexCount();
4604        for (int i = 0; i < N; i++) {
4605            int attr = a.getIndex(i);
4606            switch (attr) {
4607                case com.android.internal.R.styleable.View_background:
4608                    background = a.getDrawable(attr);
4609                    break;
4610                case com.android.internal.R.styleable.View_padding:
4611                    padding = a.getDimensionPixelSize(attr, -1);
4612                    mUserPaddingLeftInitial = padding;
4613                    mUserPaddingRightInitial = padding;
4614                    leftPaddingDefined = true;
4615                    rightPaddingDefined = true;
4616                    break;
4617                case com.android.internal.R.styleable.View_paddingHorizontal:
4618                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4619                    mUserPaddingLeftInitial = paddingHorizontal;
4620                    mUserPaddingRightInitial = paddingHorizontal;
4621                    leftPaddingDefined = true;
4622                    rightPaddingDefined = true;
4623                    break;
4624                case com.android.internal.R.styleable.View_paddingVertical:
4625                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4626                    break;
4627                 case com.android.internal.R.styleable.View_paddingLeft:
4628                    leftPadding = a.getDimensionPixelSize(attr, -1);
4629                    mUserPaddingLeftInitial = leftPadding;
4630                    leftPaddingDefined = true;
4631                    break;
4632                case com.android.internal.R.styleable.View_paddingTop:
4633                    topPadding = a.getDimensionPixelSize(attr, -1);
4634                    break;
4635                case com.android.internal.R.styleable.View_paddingRight:
4636                    rightPadding = a.getDimensionPixelSize(attr, -1);
4637                    mUserPaddingRightInitial = rightPadding;
4638                    rightPaddingDefined = true;
4639                    break;
4640                case com.android.internal.R.styleable.View_paddingBottom:
4641                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4642                    break;
4643                case com.android.internal.R.styleable.View_paddingStart:
4644                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4645                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4646                    break;
4647                case com.android.internal.R.styleable.View_paddingEnd:
4648                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4649                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4650                    break;
4651                case com.android.internal.R.styleable.View_scrollX:
4652                    x = a.getDimensionPixelOffset(attr, 0);
4653                    break;
4654                case com.android.internal.R.styleable.View_scrollY:
4655                    y = a.getDimensionPixelOffset(attr, 0);
4656                    break;
4657                case com.android.internal.R.styleable.View_alpha:
4658                    setAlpha(a.getFloat(attr, 1f));
4659                    break;
4660                case com.android.internal.R.styleable.View_transformPivotX:
4661                    setPivotX(a.getDimension(attr, 0));
4662                    break;
4663                case com.android.internal.R.styleable.View_transformPivotY:
4664                    setPivotY(a.getDimension(attr, 0));
4665                    break;
4666                case com.android.internal.R.styleable.View_translationX:
4667                    tx = a.getDimension(attr, 0);
4668                    transformSet = true;
4669                    break;
4670                case com.android.internal.R.styleable.View_translationY:
4671                    ty = a.getDimension(attr, 0);
4672                    transformSet = true;
4673                    break;
4674                case com.android.internal.R.styleable.View_translationZ:
4675                    tz = a.getDimension(attr, 0);
4676                    transformSet = true;
4677                    break;
4678                case com.android.internal.R.styleable.View_elevation:
4679                    elevation = a.getDimension(attr, 0);
4680                    transformSet = true;
4681                    break;
4682                case com.android.internal.R.styleable.View_rotation:
4683                    rotation = a.getFloat(attr, 0);
4684                    transformSet = true;
4685                    break;
4686                case com.android.internal.R.styleable.View_rotationX:
4687                    rotationX = a.getFloat(attr, 0);
4688                    transformSet = true;
4689                    break;
4690                case com.android.internal.R.styleable.View_rotationY:
4691                    rotationY = a.getFloat(attr, 0);
4692                    transformSet = true;
4693                    break;
4694                case com.android.internal.R.styleable.View_scaleX:
4695                    sx = a.getFloat(attr, 1f);
4696                    transformSet = true;
4697                    break;
4698                case com.android.internal.R.styleable.View_scaleY:
4699                    sy = a.getFloat(attr, 1f);
4700                    transformSet = true;
4701                    break;
4702                case com.android.internal.R.styleable.View_id:
4703                    mID = a.getResourceId(attr, NO_ID);
4704                    break;
4705                case com.android.internal.R.styleable.View_tag:
4706                    mTag = a.getText(attr);
4707                    break;
4708                case com.android.internal.R.styleable.View_fitsSystemWindows:
4709                    if (a.getBoolean(attr, false)) {
4710                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4711                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4712                    }
4713                    break;
4714                case com.android.internal.R.styleable.View_focusable:
4715                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4716                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4717                        viewFlagMasks |= FOCUSABLE_MASK;
4718                    }
4719                    break;
4720                case com.android.internal.R.styleable.View_focusableInTouchMode:
4721                    if (a.getBoolean(attr, false)) {
4722                        // unset auto focus since focusableInTouchMode implies explicit focusable
4723                        viewFlagValues &= ~FOCUSABLE_AUTO;
4724                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4725                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4726                    }
4727                    break;
4728                case com.android.internal.R.styleable.View_clickable:
4729                    if (a.getBoolean(attr, false)) {
4730                        viewFlagValues |= CLICKABLE;
4731                        viewFlagMasks |= CLICKABLE;
4732                    }
4733                    break;
4734                case com.android.internal.R.styleable.View_longClickable:
4735                    if (a.getBoolean(attr, false)) {
4736                        viewFlagValues |= LONG_CLICKABLE;
4737                        viewFlagMasks |= LONG_CLICKABLE;
4738                    }
4739                    break;
4740                case com.android.internal.R.styleable.View_contextClickable:
4741                    if (a.getBoolean(attr, false)) {
4742                        viewFlagValues |= CONTEXT_CLICKABLE;
4743                        viewFlagMasks |= CONTEXT_CLICKABLE;
4744                    }
4745                    break;
4746                case com.android.internal.R.styleable.View_saveEnabled:
4747                    if (!a.getBoolean(attr, true)) {
4748                        viewFlagValues |= SAVE_DISABLED;
4749                        viewFlagMasks |= SAVE_DISABLED_MASK;
4750                    }
4751                    break;
4752                case com.android.internal.R.styleable.View_duplicateParentState:
4753                    if (a.getBoolean(attr, false)) {
4754                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4755                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4756                    }
4757                    break;
4758                case com.android.internal.R.styleable.View_visibility:
4759                    final int visibility = a.getInt(attr, 0);
4760                    if (visibility != 0) {
4761                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4762                        viewFlagMasks |= VISIBILITY_MASK;
4763                    }
4764                    break;
4765                case com.android.internal.R.styleable.View_layoutDirection:
4766                    // Clear any layout direction flags (included resolved bits) already set
4767                    mPrivateFlags2 &=
4768                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4769                    // Set the layout direction flags depending on the value of the attribute
4770                    final int layoutDirection = a.getInt(attr, -1);
4771                    final int value = (layoutDirection != -1) ?
4772                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4773                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4774                    break;
4775                case com.android.internal.R.styleable.View_drawingCacheQuality:
4776                    final int cacheQuality = a.getInt(attr, 0);
4777                    if (cacheQuality != 0) {
4778                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4779                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4780                    }
4781                    break;
4782                case com.android.internal.R.styleable.View_contentDescription:
4783                    setContentDescription(a.getString(attr));
4784                    break;
4785                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4786                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4787                    break;
4788                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4789                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4790                    break;
4791                case com.android.internal.R.styleable.View_labelFor:
4792                    setLabelFor(a.getResourceId(attr, NO_ID));
4793                    break;
4794                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4795                    if (!a.getBoolean(attr, true)) {
4796                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4797                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4798                    }
4799                    break;
4800                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4801                    if (!a.getBoolean(attr, true)) {
4802                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4803                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4804                    }
4805                    break;
4806                case R.styleable.View_scrollbars:
4807                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4808                    if (scrollbars != SCROLLBARS_NONE) {
4809                        viewFlagValues |= scrollbars;
4810                        viewFlagMasks |= SCROLLBARS_MASK;
4811                        initializeScrollbars = true;
4812                    }
4813                    break;
4814                //noinspection deprecation
4815                case R.styleable.View_fadingEdge:
4816                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4817                        // Ignore the attribute starting with ICS
4818                        break;
4819                    }
4820                    // With builds < ICS, fall through and apply fading edges
4821                case R.styleable.View_requiresFadingEdge:
4822                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4823                    if (fadingEdge != FADING_EDGE_NONE) {
4824                        viewFlagValues |= fadingEdge;
4825                        viewFlagMasks |= FADING_EDGE_MASK;
4826                        initializeFadingEdgeInternal(a);
4827                    }
4828                    break;
4829                case R.styleable.View_scrollbarStyle:
4830                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4831                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4832                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4833                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4834                    }
4835                    break;
4836                case R.styleable.View_isScrollContainer:
4837                    setScrollContainer = true;
4838                    if (a.getBoolean(attr, false)) {
4839                        setScrollContainer(true);
4840                    }
4841                    break;
4842                case com.android.internal.R.styleable.View_keepScreenOn:
4843                    if (a.getBoolean(attr, false)) {
4844                        viewFlagValues |= KEEP_SCREEN_ON;
4845                        viewFlagMasks |= KEEP_SCREEN_ON;
4846                    }
4847                    break;
4848                case R.styleable.View_filterTouchesWhenObscured:
4849                    if (a.getBoolean(attr, false)) {
4850                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4851                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4852                    }
4853                    break;
4854                case R.styleable.View_nextFocusLeft:
4855                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4856                    break;
4857                case R.styleable.View_nextFocusRight:
4858                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4859                    break;
4860                case R.styleable.View_nextFocusUp:
4861                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4862                    break;
4863                case R.styleable.View_nextFocusDown:
4864                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4865                    break;
4866                case R.styleable.View_nextFocusForward:
4867                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4868                    break;
4869                case R.styleable.View_nextClusterForward:
4870                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4871                    break;
4872                case R.styleable.View_minWidth:
4873                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4874                    break;
4875                case R.styleable.View_minHeight:
4876                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4877                    break;
4878                case R.styleable.View_onClick:
4879                    if (context.isRestricted()) {
4880                        throw new IllegalStateException("The android:onClick attribute cannot "
4881                                + "be used within a restricted context");
4882                    }
4883
4884                    final String handlerName = a.getString(attr);
4885                    if (handlerName != null) {
4886                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4887                    }
4888                    break;
4889                case R.styleable.View_overScrollMode:
4890                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4891                    break;
4892                case R.styleable.View_verticalScrollbarPosition:
4893                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4894                    break;
4895                case R.styleable.View_layerType:
4896                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4897                    break;
4898                case R.styleable.View_textDirection:
4899                    // Clear any text direction flag already set
4900                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4901                    // Set the text direction flags depending on the value of the attribute
4902                    final int textDirection = a.getInt(attr, -1);
4903                    if (textDirection != -1) {
4904                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4905                    }
4906                    break;
4907                case R.styleable.View_textAlignment:
4908                    // Clear any text alignment flag already set
4909                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4910                    // Set the text alignment flag depending on the value of the attribute
4911                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4912                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4913                    break;
4914                case R.styleable.View_importantForAccessibility:
4915                    setImportantForAccessibility(a.getInt(attr,
4916                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4917                    break;
4918                case R.styleable.View_accessibilityLiveRegion:
4919                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4920                    break;
4921                case R.styleable.View_transitionName:
4922                    setTransitionName(a.getString(attr));
4923                    break;
4924                case R.styleable.View_nestedScrollingEnabled:
4925                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4926                    break;
4927                case R.styleable.View_stateListAnimator:
4928                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4929                            a.getResourceId(attr, 0)));
4930                    break;
4931                case R.styleable.View_backgroundTint:
4932                    // This will get applied later during setBackground().
4933                    if (mBackgroundTint == null) {
4934                        mBackgroundTint = new TintInfo();
4935                    }
4936                    mBackgroundTint.mTintList = a.getColorStateList(
4937                            R.styleable.View_backgroundTint);
4938                    mBackgroundTint.mHasTintList = true;
4939                    break;
4940                case R.styleable.View_backgroundTintMode:
4941                    // This will get applied later during setBackground().
4942                    if (mBackgroundTint == null) {
4943                        mBackgroundTint = new TintInfo();
4944                    }
4945                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4946                            R.styleable.View_backgroundTintMode, -1), null);
4947                    mBackgroundTint.mHasTintMode = true;
4948                    break;
4949                case R.styleable.View_outlineProvider:
4950                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4951                            PROVIDER_BACKGROUND));
4952                    break;
4953                case R.styleable.View_foreground:
4954                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4955                        setForeground(a.getDrawable(attr));
4956                    }
4957                    break;
4958                case R.styleable.View_foregroundGravity:
4959                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4960                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4961                    }
4962                    break;
4963                case R.styleable.View_foregroundTintMode:
4964                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4965                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4966                    }
4967                    break;
4968                case R.styleable.View_foregroundTint:
4969                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4970                        setForegroundTintList(a.getColorStateList(attr));
4971                    }
4972                    break;
4973                case R.styleable.View_foregroundInsidePadding:
4974                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4975                        if (mForegroundInfo == null) {
4976                            mForegroundInfo = new ForegroundInfo();
4977                        }
4978                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4979                                mForegroundInfo.mInsidePadding);
4980                    }
4981                    break;
4982                case R.styleable.View_scrollIndicators:
4983                    final int scrollIndicators =
4984                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4985                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4986                    if (scrollIndicators != 0) {
4987                        mPrivateFlags3 |= scrollIndicators;
4988                        initializeScrollIndicators = true;
4989                    }
4990                    break;
4991                case R.styleable.View_pointerIcon:
4992                    final int resourceId = a.getResourceId(attr, 0);
4993                    if (resourceId != 0) {
4994                        setPointerIcon(PointerIcon.load(
4995                                context.getResources(), resourceId));
4996                    } else {
4997                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4998                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4999                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5000                        }
5001                    }
5002                    break;
5003                case R.styleable.View_forceHasOverlappingRendering:
5004                    if (a.peekValue(attr) != null) {
5005                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5006                    }
5007                    break;
5008                case R.styleable.View_tooltipText:
5009                    setTooltipText(a.getText(attr));
5010                    break;
5011                case R.styleable.View_keyboardNavigationCluster:
5012                    if (a.peekValue(attr) != null) {
5013                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5014                    }
5015                    break;
5016                case R.styleable.View_focusedByDefault:
5017                    if (a.peekValue(attr) != null) {
5018                        setFocusedByDefault(a.getBoolean(attr, true));
5019                    }
5020                    break;
5021                case R.styleable.View_autofillMode:
5022                    if (a.peekValue(attr) != null) {
5023                        setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
5024                    }
5025                    break;
5026                case R.styleable.View_autofillHint:
5027                    if (a.peekValue(attr) != null) {
5028                        CharSequence[] rawHints = null;
5029                        String rawString = null;
5030
5031                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5032                            int resId = a.getResourceId(attr, 0);
5033
5034                            try {
5035                                rawHints = a.getTextArray(attr);
5036                            } catch (Resources.NotFoundException e) {
5037                                rawString = getResources().getString(resId);
5038                            }
5039                        } else {
5040                            rawString = a.getString(attr);
5041                        }
5042
5043                        if (rawHints == null) {
5044                            if (rawString == null) {
5045                                throw new IllegalArgumentException(
5046                                        "Could not resolve autofillHint");
5047                            } else {
5048                                rawHints = rawString.split(",");
5049                            }
5050                        }
5051
5052                        String[] hints = new String[rawHints.length];
5053
5054                        int numHints = rawHints.length;
5055                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5056                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5057                        }
5058                        setAutofillHint(hints);
5059                    }
5060                    break;
5061                case R.styleable.View_importantForAutofill:
5062                    if (a.peekValue(attr) != null) {
5063                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5064                    }
5065                    break;
5066            }
5067        }
5068
5069        setOverScrollMode(overScrollMode);
5070
5071        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5072        // the resolved layout direction). Those cached values will be used later during padding
5073        // resolution.
5074        mUserPaddingStart = startPadding;
5075        mUserPaddingEnd = endPadding;
5076
5077        if (background != null) {
5078            setBackground(background);
5079        }
5080
5081        // setBackground above will record that padding is currently provided by the background.
5082        // If we have padding specified via xml, record that here instead and use it.
5083        mLeftPaddingDefined = leftPaddingDefined;
5084        mRightPaddingDefined = rightPaddingDefined;
5085
5086        if (padding >= 0) {
5087            leftPadding = padding;
5088            topPadding = padding;
5089            rightPadding = padding;
5090            bottomPadding = padding;
5091            mUserPaddingLeftInitial = padding;
5092            mUserPaddingRightInitial = padding;
5093        } else {
5094            if (paddingHorizontal >= 0) {
5095                leftPadding = paddingHorizontal;
5096                rightPadding = paddingHorizontal;
5097                mUserPaddingLeftInitial = paddingHorizontal;
5098                mUserPaddingRightInitial = paddingHorizontal;
5099            }
5100            if (paddingVertical >= 0) {
5101                topPadding = paddingVertical;
5102                bottomPadding = paddingVertical;
5103            }
5104        }
5105
5106        if (isRtlCompatibilityMode()) {
5107            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5108            // left / right padding are used if defined (meaning here nothing to do). If they are not
5109            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5110            // start / end and resolve them as left / right (layout direction is not taken into account).
5111            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5112            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5113            // defined.
5114            if (!mLeftPaddingDefined && startPaddingDefined) {
5115                leftPadding = startPadding;
5116            }
5117            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5118            if (!mRightPaddingDefined && endPaddingDefined) {
5119                rightPadding = endPadding;
5120            }
5121            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5122        } else {
5123            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5124            // values defined. Otherwise, left /right values are used.
5125            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5126            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5127            // defined.
5128            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5129
5130            if (mLeftPaddingDefined && !hasRelativePadding) {
5131                mUserPaddingLeftInitial = leftPadding;
5132            }
5133            if (mRightPaddingDefined && !hasRelativePadding) {
5134                mUserPaddingRightInitial = rightPadding;
5135            }
5136        }
5137
5138        internalSetPadding(
5139                mUserPaddingLeftInitial,
5140                topPadding >= 0 ? topPadding : mPaddingTop,
5141                mUserPaddingRightInitial,
5142                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5143
5144        if (viewFlagMasks != 0) {
5145            setFlags(viewFlagValues, viewFlagMasks);
5146        }
5147
5148        if (initializeScrollbars) {
5149            initializeScrollbarsInternal(a);
5150        }
5151
5152        if (initializeScrollIndicators) {
5153            initializeScrollIndicatorsInternal();
5154        }
5155
5156        a.recycle();
5157
5158        // Needs to be called after mViewFlags is set
5159        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5160            recomputePadding();
5161        }
5162
5163        if (x != 0 || y != 0) {
5164            scrollTo(x, y);
5165        }
5166
5167        if (transformSet) {
5168            setTranslationX(tx);
5169            setTranslationY(ty);
5170            setTranslationZ(tz);
5171            setElevation(elevation);
5172            setRotation(rotation);
5173            setRotationX(rotationX);
5174            setRotationY(rotationY);
5175            setScaleX(sx);
5176            setScaleY(sy);
5177        }
5178
5179        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5180            setScrollContainer(true);
5181        }
5182
5183        computeOpaqueFlags();
5184    }
5185
5186    /**
5187     * An implementation of OnClickListener that attempts to lazily load a
5188     * named click handling method from a parent or ancestor context.
5189     */
5190    private static class DeclaredOnClickListener implements OnClickListener {
5191        private final View mHostView;
5192        private final String mMethodName;
5193
5194        private Method mResolvedMethod;
5195        private Context mResolvedContext;
5196
5197        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5198            mHostView = hostView;
5199            mMethodName = methodName;
5200        }
5201
5202        @Override
5203        public void onClick(@NonNull View v) {
5204            if (mResolvedMethod == null) {
5205                resolveMethod(mHostView.getContext(), mMethodName);
5206            }
5207
5208            try {
5209                mResolvedMethod.invoke(mResolvedContext, v);
5210            } catch (IllegalAccessException e) {
5211                throw new IllegalStateException(
5212                        "Could not execute non-public method for android:onClick", e);
5213            } catch (InvocationTargetException e) {
5214                throw new IllegalStateException(
5215                        "Could not execute method for android:onClick", e);
5216            }
5217        }
5218
5219        @NonNull
5220        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5221            while (context != null) {
5222                try {
5223                    if (!context.isRestricted()) {
5224                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5225                        if (method != null) {
5226                            mResolvedMethod = method;
5227                            mResolvedContext = context;
5228                            return;
5229                        }
5230                    }
5231                } catch (NoSuchMethodException e) {
5232                    // Failed to find method, keep searching up the hierarchy.
5233                }
5234
5235                if (context instanceof ContextWrapper) {
5236                    context = ((ContextWrapper) context).getBaseContext();
5237                } else {
5238                    // Can't search up the hierarchy, null out and fail.
5239                    context = null;
5240                }
5241            }
5242
5243            final int id = mHostView.getId();
5244            final String idText = id == NO_ID ? "" : " with id '"
5245                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5246            throw new IllegalStateException("Could not find method " + mMethodName
5247                    + "(View) in a parent or ancestor Context for android:onClick "
5248                    + "attribute defined on view " + mHostView.getClass() + idText);
5249        }
5250    }
5251
5252    /**
5253     * Non-public constructor for use in testing
5254     */
5255    View() {
5256        mResources = null;
5257        mRenderNode = RenderNode.create(getClass().getName(), this);
5258    }
5259
5260    final boolean debugDraw() {
5261        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5262    }
5263
5264    private static SparseArray<String> getAttributeMap() {
5265        if (mAttributeMap == null) {
5266            mAttributeMap = new SparseArray<>();
5267        }
5268        return mAttributeMap;
5269    }
5270
5271    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5272        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5273        final int indexCount = t.getIndexCount();
5274        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5275
5276        int i = 0;
5277
5278        // Store raw XML attributes.
5279        for (int j = 0; j < attrsCount; ++j) {
5280            attributes[i] = attrs.getAttributeName(j);
5281            attributes[i + 1] = attrs.getAttributeValue(j);
5282            i += 2;
5283        }
5284
5285        // Store resolved styleable attributes.
5286        final Resources res = t.getResources();
5287        final SparseArray<String> attributeMap = getAttributeMap();
5288        for (int j = 0; j < indexCount; ++j) {
5289            final int index = t.getIndex(j);
5290            if (!t.hasValueOrEmpty(index)) {
5291                // Value is undefined. Skip it.
5292                continue;
5293            }
5294
5295            final int resourceId = t.getResourceId(index, 0);
5296            if (resourceId == 0) {
5297                // Value is not a reference. Skip it.
5298                continue;
5299            }
5300
5301            String resourceName = attributeMap.get(resourceId);
5302            if (resourceName == null) {
5303                try {
5304                    resourceName = res.getResourceName(resourceId);
5305                } catch (Resources.NotFoundException e) {
5306                    resourceName = "0x" + Integer.toHexString(resourceId);
5307                }
5308                attributeMap.put(resourceId, resourceName);
5309            }
5310
5311            attributes[i] = resourceName;
5312            attributes[i + 1] = t.getString(index);
5313            i += 2;
5314        }
5315
5316        // Trim to fit contents.
5317        final String[] trimmed = new String[i];
5318        System.arraycopy(attributes, 0, trimmed, 0, i);
5319        mAttributes = trimmed;
5320    }
5321
5322    public String toString() {
5323        StringBuilder out = new StringBuilder(128);
5324        out.append(getClass().getName());
5325        out.append('{');
5326        out.append(Integer.toHexString(System.identityHashCode(this)));
5327        out.append(' ');
5328        switch (mViewFlags&VISIBILITY_MASK) {
5329            case VISIBLE: out.append('V'); break;
5330            case INVISIBLE: out.append('I'); break;
5331            case GONE: out.append('G'); break;
5332            default: out.append('.'); break;
5333        }
5334        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5335        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5336        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5337        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5338        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5339        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5340        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5341        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5342        out.append(' ');
5343        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5344        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5345        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5346        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5347            out.append('p');
5348        } else {
5349            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5350        }
5351        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5352        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5353        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5354        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5355        out.append(' ');
5356        out.append(mLeft);
5357        out.append(',');
5358        out.append(mTop);
5359        out.append('-');
5360        out.append(mRight);
5361        out.append(',');
5362        out.append(mBottom);
5363        final int id = getId();
5364        if (id != NO_ID) {
5365            out.append(" #");
5366            out.append(Integer.toHexString(id));
5367            final Resources r = mResources;
5368            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5369                try {
5370                    String pkgname;
5371                    switch (id&0xff000000) {
5372                        case 0x7f000000:
5373                            pkgname="app";
5374                            break;
5375                        case 0x01000000:
5376                            pkgname="android";
5377                            break;
5378                        default:
5379                            pkgname = r.getResourcePackageName(id);
5380                            break;
5381                    }
5382                    String typename = r.getResourceTypeName(id);
5383                    String entryname = r.getResourceEntryName(id);
5384                    out.append(" ");
5385                    out.append(pkgname);
5386                    out.append(":");
5387                    out.append(typename);
5388                    out.append("/");
5389                    out.append(entryname);
5390                } catch (Resources.NotFoundException e) {
5391                }
5392            }
5393        }
5394        out.append("}");
5395        return out.toString();
5396    }
5397
5398    /**
5399     * <p>
5400     * Initializes the fading edges from a given set of styled attributes. This
5401     * method should be called by subclasses that need fading edges and when an
5402     * instance of these subclasses is created programmatically rather than
5403     * being inflated from XML. This method is automatically called when the XML
5404     * is inflated.
5405     * </p>
5406     *
5407     * @param a the styled attributes set to initialize the fading edges from
5408     *
5409     * @removed
5410     */
5411    protected void initializeFadingEdge(TypedArray a) {
5412        // This method probably shouldn't have been included in the SDK to begin with.
5413        // It relies on 'a' having been initialized using an attribute filter array that is
5414        // not publicly available to the SDK. The old method has been renamed
5415        // to initializeFadingEdgeInternal and hidden for framework use only;
5416        // this one initializes using defaults to make it safe to call for apps.
5417
5418        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5419
5420        initializeFadingEdgeInternal(arr);
5421
5422        arr.recycle();
5423    }
5424
5425    /**
5426     * <p>
5427     * Initializes the fading edges from a given set of styled attributes. This
5428     * method should be called by subclasses that need fading edges and when an
5429     * instance of these subclasses is created programmatically rather than
5430     * being inflated from XML. This method is automatically called when the XML
5431     * is inflated.
5432     * </p>
5433     *
5434     * @param a the styled attributes set to initialize the fading edges from
5435     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5436     */
5437    protected void initializeFadingEdgeInternal(TypedArray a) {
5438        initScrollCache();
5439
5440        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5441                R.styleable.View_fadingEdgeLength,
5442                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5443    }
5444
5445    /**
5446     * Returns the size of the vertical faded edges used to indicate that more
5447     * content in this view is visible.
5448     *
5449     * @return The size in pixels of the vertical faded edge or 0 if vertical
5450     *         faded edges are not enabled for this view.
5451     * @attr ref android.R.styleable#View_fadingEdgeLength
5452     */
5453    public int getVerticalFadingEdgeLength() {
5454        if (isVerticalFadingEdgeEnabled()) {
5455            ScrollabilityCache cache = mScrollCache;
5456            if (cache != null) {
5457                return cache.fadingEdgeLength;
5458            }
5459        }
5460        return 0;
5461    }
5462
5463    /**
5464     * Set the size of the faded edge used to indicate that more content in this
5465     * view is available.  Will not change whether the fading edge is enabled; use
5466     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5467     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5468     * for the vertical or horizontal fading edges.
5469     *
5470     * @param length The size in pixels of the faded edge used to indicate that more
5471     *        content in this view is visible.
5472     */
5473    public void setFadingEdgeLength(int length) {
5474        initScrollCache();
5475        mScrollCache.fadingEdgeLength = length;
5476    }
5477
5478    /**
5479     * Returns the size of the horizontal faded edges used to indicate that more
5480     * content in this view is visible.
5481     *
5482     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5483     *         faded edges are not enabled for this view.
5484     * @attr ref android.R.styleable#View_fadingEdgeLength
5485     */
5486    public int getHorizontalFadingEdgeLength() {
5487        if (isHorizontalFadingEdgeEnabled()) {
5488            ScrollabilityCache cache = mScrollCache;
5489            if (cache != null) {
5490                return cache.fadingEdgeLength;
5491            }
5492        }
5493        return 0;
5494    }
5495
5496    /**
5497     * Returns the width of the vertical scrollbar.
5498     *
5499     * @return The width in pixels of the vertical scrollbar or 0 if there
5500     *         is no vertical scrollbar.
5501     */
5502    public int getVerticalScrollbarWidth() {
5503        ScrollabilityCache cache = mScrollCache;
5504        if (cache != null) {
5505            ScrollBarDrawable scrollBar = cache.scrollBar;
5506            if (scrollBar != null) {
5507                int size = scrollBar.getSize(true);
5508                if (size <= 0) {
5509                    size = cache.scrollBarSize;
5510                }
5511                return size;
5512            }
5513            return 0;
5514        }
5515        return 0;
5516    }
5517
5518    /**
5519     * Returns the height of the horizontal scrollbar.
5520     *
5521     * @return The height in pixels of the horizontal scrollbar or 0 if
5522     *         there is no horizontal scrollbar.
5523     */
5524    protected int getHorizontalScrollbarHeight() {
5525        ScrollabilityCache cache = mScrollCache;
5526        if (cache != null) {
5527            ScrollBarDrawable scrollBar = cache.scrollBar;
5528            if (scrollBar != null) {
5529                int size = scrollBar.getSize(false);
5530                if (size <= 0) {
5531                    size = cache.scrollBarSize;
5532                }
5533                return size;
5534            }
5535            return 0;
5536        }
5537        return 0;
5538    }
5539
5540    /**
5541     * <p>
5542     * Initializes the scrollbars from a given set of styled attributes. This
5543     * method should be called by subclasses that need scrollbars and when an
5544     * instance of these subclasses is created programmatically rather than
5545     * being inflated from XML. This method is automatically called when the XML
5546     * is inflated.
5547     * </p>
5548     *
5549     * @param a the styled attributes set to initialize the scrollbars from
5550     *
5551     * @removed
5552     */
5553    protected void initializeScrollbars(TypedArray a) {
5554        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5555        // using the View filter array which is not available to the SDK. As such, internal
5556        // framework usage now uses initializeScrollbarsInternal and we grab a default
5557        // TypedArray with the right filter instead here.
5558        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5559
5560        initializeScrollbarsInternal(arr);
5561
5562        // We ignored the method parameter. Recycle the one we actually did use.
5563        arr.recycle();
5564    }
5565
5566    /**
5567     * <p>
5568     * Initializes the scrollbars from a given set of styled attributes. This
5569     * method should be called by subclasses that need scrollbars and when an
5570     * instance of these subclasses is created programmatically rather than
5571     * being inflated from XML. This method is automatically called when the XML
5572     * is inflated.
5573     * </p>
5574     *
5575     * @param a the styled attributes set to initialize the scrollbars from
5576     * @hide
5577     */
5578    protected void initializeScrollbarsInternal(TypedArray a) {
5579        initScrollCache();
5580
5581        final ScrollabilityCache scrollabilityCache = mScrollCache;
5582
5583        if (scrollabilityCache.scrollBar == null) {
5584            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5585            scrollabilityCache.scrollBar.setState(getDrawableState());
5586            scrollabilityCache.scrollBar.setCallback(this);
5587        }
5588
5589        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5590
5591        if (!fadeScrollbars) {
5592            scrollabilityCache.state = ScrollabilityCache.ON;
5593        }
5594        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5595
5596
5597        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5598                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5599                        .getScrollBarFadeDuration());
5600        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5601                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5602                ViewConfiguration.getScrollDefaultDelay());
5603
5604
5605        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5606                com.android.internal.R.styleable.View_scrollbarSize,
5607                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5608
5609        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5610        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5611
5612        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5613        if (thumb != null) {
5614            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5615        }
5616
5617        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5618                false);
5619        if (alwaysDraw) {
5620            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5621        }
5622
5623        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5624        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5625
5626        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5627        if (thumb != null) {
5628            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5629        }
5630
5631        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5632                false);
5633        if (alwaysDraw) {
5634            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5635        }
5636
5637        // Apply layout direction to the new Drawables if needed
5638        final int layoutDirection = getLayoutDirection();
5639        if (track != null) {
5640            track.setLayoutDirection(layoutDirection);
5641        }
5642        if (thumb != null) {
5643            thumb.setLayoutDirection(layoutDirection);
5644        }
5645
5646        // Re-apply user/background padding so that scrollbar(s) get added
5647        resolvePadding();
5648    }
5649
5650    private void initializeScrollIndicatorsInternal() {
5651        // Some day maybe we'll break this into top/left/start/etc. and let the
5652        // client control it. Until then, you can have any scroll indicator you
5653        // want as long as it's a 1dp foreground-colored rectangle.
5654        if (mScrollIndicatorDrawable == null) {
5655            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5656        }
5657    }
5658
5659    /**
5660     * <p>
5661     * Initalizes the scrollability cache if necessary.
5662     * </p>
5663     */
5664    private void initScrollCache() {
5665        if (mScrollCache == null) {
5666            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5667        }
5668    }
5669
5670    private ScrollabilityCache getScrollCache() {
5671        initScrollCache();
5672        return mScrollCache;
5673    }
5674
5675    /**
5676     * Set the position of the vertical scroll bar. Should be one of
5677     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5678     * {@link #SCROLLBAR_POSITION_RIGHT}.
5679     *
5680     * @param position Where the vertical scroll bar should be positioned.
5681     */
5682    public void setVerticalScrollbarPosition(int position) {
5683        if (mVerticalScrollbarPosition != position) {
5684            mVerticalScrollbarPosition = position;
5685            computeOpaqueFlags();
5686            resolvePadding();
5687        }
5688    }
5689
5690    /**
5691     * @return The position where the vertical scroll bar will show, if applicable.
5692     * @see #setVerticalScrollbarPosition(int)
5693     */
5694    public int getVerticalScrollbarPosition() {
5695        return mVerticalScrollbarPosition;
5696    }
5697
5698    boolean isOnScrollbar(float x, float y) {
5699        if (mScrollCache == null) {
5700            return false;
5701        }
5702        x += getScrollX();
5703        y += getScrollY();
5704        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5705            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5706            getVerticalScrollBarBounds(null, touchBounds);
5707            if (touchBounds.contains((int) x, (int) y)) {
5708                return true;
5709            }
5710        }
5711        if (isHorizontalScrollBarEnabled()) {
5712            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5713            getHorizontalScrollBarBounds(null, touchBounds);
5714            if (touchBounds.contains((int) x, (int) y)) {
5715                return true;
5716            }
5717        }
5718        return false;
5719    }
5720
5721    boolean isOnScrollbarThumb(float x, float y) {
5722        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5723    }
5724
5725    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5726        if (mScrollCache == null) {
5727            return false;
5728        }
5729        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5730            x += getScrollX();
5731            y += getScrollY();
5732            final Rect bounds = mScrollCache.mScrollBarBounds;
5733            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5734            getVerticalScrollBarBounds(bounds, touchBounds);
5735            final int range = computeVerticalScrollRange();
5736            final int offset = computeVerticalScrollOffset();
5737            final int extent = computeVerticalScrollExtent();
5738            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5739                    extent, range);
5740            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5741                    extent, range, offset);
5742            final int thumbTop = bounds.top + thumbOffset;
5743            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5744            if (x >= touchBounds.left && x <= touchBounds.right
5745                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5746                return true;
5747            }
5748        }
5749        return false;
5750    }
5751
5752    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5753        if (mScrollCache == null) {
5754            return false;
5755        }
5756        if (isHorizontalScrollBarEnabled()) {
5757            x += getScrollX();
5758            y += getScrollY();
5759            final Rect bounds = mScrollCache.mScrollBarBounds;
5760            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5761            getHorizontalScrollBarBounds(bounds, touchBounds);
5762            final int range = computeHorizontalScrollRange();
5763            final int offset = computeHorizontalScrollOffset();
5764            final int extent = computeHorizontalScrollExtent();
5765            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5766                    extent, range);
5767            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5768                    extent, range, offset);
5769            final int thumbLeft = bounds.left + thumbOffset;
5770            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5771            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5772                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5773                return true;
5774            }
5775        }
5776        return false;
5777    }
5778
5779    boolean isDraggingScrollBar() {
5780        return mScrollCache != null
5781                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5782    }
5783
5784    /**
5785     * Sets the state of all scroll indicators.
5786     * <p>
5787     * See {@link #setScrollIndicators(int, int)} for usage information.
5788     *
5789     * @param indicators a bitmask of indicators that should be enabled, or
5790     *                   {@code 0} to disable all indicators
5791     * @see #setScrollIndicators(int, int)
5792     * @see #getScrollIndicators()
5793     * @attr ref android.R.styleable#View_scrollIndicators
5794     */
5795    public void setScrollIndicators(@ScrollIndicators int indicators) {
5796        setScrollIndicators(indicators,
5797                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5798    }
5799
5800    /**
5801     * Sets the state of the scroll indicators specified by the mask. To change
5802     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5803     * <p>
5804     * When a scroll indicator is enabled, it will be displayed if the view
5805     * can scroll in the direction of the indicator.
5806     * <p>
5807     * Multiple indicator types may be enabled or disabled by passing the
5808     * logical OR of the desired types. If multiple types are specified, they
5809     * will all be set to the same enabled state.
5810     * <p>
5811     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5812     *
5813     * @param indicators the indicator direction, or the logical OR of multiple
5814     *             indicator directions. One or more of:
5815     *             <ul>
5816     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5817     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5818     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5819     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5820     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5821     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5822     *             </ul>
5823     * @see #setScrollIndicators(int)
5824     * @see #getScrollIndicators()
5825     * @attr ref android.R.styleable#View_scrollIndicators
5826     */
5827    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5828        // Shift and sanitize mask.
5829        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5830        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5831
5832        // Shift and mask indicators.
5833        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5834        indicators &= mask;
5835
5836        // Merge with non-masked flags.
5837        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5838
5839        if (mPrivateFlags3 != updatedFlags) {
5840            mPrivateFlags3 = updatedFlags;
5841
5842            if (indicators != 0) {
5843                initializeScrollIndicatorsInternal();
5844            }
5845            invalidate();
5846        }
5847    }
5848
5849    /**
5850     * Returns a bitmask representing the enabled scroll indicators.
5851     * <p>
5852     * For example, if the top and left scroll indicators are enabled and all
5853     * other indicators are disabled, the return value will be
5854     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5855     * <p>
5856     * To check whether the bottom scroll indicator is enabled, use the value
5857     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5858     *
5859     * @return a bitmask representing the enabled scroll indicators
5860     */
5861    @ScrollIndicators
5862    public int getScrollIndicators() {
5863        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5864                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5865    }
5866
5867    ListenerInfo getListenerInfo() {
5868        if (mListenerInfo != null) {
5869            return mListenerInfo;
5870        }
5871        mListenerInfo = new ListenerInfo();
5872        return mListenerInfo;
5873    }
5874
5875    /**
5876     * Register a callback to be invoked when the scroll X or Y positions of
5877     * this view change.
5878     * <p>
5879     * <b>Note:</b> Some views handle scrolling independently from View and may
5880     * have their own separate listeners for scroll-type events. For example,
5881     * {@link android.widget.ListView ListView} allows clients to register an
5882     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5883     * to listen for changes in list scroll position.
5884     *
5885     * @param l The listener to notify when the scroll X or Y position changes.
5886     * @see android.view.View#getScrollX()
5887     * @see android.view.View#getScrollY()
5888     */
5889    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5890        getListenerInfo().mOnScrollChangeListener = l;
5891    }
5892
5893    /**
5894     * Register a callback to be invoked when focus of this view changed.
5895     *
5896     * @param l The callback that will run.
5897     */
5898    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5899        getListenerInfo().mOnFocusChangeListener = l;
5900    }
5901
5902    /**
5903     * Add a listener that will be called when the bounds of the view change due to
5904     * layout processing.
5905     *
5906     * @param listener The listener that will be called when layout bounds change.
5907     */
5908    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5909        ListenerInfo li = getListenerInfo();
5910        if (li.mOnLayoutChangeListeners == null) {
5911            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5912        }
5913        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5914            li.mOnLayoutChangeListeners.add(listener);
5915        }
5916    }
5917
5918    /**
5919     * Remove a listener for layout changes.
5920     *
5921     * @param listener The listener for layout bounds change.
5922     */
5923    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5924        ListenerInfo li = mListenerInfo;
5925        if (li == null || li.mOnLayoutChangeListeners == null) {
5926            return;
5927        }
5928        li.mOnLayoutChangeListeners.remove(listener);
5929    }
5930
5931    /**
5932     * Add a listener for attach state changes.
5933     *
5934     * This listener will be called whenever this view is attached or detached
5935     * from a window. Remove the listener using
5936     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5937     *
5938     * @param listener Listener to attach
5939     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5940     */
5941    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5942        ListenerInfo li = getListenerInfo();
5943        if (li.mOnAttachStateChangeListeners == null) {
5944            li.mOnAttachStateChangeListeners
5945                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5946        }
5947        li.mOnAttachStateChangeListeners.add(listener);
5948    }
5949
5950    /**
5951     * Remove a listener for attach state changes. The listener will receive no further
5952     * notification of window attach/detach events.
5953     *
5954     * @param listener Listener to remove
5955     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5956     */
5957    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5958        ListenerInfo li = mListenerInfo;
5959        if (li == null || li.mOnAttachStateChangeListeners == null) {
5960            return;
5961        }
5962        li.mOnAttachStateChangeListeners.remove(listener);
5963    }
5964
5965    /**
5966     * Returns the focus-change callback registered for this view.
5967     *
5968     * @return The callback, or null if one is not registered.
5969     */
5970    public OnFocusChangeListener getOnFocusChangeListener() {
5971        ListenerInfo li = mListenerInfo;
5972        return li != null ? li.mOnFocusChangeListener : null;
5973    }
5974
5975    /**
5976     * Register a callback to be invoked when this view is clicked. If this view is not
5977     * clickable, it becomes clickable.
5978     *
5979     * @param l The callback that will run
5980     *
5981     * @see #setClickable(boolean)
5982     */
5983    public void setOnClickListener(@Nullable OnClickListener l) {
5984        if (!isClickable()) {
5985            setClickable(true);
5986        }
5987        getListenerInfo().mOnClickListener = l;
5988    }
5989
5990    /**
5991     * Return whether this view has an attached OnClickListener.  Returns
5992     * true if there is a listener, false if there is none.
5993     */
5994    public boolean hasOnClickListeners() {
5995        ListenerInfo li = mListenerInfo;
5996        return (li != null && li.mOnClickListener != null);
5997    }
5998
5999    /**
6000     * Register a callback to be invoked when this view is clicked and held. If this view is not
6001     * long clickable, it becomes long clickable.
6002     *
6003     * @param l The callback that will run
6004     *
6005     * @see #setLongClickable(boolean)
6006     */
6007    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6008        if (!isLongClickable()) {
6009            setLongClickable(true);
6010        }
6011        getListenerInfo().mOnLongClickListener = l;
6012    }
6013
6014    /**
6015     * Register a callback to be invoked when this view is context clicked. If the view is not
6016     * context clickable, it becomes context clickable.
6017     *
6018     * @param l The callback that will run
6019     * @see #setContextClickable(boolean)
6020     */
6021    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6022        if (!isContextClickable()) {
6023            setContextClickable(true);
6024        }
6025        getListenerInfo().mOnContextClickListener = l;
6026    }
6027
6028    /**
6029     * Register a callback to be invoked when the context menu for this view is
6030     * being built. If this view is not long clickable, it becomes long clickable.
6031     *
6032     * @param l The callback that will run
6033     *
6034     */
6035    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6036        if (!isLongClickable()) {
6037            setLongClickable(true);
6038        }
6039        getListenerInfo().mOnCreateContextMenuListener = l;
6040    }
6041
6042    /**
6043     * Set an observer to collect stats for each frame rendered for this view.
6044     *
6045     * @hide
6046     */
6047    public void addFrameMetricsListener(Window window,
6048            Window.OnFrameMetricsAvailableListener listener,
6049            Handler handler) {
6050        if (mAttachInfo != null) {
6051            if (mAttachInfo.mThreadedRenderer != null) {
6052                if (mFrameMetricsObservers == null) {
6053                    mFrameMetricsObservers = new ArrayList<>();
6054                }
6055
6056                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6057                        handler.getLooper(), listener);
6058                mFrameMetricsObservers.add(fmo);
6059                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6060            } else {
6061                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6062            }
6063        } else {
6064            if (mFrameMetricsObservers == null) {
6065                mFrameMetricsObservers = new ArrayList<>();
6066            }
6067
6068            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6069                    handler.getLooper(), listener);
6070            mFrameMetricsObservers.add(fmo);
6071        }
6072    }
6073
6074    /**
6075     * Remove observer configured to collect frame stats for this view.
6076     *
6077     * @hide
6078     */
6079    public void removeFrameMetricsListener(
6080            Window.OnFrameMetricsAvailableListener listener) {
6081        ThreadedRenderer renderer = getThreadedRenderer();
6082        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6083        if (fmo == null) {
6084            throw new IllegalArgumentException(
6085                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6086        }
6087
6088        if (mFrameMetricsObservers != null) {
6089            mFrameMetricsObservers.remove(fmo);
6090            if (renderer != null) {
6091                renderer.removeFrameMetricsObserver(fmo);
6092            }
6093        }
6094    }
6095
6096    private void registerPendingFrameMetricsObservers() {
6097        if (mFrameMetricsObservers != null) {
6098            ThreadedRenderer renderer = getThreadedRenderer();
6099            if (renderer != null) {
6100                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6101                    renderer.addFrameMetricsObserver(fmo);
6102                }
6103            } else {
6104                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6105            }
6106        }
6107    }
6108
6109    private FrameMetricsObserver findFrameMetricsObserver(
6110            Window.OnFrameMetricsAvailableListener listener) {
6111        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6112            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6113            if (observer.mListener == listener) {
6114                return observer;
6115            }
6116        }
6117
6118        return null;
6119    }
6120
6121    /**
6122     * Call this view's OnClickListener, if it is defined.  Performs all normal
6123     * actions associated with clicking: reporting accessibility event, playing
6124     * a sound, etc.
6125     *
6126     * @return True there was an assigned OnClickListener that was called, false
6127     *         otherwise is returned.
6128     */
6129    public boolean performClick() {
6130        final boolean result;
6131        final ListenerInfo li = mListenerInfo;
6132        if (li != null && li.mOnClickListener != null) {
6133            playSoundEffect(SoundEffectConstants.CLICK);
6134            li.mOnClickListener.onClick(this);
6135            result = true;
6136        } else {
6137            result = false;
6138        }
6139
6140        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6141
6142        notifyEnterOrExitForAutoFillIfNeeded(true);
6143
6144        return result;
6145    }
6146
6147    /**
6148     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6149     * this only calls the listener, and does not do any associated clicking
6150     * actions like reporting an accessibility event.
6151     *
6152     * @return True there was an assigned OnClickListener that was called, false
6153     *         otherwise is returned.
6154     */
6155    public boolean callOnClick() {
6156        ListenerInfo li = mListenerInfo;
6157        if (li != null && li.mOnClickListener != null) {
6158            li.mOnClickListener.onClick(this);
6159            return true;
6160        }
6161        return false;
6162    }
6163
6164    /**
6165     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6166     * context menu if the OnLongClickListener did not consume the event.
6167     *
6168     * @return {@code true} if one of the above receivers consumed the event,
6169     *         {@code false} otherwise
6170     */
6171    public boolean performLongClick() {
6172        return performLongClickInternal(mLongClickX, mLongClickY);
6173    }
6174
6175    /**
6176     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6177     * context menu if the OnLongClickListener did not consume the event,
6178     * anchoring it to an (x,y) coordinate.
6179     *
6180     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6181     *          to disable anchoring
6182     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6183     *          to disable anchoring
6184     * @return {@code true} if one of the above receivers consumed the event,
6185     *         {@code false} otherwise
6186     */
6187    public boolean performLongClick(float x, float y) {
6188        mLongClickX = x;
6189        mLongClickY = y;
6190        final boolean handled = performLongClick();
6191        mLongClickX = Float.NaN;
6192        mLongClickY = Float.NaN;
6193        return handled;
6194    }
6195
6196    /**
6197     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6198     * context menu if the OnLongClickListener did not consume the event,
6199     * optionally anchoring it to an (x,y) coordinate.
6200     *
6201     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6202     *          to disable anchoring
6203     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6204     *          to disable anchoring
6205     * @return {@code true} if one of the above receivers consumed the event,
6206     *         {@code false} otherwise
6207     */
6208    private boolean performLongClickInternal(float x, float y) {
6209        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6210
6211        boolean handled = false;
6212        final ListenerInfo li = mListenerInfo;
6213        if (li != null && li.mOnLongClickListener != null) {
6214            handled = li.mOnLongClickListener.onLongClick(View.this);
6215        }
6216        if (!handled) {
6217            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6218            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6219        }
6220        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6221            if (!handled) {
6222                handled = showLongClickTooltip((int) x, (int) y);
6223            }
6224        }
6225        if (handled) {
6226            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6227        }
6228        return handled;
6229    }
6230
6231    /**
6232     * Call this view's OnContextClickListener, if it is defined.
6233     *
6234     * @param x the x coordinate of the context click
6235     * @param y the y coordinate of the context click
6236     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6237     *         otherwise.
6238     */
6239    public boolean performContextClick(float x, float y) {
6240        return performContextClick();
6241    }
6242
6243    /**
6244     * Call this view's OnContextClickListener, if it is defined.
6245     *
6246     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6247     *         otherwise.
6248     */
6249    public boolean performContextClick() {
6250        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6251
6252        boolean handled = false;
6253        ListenerInfo li = mListenerInfo;
6254        if (li != null && li.mOnContextClickListener != null) {
6255            handled = li.mOnContextClickListener.onContextClick(View.this);
6256        }
6257        if (handled) {
6258            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6259        }
6260        return handled;
6261    }
6262
6263    /**
6264     * Performs button-related actions during a touch down event.
6265     *
6266     * @param event The event.
6267     * @return True if the down was consumed.
6268     *
6269     * @hide
6270     */
6271    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6272        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6273            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6274            showContextMenu(event.getX(), event.getY());
6275            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6276            return true;
6277        }
6278        return false;
6279    }
6280
6281    /**
6282     * Shows the context menu for this view.
6283     *
6284     * @return {@code true} if the context menu was shown, {@code false}
6285     *         otherwise
6286     * @see #showContextMenu(float, float)
6287     */
6288    public boolean showContextMenu() {
6289        return getParent().showContextMenuForChild(this);
6290    }
6291
6292    /**
6293     * Shows the context menu for this view anchored to the specified
6294     * view-relative coordinate.
6295     *
6296     * @param x the X coordinate in pixels relative to the view to which the
6297     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6298     * @param y the Y coordinate in pixels relative to the view to which the
6299     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6300     * @return {@code true} if the context menu was shown, {@code false}
6301     *         otherwise
6302     */
6303    public boolean showContextMenu(float x, float y) {
6304        return getParent().showContextMenuForChild(this, x, y);
6305    }
6306
6307    /**
6308     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6309     *
6310     * @param callback Callback that will control the lifecycle of the action mode
6311     * @return The new action mode if it is started, null otherwise
6312     *
6313     * @see ActionMode
6314     * @see #startActionMode(android.view.ActionMode.Callback, int)
6315     */
6316    public ActionMode startActionMode(ActionMode.Callback callback) {
6317        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6318    }
6319
6320    /**
6321     * Start an action mode with the given type.
6322     *
6323     * @param callback Callback that will control the lifecycle of the action mode
6324     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6325     * @return The new action mode if it is started, null otherwise
6326     *
6327     * @see ActionMode
6328     */
6329    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6330        ViewParent parent = getParent();
6331        if (parent == null) return null;
6332        try {
6333            return parent.startActionModeForChild(this, callback, type);
6334        } catch (AbstractMethodError ame) {
6335            // Older implementations of custom views might not implement this.
6336            return parent.startActionModeForChild(this, callback);
6337        }
6338    }
6339
6340    /**
6341     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6342     * Context, creating a unique View identifier to retrieve the result.
6343     *
6344     * @param intent The Intent to be started.
6345     * @param requestCode The request code to use.
6346     * @hide
6347     */
6348    public void startActivityForResult(Intent intent, int requestCode) {
6349        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6350        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6351    }
6352
6353    /**
6354     * If this View corresponds to the calling who, dispatches the activity result.
6355     * @param who The identifier for the targeted View to receive the result.
6356     * @param requestCode The integer request code originally supplied to
6357     *                    startActivityForResult(), allowing you to identify who this
6358     *                    result came from.
6359     * @param resultCode The integer result code returned by the child activity
6360     *                   through its setResult().
6361     * @param data An Intent, which can return result data to the caller
6362     *               (various data can be attached to Intent "extras").
6363     * @return {@code true} if the activity result was dispatched.
6364     * @hide
6365     */
6366    public boolean dispatchActivityResult(
6367            String who, int requestCode, int resultCode, Intent data) {
6368        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6369            onActivityResult(requestCode, resultCode, data);
6370            mStartActivityRequestWho = null;
6371            return true;
6372        }
6373        return false;
6374    }
6375
6376    /**
6377     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6378     *
6379     * @param requestCode The integer request code originally supplied to
6380     *                    startActivityForResult(), allowing you to identify who this
6381     *                    result came from.
6382     * @param resultCode The integer result code returned by the child activity
6383     *                   through its setResult().
6384     * @param data An Intent, which can return result data to the caller
6385     *               (various data can be attached to Intent "extras").
6386     * @hide
6387     */
6388    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6389        // Do nothing.
6390    }
6391
6392    /**
6393     * Register a callback to be invoked when a hardware key is pressed in this view.
6394     * Key presses in software input methods will generally not trigger the methods of
6395     * this listener.
6396     * @param l the key listener to attach to this view
6397     */
6398    public void setOnKeyListener(OnKeyListener l) {
6399        getListenerInfo().mOnKeyListener = l;
6400    }
6401
6402    /**
6403     * Register a callback to be invoked when a touch event is sent to this view.
6404     * @param l the touch listener to attach to this view
6405     */
6406    public void setOnTouchListener(OnTouchListener l) {
6407        getListenerInfo().mOnTouchListener = l;
6408    }
6409
6410    /**
6411     * Register a callback to be invoked when a generic motion event is sent to this view.
6412     * @param l the generic motion listener to attach to this view
6413     */
6414    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6415        getListenerInfo().mOnGenericMotionListener = l;
6416    }
6417
6418    /**
6419     * Register a callback to be invoked when a hover event is sent to this view.
6420     * @param l the hover listener to attach to this view
6421     */
6422    public void setOnHoverListener(OnHoverListener l) {
6423        getListenerInfo().mOnHoverListener = l;
6424    }
6425
6426    /**
6427     * Register a drag event listener callback object for this View. The parameter is
6428     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6429     * View, the system calls the
6430     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6431     * @param l An implementation of {@link android.view.View.OnDragListener}.
6432     */
6433    public void setOnDragListener(OnDragListener l) {
6434        getListenerInfo().mOnDragListener = l;
6435    }
6436
6437    /**
6438     * Give this view focus. This will cause
6439     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6440     *
6441     * Note: this does not check whether this {@link View} should get focus, it just
6442     * gives it focus no matter what.  It should only be called internally by framework
6443     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6444     *
6445     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6446     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6447     *        focus moved when requestFocus() is called. It may not always
6448     *        apply, in which case use the default View.FOCUS_DOWN.
6449     * @param previouslyFocusedRect The rectangle of the view that had focus
6450     *        prior in this View's coordinate system.
6451     */
6452    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6453        if (DBG) {
6454            System.out.println(this + " requestFocus()");
6455        }
6456
6457        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6458            mPrivateFlags |= PFLAG_FOCUSED;
6459
6460            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6461
6462            if (mParent != null) {
6463                mParent.requestChildFocus(this, this);
6464                setFocusedInCluster();
6465            }
6466
6467            if (mAttachInfo != null) {
6468                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6469            }
6470
6471            onFocusChanged(true, direction, previouslyFocusedRect);
6472            refreshDrawableState();
6473        }
6474    }
6475
6476    /**
6477     * Sets this view's preference for reveal behavior when it gains focus.
6478     *
6479     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6480     * this view would prefer to be brought fully into view when it gains focus.
6481     * For example, a text field that a user is meant to type into. Other views such
6482     * as scrolling containers may prefer to opt-out of this behavior.</p>
6483     *
6484     * <p>The default value for views is true, though subclasses may change this
6485     * based on their preferred behavior.</p>
6486     *
6487     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6488     *
6489     * @see #getRevealOnFocusHint()
6490     */
6491    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6492        if (revealOnFocus) {
6493            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6494        } else {
6495            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6496        }
6497    }
6498
6499    /**
6500     * Returns this view's preference for reveal behavior when it gains focus.
6501     *
6502     * <p>When this method returns true for a child view requesting focus, ancestor
6503     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6504     * should make a best effort to make the newly focused child fully visible to the user.
6505     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6506     * other properties affecting visibility to the user as part of the focus change.</p>
6507     *
6508     * @return true if this view would prefer to become fully visible when it gains focus,
6509     *         false if it would prefer not to disrupt scroll positioning
6510     *
6511     * @see #setRevealOnFocusHint(boolean)
6512     */
6513    public final boolean getRevealOnFocusHint() {
6514        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6515    }
6516
6517    /**
6518     * Populates <code>outRect</code> with the hotspot bounds. By default,
6519     * the hotspot bounds are identical to the screen bounds.
6520     *
6521     * @param outRect rect to populate with hotspot bounds
6522     * @hide Only for internal use by views and widgets.
6523     */
6524    public void getHotspotBounds(Rect outRect) {
6525        final Drawable background = getBackground();
6526        if (background != null) {
6527            background.getHotspotBounds(outRect);
6528        } else {
6529            getBoundsOnScreen(outRect);
6530        }
6531    }
6532
6533    /**
6534     * Request that a rectangle of this view be visible on the screen,
6535     * scrolling if necessary just enough.
6536     *
6537     * <p>A View should call this if it maintains some notion of which part
6538     * of its content is interesting.  For example, a text editing view
6539     * should call this when its cursor moves.
6540     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6541     * It should not be affected by which part of the View is currently visible or its scroll
6542     * position.
6543     *
6544     * @param rectangle The rectangle in the View's content coordinate space
6545     * @return Whether any parent scrolled.
6546     */
6547    public boolean requestRectangleOnScreen(Rect rectangle) {
6548        return requestRectangleOnScreen(rectangle, false);
6549    }
6550
6551    /**
6552     * Request that a rectangle of this view be visible on the screen,
6553     * scrolling if necessary just enough.
6554     *
6555     * <p>A View should call this if it maintains some notion of which part
6556     * of its content is interesting.  For example, a text editing view
6557     * should call this when its cursor moves.
6558     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6559     * It should not be affected by which part of the View is currently visible or its scroll
6560     * position.
6561     * <p>When <code>immediate</code> is set to true, scrolling will not be
6562     * animated.
6563     *
6564     * @param rectangle The rectangle in the View's content coordinate space
6565     * @param immediate True to forbid animated scrolling, false otherwise
6566     * @return Whether any parent scrolled.
6567     */
6568    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6569        if (mParent == null) {
6570            return false;
6571        }
6572
6573        View child = this;
6574
6575        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6576        position.set(rectangle);
6577
6578        ViewParent parent = mParent;
6579        boolean scrolled = false;
6580        while (parent != null) {
6581            rectangle.set((int) position.left, (int) position.top,
6582                    (int) position.right, (int) position.bottom);
6583
6584            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6585
6586            if (!(parent instanceof View)) {
6587                break;
6588            }
6589
6590            // move it from child's content coordinate space to parent's content coordinate space
6591            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6592
6593            child = (View) parent;
6594            parent = child.getParent();
6595        }
6596
6597        return scrolled;
6598    }
6599
6600    /**
6601     * Called when this view wants to give up focus. If focus is cleared
6602     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6603     * <p>
6604     * <strong>Note:</strong> When a View clears focus the framework is trying
6605     * to give focus to the first focusable View from the top. Hence, if this
6606     * View is the first from the top that can take focus, then all callbacks
6607     * related to clearing focus will be invoked after which the framework will
6608     * give focus to this view.
6609     * </p>
6610     */
6611    public void clearFocus() {
6612        if (DBG) {
6613            System.out.println(this + " clearFocus()");
6614        }
6615
6616        clearFocusInternal(null, true, true);
6617    }
6618
6619    /**
6620     * Clears focus from the view, optionally propagating the change up through
6621     * the parent hierarchy and requesting that the root view place new focus.
6622     *
6623     * @param propagate whether to propagate the change up through the parent
6624     *            hierarchy
6625     * @param refocus when propagate is true, specifies whether to request the
6626     *            root view place new focus
6627     */
6628    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6629        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6630            mPrivateFlags &= ~PFLAG_FOCUSED;
6631
6632            if (propagate && mParent != null) {
6633                mParent.clearChildFocus(this);
6634            }
6635
6636            onFocusChanged(false, 0, null);
6637            refreshDrawableState();
6638
6639            if (propagate && (!refocus || !rootViewRequestFocus())) {
6640                notifyGlobalFocusCleared(this);
6641            }
6642        }
6643    }
6644
6645    void notifyGlobalFocusCleared(View oldFocus) {
6646        if (oldFocus != null && mAttachInfo != null) {
6647            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6648        }
6649    }
6650
6651    boolean rootViewRequestFocus() {
6652        final View root = getRootView();
6653        return root != null && root.requestFocus();
6654    }
6655
6656    /**
6657     * Called internally by the view system when a new view is getting focus.
6658     * This is what clears the old focus.
6659     * <p>
6660     * <b>NOTE:</b> The parent view's focused child must be updated manually
6661     * after calling this method. Otherwise, the view hierarchy may be left in
6662     * an inconstent state.
6663     */
6664    void unFocus(View focused) {
6665        if (DBG) {
6666            System.out.println(this + " unFocus()");
6667        }
6668
6669        clearFocusInternal(focused, false, false);
6670    }
6671
6672    /**
6673     * Returns true if this view has focus itself, or is the ancestor of the
6674     * view that has focus.
6675     *
6676     * @return True if this view has or contains focus, false otherwise.
6677     */
6678    @ViewDebug.ExportedProperty(category = "focus")
6679    public boolean hasFocus() {
6680        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6681    }
6682
6683    /**
6684     * Returns true if this view is focusable or if it contains a reachable View
6685     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6686     * is a view whose parents do not block descendants focus.
6687     * Only {@link #VISIBLE} views are considered focusable.
6688     *
6689     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6690     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6691     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6692     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6693     * {@code false} for views not explicitly marked as focusable.
6694     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6695     * behavior.</p>
6696     *
6697     * @return {@code true} if the view is focusable or if the view contains a focusable
6698     *         view, {@code false} otherwise
6699     *
6700     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6701     * @see ViewGroup#getTouchscreenBlocksFocus()
6702     * @see #hasExplicitFocusable()
6703     */
6704    public boolean hasFocusable() {
6705        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6706    }
6707
6708    /**
6709     * Returns true if this view is focusable or if it contains a reachable View
6710     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6711     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6712     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6713     * {@link #FOCUSABLE} are considered focusable.
6714     *
6715     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6716     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6717     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6718     * to focusable will not.</p>
6719     *
6720     * @return {@code true} if the view is focusable or if the view contains a focusable
6721     *         view, {@code false} otherwise
6722     *
6723     * @see #hasFocusable()
6724     */
6725    public boolean hasExplicitFocusable() {
6726        return hasFocusable(false, true);
6727    }
6728
6729    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6730        if (!isFocusableInTouchMode()) {
6731            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6732                final ViewGroup g = (ViewGroup) p;
6733                if (g.shouldBlockFocusForTouchscreen()) {
6734                    return false;
6735                }
6736            }
6737        }
6738
6739        // Invisible and gone views are never focusable.
6740        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6741            return false;
6742        }
6743
6744        // Only use effective focusable value when allowed.
6745        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6746            return true;
6747        }
6748
6749        return false;
6750    }
6751
6752    /**
6753     * Called by the view system when the focus state of this view changes.
6754     * When the focus change event is caused by directional navigation, direction
6755     * and previouslyFocusedRect provide insight into where the focus is coming from.
6756     * When overriding, be sure to call up through to the super class so that
6757     * the standard focus handling will occur.
6758     *
6759     * @param gainFocus True if the View has focus; false otherwise.
6760     * @param direction The direction focus has moved when requestFocus()
6761     *                  is called to give this view focus. Values are
6762     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6763     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6764     *                  It may not always apply, in which case use the default.
6765     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6766     *        system, of the previously focused view.  If applicable, this will be
6767     *        passed in as finer grained information about where the focus is coming
6768     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6769     */
6770    @CallSuper
6771    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6772            @Nullable Rect previouslyFocusedRect) {
6773        if (gainFocus) {
6774            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6775        } else {
6776            notifyViewAccessibilityStateChangedIfNeeded(
6777                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6778        }
6779
6780        InputMethodManager imm = InputMethodManager.peekInstance();
6781        if (!gainFocus) {
6782            if (isPressed()) {
6783                setPressed(false);
6784            }
6785            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6786                imm.focusOut(this);
6787            }
6788            onFocusLost();
6789        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6790            imm.focusIn(this);
6791        }
6792
6793        invalidate(true);
6794        ListenerInfo li = mListenerInfo;
6795        if (li != null && li.mOnFocusChangeListener != null) {
6796            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6797        }
6798
6799        if (mAttachInfo != null) {
6800            mAttachInfo.mKeyDispatchState.reset(this);
6801        }
6802
6803        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6804    }
6805
6806    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6807        if (isAutofillable() && isAttachedToWindow()
6808                && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
6809            AutofillManager afm = getAutofillManager();
6810            if (afm != null) {
6811                if (enter && hasWindowFocus() && isFocused()) {
6812                    afm.notifyViewEntered(this);
6813                } else if (!hasWindowFocus() || !isFocused()) {
6814                    afm.notifyViewExited(this);
6815                }
6816            }
6817        }
6818    }
6819
6820    /**
6821     * Sends an accessibility event of the given type. If accessibility is
6822     * not enabled this method has no effect. The default implementation calls
6823     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6824     * to populate information about the event source (this View), then calls
6825     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6826     * populate the text content of the event source including its descendants,
6827     * and last calls
6828     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6829     * on its parent to request sending of the event to interested parties.
6830     * <p>
6831     * If an {@link AccessibilityDelegate} has been specified via calling
6832     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6833     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6834     * responsible for handling this call.
6835     * </p>
6836     *
6837     * @param eventType The type of the event to send, as defined by several types from
6838     * {@link android.view.accessibility.AccessibilityEvent}, such as
6839     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6840     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6841     *
6842     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6843     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6844     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6845     * @see AccessibilityDelegate
6846     */
6847    public void sendAccessibilityEvent(int eventType) {
6848        if (mAccessibilityDelegate != null) {
6849            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6850        } else {
6851            sendAccessibilityEventInternal(eventType);
6852        }
6853    }
6854
6855    /**
6856     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6857     * {@link AccessibilityEvent} to make an announcement which is related to some
6858     * sort of a context change for which none of the events representing UI transitions
6859     * is a good fit. For example, announcing a new page in a book. If accessibility
6860     * is not enabled this method does nothing.
6861     *
6862     * @param text The announcement text.
6863     */
6864    public void announceForAccessibility(CharSequence text) {
6865        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6866            AccessibilityEvent event = AccessibilityEvent.obtain(
6867                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6868            onInitializeAccessibilityEvent(event);
6869            event.getText().add(text);
6870            event.setContentDescription(null);
6871            mParent.requestSendAccessibilityEvent(this, event);
6872        }
6873    }
6874
6875    /**
6876     * @see #sendAccessibilityEvent(int)
6877     *
6878     * Note: Called from the default {@link AccessibilityDelegate}.
6879     *
6880     * @hide
6881     */
6882    public void sendAccessibilityEventInternal(int eventType) {
6883        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6884            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6885        }
6886    }
6887
6888    /**
6889     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6890     * takes as an argument an empty {@link AccessibilityEvent} and does not
6891     * perform a check whether accessibility is enabled.
6892     * <p>
6893     * If an {@link AccessibilityDelegate} has been specified via calling
6894     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6895     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6896     * is responsible for handling this call.
6897     * </p>
6898     *
6899     * @param event The event to send.
6900     *
6901     * @see #sendAccessibilityEvent(int)
6902     */
6903    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6904        if (mAccessibilityDelegate != null) {
6905            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6906        } else {
6907            sendAccessibilityEventUncheckedInternal(event);
6908        }
6909    }
6910
6911    /**
6912     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6913     *
6914     * Note: Called from the default {@link AccessibilityDelegate}.
6915     *
6916     * @hide
6917     */
6918    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6919        if (!isShown()) {
6920            return;
6921        }
6922        onInitializeAccessibilityEvent(event);
6923        // Only a subset of accessibility events populates text content.
6924        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6925            dispatchPopulateAccessibilityEvent(event);
6926        }
6927        // In the beginning we called #isShown(), so we know that getParent() is not null.
6928        getParent().requestSendAccessibilityEvent(this, event);
6929    }
6930
6931    /**
6932     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6933     * to its children for adding their text content to the event. Note that the
6934     * event text is populated in a separate dispatch path since we add to the
6935     * event not only the text of the source but also the text of all its descendants.
6936     * A typical implementation will call
6937     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6938     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6939     * on each child. Override this method if custom population of the event text
6940     * content is required.
6941     * <p>
6942     * If an {@link AccessibilityDelegate} has been specified via calling
6943     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6944     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6945     * is responsible for handling this call.
6946     * </p>
6947     * <p>
6948     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6949     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6950     * </p>
6951     *
6952     * @param event The event.
6953     *
6954     * @return True if the event population was completed.
6955     */
6956    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6957        if (mAccessibilityDelegate != null) {
6958            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6959        } else {
6960            return dispatchPopulateAccessibilityEventInternal(event);
6961        }
6962    }
6963
6964    /**
6965     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6966     *
6967     * Note: Called from the default {@link AccessibilityDelegate}.
6968     *
6969     * @hide
6970     */
6971    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6972        onPopulateAccessibilityEvent(event);
6973        return false;
6974    }
6975
6976    /**
6977     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6978     * giving a chance to this View to populate the accessibility event with its
6979     * text content. While this method is free to modify event
6980     * attributes other than text content, doing so should normally be performed in
6981     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6982     * <p>
6983     * Example: Adding formatted date string to an accessibility event in addition
6984     *          to the text added by the super implementation:
6985     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6986     *     super.onPopulateAccessibilityEvent(event);
6987     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6988     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6989     *         mCurrentDate.getTimeInMillis(), flags);
6990     *     event.getText().add(selectedDateUtterance);
6991     * }</pre>
6992     * <p>
6993     * If an {@link AccessibilityDelegate} has been specified via calling
6994     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6995     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6996     * is responsible for handling this call.
6997     * </p>
6998     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6999     * information to the event, in case the default implementation has basic information to add.
7000     * </p>
7001     *
7002     * @param event The accessibility event which to populate.
7003     *
7004     * @see #sendAccessibilityEvent(int)
7005     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7006     */
7007    @CallSuper
7008    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7009        if (mAccessibilityDelegate != null) {
7010            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7011        } else {
7012            onPopulateAccessibilityEventInternal(event);
7013        }
7014    }
7015
7016    /**
7017     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7018     *
7019     * Note: Called from the default {@link AccessibilityDelegate}.
7020     *
7021     * @hide
7022     */
7023    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7024    }
7025
7026    /**
7027     * Initializes an {@link AccessibilityEvent} with information about
7028     * this View which is the event source. In other words, the source of
7029     * an accessibility event is the view whose state change triggered firing
7030     * the event.
7031     * <p>
7032     * Example: Setting the password property of an event in addition
7033     *          to properties set by the super implementation:
7034     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7035     *     super.onInitializeAccessibilityEvent(event);
7036     *     event.setPassword(true);
7037     * }</pre>
7038     * <p>
7039     * If an {@link AccessibilityDelegate} has been specified via calling
7040     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7041     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7042     * is responsible for handling this call.
7043     * </p>
7044     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7045     * information to the event, in case the default implementation has basic information to add.
7046     * </p>
7047     * @param event The event to initialize.
7048     *
7049     * @see #sendAccessibilityEvent(int)
7050     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7051     */
7052    @CallSuper
7053    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7054        if (mAccessibilityDelegate != null) {
7055            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7056        } else {
7057            onInitializeAccessibilityEventInternal(event);
7058        }
7059    }
7060
7061    /**
7062     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7063     *
7064     * Note: Called from the default {@link AccessibilityDelegate}.
7065     *
7066     * @hide
7067     */
7068    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7069        event.setSource(this);
7070        event.setClassName(getAccessibilityClassName());
7071        event.setPackageName(getContext().getPackageName());
7072        event.setEnabled(isEnabled());
7073        event.setContentDescription(mContentDescription);
7074
7075        switch (event.getEventType()) {
7076            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7077                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7078                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7079                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7080                event.setItemCount(focusablesTempList.size());
7081                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7082                if (mAttachInfo != null) {
7083                    focusablesTempList.clear();
7084                }
7085            } break;
7086            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7087                CharSequence text = getIterableTextForAccessibility();
7088                if (text != null && text.length() > 0) {
7089                    event.setFromIndex(getAccessibilitySelectionStart());
7090                    event.setToIndex(getAccessibilitySelectionEnd());
7091                    event.setItemCount(text.length());
7092                }
7093            } break;
7094        }
7095    }
7096
7097    /**
7098     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7099     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7100     * This method is responsible for obtaining an accessibility node info from a
7101     * pool of reusable instances and calling
7102     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7103     * initialize the former.
7104     * <p>
7105     * Note: The client is responsible for recycling the obtained instance by calling
7106     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7107     * </p>
7108     *
7109     * @return A populated {@link AccessibilityNodeInfo}.
7110     *
7111     * @see AccessibilityNodeInfo
7112     */
7113    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7114        if (mAccessibilityDelegate != null) {
7115            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7116        } else {
7117            return createAccessibilityNodeInfoInternal();
7118        }
7119    }
7120
7121    /**
7122     * @see #createAccessibilityNodeInfo()
7123     *
7124     * @hide
7125     */
7126    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7127        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7128        if (provider != null) {
7129            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7130        } else {
7131            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7132            onInitializeAccessibilityNodeInfo(info);
7133            return info;
7134        }
7135    }
7136
7137    /**
7138     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7139     * The base implementation sets:
7140     * <ul>
7141     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7142     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7143     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7144     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7145     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7146     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7147     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7148     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7149     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7150     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7151     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7152     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7153     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7154     * </ul>
7155     * <p>
7156     * Subclasses should override this method, call the super implementation,
7157     * and set additional attributes.
7158     * </p>
7159     * <p>
7160     * If an {@link AccessibilityDelegate} has been specified via calling
7161     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7162     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7163     * is responsible for handling this call.
7164     * </p>
7165     *
7166     * @param info The instance to initialize.
7167     */
7168    @CallSuper
7169    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7170        if (mAccessibilityDelegate != null) {
7171            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7172        } else {
7173            onInitializeAccessibilityNodeInfoInternal(info);
7174        }
7175    }
7176
7177    /**
7178     * Gets the location of this view in screen coordinates.
7179     *
7180     * @param outRect The output location
7181     * @hide
7182     */
7183    public void getBoundsOnScreen(Rect outRect) {
7184        getBoundsOnScreen(outRect, false);
7185    }
7186
7187    /**
7188     * Gets the location of this view in screen coordinates.
7189     *
7190     * @param outRect The output location
7191     * @param clipToParent Whether to clip child bounds to the parent ones.
7192     * @hide
7193     */
7194    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7195        if (mAttachInfo == null) {
7196            return;
7197        }
7198
7199        RectF position = mAttachInfo.mTmpTransformRect;
7200        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7201
7202        if (!hasIdentityMatrix()) {
7203            getMatrix().mapRect(position);
7204        }
7205
7206        position.offset(mLeft, mTop);
7207
7208        ViewParent parent = mParent;
7209        while (parent instanceof View) {
7210            View parentView = (View) parent;
7211
7212            position.offset(-parentView.mScrollX, -parentView.mScrollY);
7213
7214            if (clipToParent) {
7215                position.left = Math.max(position.left, 0);
7216                position.top = Math.max(position.top, 0);
7217                position.right = Math.min(position.right, parentView.getWidth());
7218                position.bottom = Math.min(position.bottom, parentView.getHeight());
7219            }
7220
7221            if (!parentView.hasIdentityMatrix()) {
7222                parentView.getMatrix().mapRect(position);
7223            }
7224
7225            position.offset(parentView.mLeft, parentView.mTop);
7226
7227            parent = parentView.mParent;
7228        }
7229
7230        if (parent instanceof ViewRootImpl) {
7231            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7232            position.offset(0, -viewRootImpl.mCurScrollY);
7233        }
7234
7235        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7236
7237        outRect.set(Math.round(position.left), Math.round(position.top),
7238                Math.round(position.right), Math.round(position.bottom));
7239    }
7240
7241    /**
7242     * Return the class name of this object to be used for accessibility purposes.
7243     * Subclasses should only override this if they are implementing something that
7244     * should be seen as a completely new class of view when used by accessibility,
7245     * unrelated to the class it is deriving from.  This is used to fill in
7246     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7247     */
7248    public CharSequence getAccessibilityClassName() {
7249        return View.class.getName();
7250    }
7251
7252    /**
7253     * Called when assist structure is being retrieved from a view as part of
7254     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7255     * @param structure Fill in with structured view data.  The default implementation
7256     * fills in all data that can be inferred from the view itself.
7257     */
7258    public void onProvideStructure(ViewStructure structure) {
7259        onProvideStructureForAssistOrAutofill(structure, false);
7260    }
7261
7262    /**
7263     * Called when assist structure is being retrieved from a view as part of an autofill request.
7264     *
7265     * <p>This method already provides most of what's needed for autofill, but should be overridden
7266     * when:
7267     * <ol>
7268     * <li>The view contents does not include PII (Personally Identifiable Information), so it
7269     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7270     * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7271     * {@link ViewStructure#setAutofillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
7272     * </ol>
7273     *
7274     * @param structure Fill in with structured view data. The default implementation
7275     * fills in all data that can be inferred from the view itself.
7276     * @param flags optional flags (currently {@code 0}).
7277     */
7278    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
7279        onProvideStructureForAssistOrAutofill(structure, true);
7280    }
7281
7282    private void setAutofillId(ViewStructure structure) {
7283        // The autofill id needs to be unique, but its value doesn't matter,
7284        // so it's better to reuse the accessibility id to save space.
7285        structure.setAutofillId(getAccessibilityViewId());
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            setAutofillId(structure);
7308            final @AutofillType int autofillType = getAutofillType();
7309            // Don't need to fill autofill info if view does not support it.
7310            // For example, only TextViews that are editable support autofill
7311            if (autofillType != AUTOFILL_TYPE_NONE) {
7312                structure.setAutofillType(autofillType);
7313                structure.setAutofillHint(getAutofillHint());
7314                structure.setAutofillValue(getAutofillValue());
7315            }
7316        }
7317
7318        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
7319        if (!hasIdentityMatrix()) {
7320            structure.setTransformation(getMatrix());
7321        }
7322        structure.setElevation(getZ());
7323        structure.setVisibility(getVisibility());
7324        structure.setEnabled(isEnabled());
7325        if (isClickable()) {
7326            structure.setClickable(true);
7327        }
7328        if (isFocusable()) {
7329            structure.setFocusable(true);
7330        }
7331        if (isFocused()) {
7332            structure.setFocused(true);
7333        }
7334        if (isAccessibilityFocused()) {
7335            structure.setAccessibilityFocused(true);
7336        }
7337        if (isSelected()) {
7338            structure.setSelected(true);
7339        }
7340        if (isActivated()) {
7341            structure.setActivated(true);
7342        }
7343        if (isLongClickable()) {
7344            structure.setLongClickable(true);
7345        }
7346        if (this instanceof Checkable) {
7347            structure.setCheckable(true);
7348            if (((Checkable)this).isChecked()) {
7349                structure.setChecked(true);
7350            }
7351        }
7352        if (isOpaque()) {
7353            structure.setOpaque(true);
7354        }
7355        if (isContextClickable()) {
7356            structure.setContextClickable(true);
7357        }
7358        structure.setClassName(getAccessibilityClassName().toString());
7359        structure.setContentDescription(getContentDescription());
7360    }
7361
7362    /**
7363     * Called when assist structure is being retrieved from a view as part of
7364     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7365     * generate additional virtual structure under this view.  The defaullt implementation
7366     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7367     * view's virtual accessibility nodes, if any.  You can override this for a more
7368     * optimal implementation providing this data.
7369     */
7370    public void onProvideVirtualStructure(ViewStructure structure) {
7371        onProvideVirtualStructureForAssistOrAutofill(structure, false);
7372    }
7373
7374    /**
7375     * Called when assist structure is being retrieved from a view as part of an autofill request
7376     * to generate additional virtual structure under this view.
7377     *
7378     * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
7379     * generate this from the view's virtual accessibility nodes, if any. You can override this
7380     * for a more optimal implementation providing this data.
7381     *
7382     * <p>When implementing this method, subclasses must follow the rules below:
7383     *
7384     * <ol>
7385     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7386     * children.
7387     * <li>Call
7388     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7389     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7390     * when the focus inside the view changed.
7391     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7392     * AutofillValue)} when the value of a child changed.
7393     * <li>Call {@link AutofillManager#commit()} when the autofill context
7394     * of the view structure changed and you want the current autofill interaction if such
7395     * to be commited.
7396     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7397     * of the view structure changed and you want the current autofill interaction if such
7398     * to be cancelled.
7399     * </ol>
7400     *
7401     * @param structure Fill in with structured view data.
7402     * @param flags optional flags (currently {@code 0}).
7403     */
7404    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7405        onProvideVirtualStructureForAssistOrAutofill(structure, true);
7406    }
7407
7408    private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure,
7409            boolean forAutofill) {
7410        if (forAutofill) {
7411            setAutofillId(structure);
7412        }
7413        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7414        // this method should take a boolean with the type of request.
7415        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7416        if (provider != null) {
7417            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7418            structure.setChildCount(1);
7419            ViewStructure root = structure.newChild(0);
7420            populateVirtualStructure(root, provider, info, forAutofill);
7421            info.recycle();
7422        }
7423    }
7424
7425    /**
7426     * Automatically fills the content of this view with the {@code value}.
7427     *
7428     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7429     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7430     * to support the Autofill Framework.
7431     *
7432     * <p>Typically, it is implemented by:
7433     *
7434     * <ol>
7435     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7436     * <li>Passing the actual value to the equivalent setter in the view.
7437     * <ol>
7438     *
7439     * <p>For example, a text-field view would call:
7440     *
7441     * <pre class="prettyprint">
7442     * CharSequence text = value.getTextValue();
7443     * if (text != null) {
7444     *     setText(text);
7445     * }
7446     * </pre>
7447     *
7448     * @param value value to be autofilled.
7449     *
7450     * @return {@code true} if the view was successfully autofilled, {@code false} otherwise
7451     */
7452    public boolean autofill(@SuppressWarnings("unused") AutofillValue value) {
7453        return false;
7454    }
7455
7456    /**
7457     * Automatically fills the content of a virtual views.
7458     *
7459     * <p>See {@link #autofill(AutofillValue)} and
7460     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7461     *
7462     * @param values map of values to be autofilled, keyed by virtual child id.
7463     *
7464     * @return {@code true} if the view was successfully autofilled, {@code false} otherwise
7465     */
7466    public boolean autofill(
7467            @NonNull @SuppressWarnings("unused") SparseArray<AutofillValue>values) {
7468        return false;
7469    }
7470
7471    /**
7472     * Describes the autofill type that should be used on calls to
7473     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7474     *
7475     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7476     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7477     */
7478    public @AutofillType int getAutofillType() {
7479        return AUTOFILL_TYPE_NONE;
7480    }
7481
7482    /**
7483     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7484     *
7485     * @return The hint set via the attribute or {@code null} if no hint it set.
7486     *
7487     * @attr ref android.R.styleable#View_autofillHint
7488     */
7489    @ViewDebug.ExportedProperty()
7490    @Nullable public String[] getAutofillHint() {
7491        return mAutofillHint;
7492    }
7493
7494    /**
7495     * Gets the {@link View}'s current autofill value.
7496     *
7497     * <p>By default returns {@code null}, but views should override it (and
7498     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7499     * Framework.
7500     */
7501    @Nullable
7502    public AutofillValue getAutofillValue() {
7503        return null;
7504    }
7505
7506    /**
7507     * Gets the mode for determining whether this View is important for autofill.
7508     *
7509     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7510     *
7511     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7512     * {@link #setImportantForAutofill(int)}.
7513     *
7514     * @attr ref android.R.styleable#View_importantForAutofill
7515     */
7516    @ViewDebug.ExportedProperty(mapping = {
7517            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7518            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7519            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
7520    public @AutofillImportance int getImportantForAutofill() {
7521        return (mPrivateFlags3
7522                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7523    }
7524
7525    /**
7526     * Sets the mode for determining whether this View is important for autofill.
7527     *
7528     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7529     *
7530     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7531     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7532     *
7533     * @attr ref android.R.styleable#View_importantForAutofill
7534     */
7535    public void setImportantForAutofill(@AutofillImportance int mode) {
7536        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7537        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7538                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7539    }
7540
7541    /**
7542     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7543     * associated with this View should be included in a {@link ViewStructure} used for
7544     * autofill purposes.
7545     *
7546     * <p>Generally speaking, a view is important for autofill if:
7547     * <ol>
7548     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7549     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7550     * autofill other views.
7551     * <ol>
7552     *
7553     * <p>For example, view containers should typically return {@code false} for performance reasons
7554     * (since the important info is provided by their children), but if the container is actually
7555     * whose children are part of a compound view, it should return {@code true} (and then override
7556     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7557     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7558     * the structure). On the other hand, views representing labels or editable fields should
7559     * typically return {@code true}, but in some cases they could return {@code false} (for
7560     * example, if they're part of a "Captcha" mechanism).
7561     *
7562     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7563     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7564     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7565     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7566     * should use {@link #setImportantForAutofill(int)} instead.
7567     *
7568     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7569     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
7570     * View might be always included.
7571     *
7572     * <p>This decision applies just for the view, not its children - if the view children are not
7573     * important for autofill, the view should override
7574     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7575     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7576     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7577     *
7578     * @return whether the view is considered important for autofill.
7579     *
7580     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7581     * @see #IMPORTANT_FOR_AUTOFILL_YES
7582     * @see #IMPORTANT_FOR_AUTOFILL_NO
7583     */
7584    public final boolean isImportantForAutofill() {
7585        final int flag = getImportantForAutofill();
7586
7587        // First, check if view explicity set it to YES or NO
7588        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
7589            return true;
7590        }
7591        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
7592            return false;
7593        }
7594
7595        // Then use some heuristics to handle AUTO.
7596
7597        // Always include views that have a explicity resource id.
7598        final int id = mID;
7599        if (id != NO_ID && !isViewIdGenerated(id)) {
7600            final Resources res = getResources();
7601            String entry = null;
7602            String pkg = null;
7603            try {
7604                entry = res.getResourceEntryName(id);
7605                pkg = res.getResourcePackageName(id);
7606            } catch (Resources.NotFoundException e) {
7607                // ignore
7608            }
7609            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7610                return true;
7611            }
7612        }
7613
7614        // Otherwise, assume it's not important...
7615        return false;
7616    }
7617
7618    @Nullable
7619    private AutofillManager getAutofillManager() {
7620        return mContext.getSystemService(AutofillManager.class);
7621    }
7622
7623    private boolean isAutofillable() {
7624        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
7625    }
7626
7627    private void populateVirtualStructure(ViewStructure structure,
7628            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) {
7629        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7630                null, null, null);
7631        Rect rect = structure.getTempRect();
7632        info.getBoundsInParent(rect);
7633        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7634        structure.setVisibility(VISIBLE);
7635        structure.setEnabled(info.isEnabled());
7636        if (info.isClickable()) {
7637            structure.setClickable(true);
7638        }
7639        if (info.isFocusable()) {
7640            structure.setFocusable(true);
7641        }
7642        if (info.isFocused()) {
7643            structure.setFocused(true);
7644        }
7645        if (info.isAccessibilityFocused()) {
7646            structure.setAccessibilityFocused(true);
7647        }
7648        if (info.isSelected()) {
7649            structure.setSelected(true);
7650        }
7651        if (info.isLongClickable()) {
7652            structure.setLongClickable(true);
7653        }
7654        if (info.isCheckable()) {
7655            structure.setCheckable(true);
7656            if (info.isChecked()) {
7657                structure.setChecked(true);
7658            }
7659        }
7660        if (info.isContextClickable()) {
7661            structure.setContextClickable(true);
7662        }
7663        CharSequence cname = info.getClassName();
7664        structure.setClassName(cname != null ? cname.toString() : null);
7665        structure.setContentDescription(info.getContentDescription());
7666        if (!forAutofill && (info.getText() != null || info.getError() != null)) {
7667            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7668            // just set sanitized values (like text coming from resource files), rather than not
7669            // setting it at all.
7670            structure.setText(info.getText(), info.getTextSelectionStart(),
7671                    info.getTextSelectionEnd());
7672        }
7673        final int NCHILDREN = info.getChildCount();
7674        if (NCHILDREN > 0) {
7675            structure.setChildCount(NCHILDREN);
7676            for (int i=0; i<NCHILDREN; i++) {
7677                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7678                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7679                ViewStructure child = structure.newChild(i);
7680                if (forAutofill) {
7681                    // TODO(b/33197203): add CTS test to autofill virtual children based on
7682                    // Accessibility API.
7683                    child.setAutofillId(structure, i);
7684                }
7685                populateVirtualStructure(child, provider, cinfo, forAutofill);
7686                cinfo.recycle();
7687            }
7688        }
7689    }
7690
7691    /**
7692     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7693     * implementation calls {@link #onProvideStructure} and
7694     * {@link #onProvideVirtualStructure}.
7695     */
7696    public void dispatchProvideStructure(ViewStructure structure) {
7697        dispatchProvideStructureForAssistOrAutofill(structure, false);
7698    }
7699
7700    /**
7701     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7702     *
7703     * <p>The structure must be filled according to the request type, which is set in the
7704     * {@code flags} parameter - see the documentation on each flag for more details.
7705     *
7706     * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
7707     * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7708     *
7709     * @param structure Fill in with structured view data.
7710     * @param flags optional flags (currently {@code 0}).
7711     */
7712    public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
7713        dispatchProvideStructureForAssistOrAutofill(structure, true);
7714    }
7715
7716    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7717            boolean forAutofill) {
7718        boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
7719        if (!blocked) {
7720            if (forAutofill) {
7721                setAutofillId(structure);
7722                // NOTE: flags are not currently supported, hence 0
7723                onProvideAutofillStructure(structure, 0);
7724                onProvideAutofillVirtualStructure(structure, 0);
7725            } else {
7726                onProvideStructure(structure);
7727                onProvideVirtualStructure(structure);
7728            }
7729        } else {
7730            structure.setClassName(getAccessibilityClassName().toString());
7731            structure.setAssistBlocked(true);
7732        }
7733    }
7734
7735    /**
7736     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7737     *
7738     * Note: Called from the default {@link AccessibilityDelegate}.
7739     *
7740     * @hide
7741     */
7742    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7743        if (mAttachInfo == null) {
7744            return;
7745        }
7746
7747        Rect bounds = mAttachInfo.mTmpInvalRect;
7748
7749        getDrawingRect(bounds);
7750        info.setBoundsInParent(bounds);
7751
7752        getBoundsOnScreen(bounds, true);
7753        info.setBoundsInScreen(bounds);
7754
7755        ViewParent parent = getParentForAccessibility();
7756        if (parent instanceof View) {
7757            info.setParent((View) parent);
7758        }
7759
7760        if (mID != View.NO_ID) {
7761            View rootView = getRootView();
7762            if (rootView == null) {
7763                rootView = this;
7764            }
7765
7766            View label = rootView.findLabelForView(this, mID);
7767            if (label != null) {
7768                info.setLabeledBy(label);
7769            }
7770
7771            if ((mAttachInfo.mAccessibilityFetchFlags
7772                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7773                    && Resources.resourceHasPackage(mID)) {
7774                try {
7775                    String viewId = getResources().getResourceName(mID);
7776                    info.setViewIdResourceName(viewId);
7777                } catch (Resources.NotFoundException nfe) {
7778                    /* ignore */
7779                }
7780            }
7781        }
7782
7783        if (mLabelForId != View.NO_ID) {
7784            View rootView = getRootView();
7785            if (rootView == null) {
7786                rootView = this;
7787            }
7788            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7789            if (labeled != null) {
7790                info.setLabelFor(labeled);
7791            }
7792        }
7793
7794        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7795            View rootView = getRootView();
7796            if (rootView == null) {
7797                rootView = this;
7798            }
7799            View next = rootView.findViewInsideOutShouldExist(this,
7800                    mAccessibilityTraversalBeforeId);
7801            if (next != null && next.includeForAccessibility()) {
7802                info.setTraversalBefore(next);
7803            }
7804        }
7805
7806        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7807            View rootView = getRootView();
7808            if (rootView == null) {
7809                rootView = this;
7810            }
7811            View next = rootView.findViewInsideOutShouldExist(this,
7812                    mAccessibilityTraversalAfterId);
7813            if (next != null && next.includeForAccessibility()) {
7814                info.setTraversalAfter(next);
7815            }
7816        }
7817
7818        info.setVisibleToUser(isVisibleToUser());
7819
7820        info.setImportantForAccessibility(isImportantForAccessibility());
7821        info.setPackageName(mContext.getPackageName());
7822        info.setClassName(getAccessibilityClassName());
7823        info.setContentDescription(getContentDescription());
7824
7825        info.setEnabled(isEnabled());
7826        info.setClickable(isClickable());
7827        info.setFocusable(isFocusable());
7828        info.setFocused(isFocused());
7829        info.setAccessibilityFocused(isAccessibilityFocused());
7830        info.setSelected(isSelected());
7831        info.setLongClickable(isLongClickable());
7832        info.setContextClickable(isContextClickable());
7833        info.setLiveRegion(getAccessibilityLiveRegion());
7834
7835        // TODO: These make sense only if we are in an AdapterView but all
7836        // views can be selected. Maybe from accessibility perspective
7837        // we should report as selectable view in an AdapterView.
7838        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7839        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7840
7841        if (isFocusable()) {
7842            if (isFocused()) {
7843                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7844            } else {
7845                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7846            }
7847        }
7848
7849        if (!isAccessibilityFocused()) {
7850            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7851        } else {
7852            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7853        }
7854
7855        if (isClickable() && isEnabled()) {
7856            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7857        }
7858
7859        if (isLongClickable() && isEnabled()) {
7860            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7861        }
7862
7863        if (isContextClickable() && isEnabled()) {
7864            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7865        }
7866
7867        CharSequence text = getIterableTextForAccessibility();
7868        if (text != null && text.length() > 0) {
7869            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7870
7871            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7872            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7873            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7874            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7875                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7876                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7877        }
7878
7879        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7880        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7881    }
7882
7883    /**
7884     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7885     * additional data.
7886     * <p>
7887     * This method only needs overloading if the node is marked as having extra data available.
7888     * </p>
7889     *
7890     * @param info The info to which to add the extra data. Never {@code null}.
7891     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7892     *                     extra data should be added to the {@link Bundle} returned by
7893     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7894     *                     {@code null}.
7895     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7896     *                  {@code null} if the service provided no arguments.
7897     *
7898     * @see AccessibilityNodeInfo#setExtraAvailableData
7899     */
7900    public void addExtraDataToAccessibilityNodeInfo(
7901            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7902            @Nullable Bundle arguments) {
7903    }
7904
7905    /**
7906     * Determine the order in which this view will be drawn relative to its siblings for a11y
7907     *
7908     * @param info The info whose drawing order should be populated
7909     */
7910    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7911        /*
7912         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7913         * drawing order may not be well-defined, and some Views with custom drawing order may
7914         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7915         */
7916        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7917            info.setDrawingOrder(0);
7918            return;
7919        }
7920        int drawingOrderInParent = 1;
7921        // Iterate up the hierarchy if parents are not important for a11y
7922        View viewAtDrawingLevel = this;
7923        final ViewParent parent = getParentForAccessibility();
7924        while (viewAtDrawingLevel != parent) {
7925            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7926            if (!(currentParent instanceof ViewGroup)) {
7927                // Should only happen for the Decor
7928                drawingOrderInParent = 0;
7929                break;
7930            } else {
7931                final ViewGroup parentGroup = (ViewGroup) currentParent;
7932                final int childCount = parentGroup.getChildCount();
7933                if (childCount > 1) {
7934                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7935                    if (preorderedList != null) {
7936                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7937                        for (int i = 0; i < childDrawIndex; i++) {
7938                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7939                        }
7940                    } else {
7941                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7942                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7943                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7944                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7945                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7946                        if (childDrawIndex != 0) {
7947                            for (int i = 0; i < numChildrenToIterate; i++) {
7948                                final int otherDrawIndex = (customOrder ?
7949                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7950                                if (otherDrawIndex < childDrawIndex) {
7951                                    drawingOrderInParent +=
7952                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7953                                }
7954                            }
7955                        }
7956                    }
7957                }
7958            }
7959            viewAtDrawingLevel = (View) currentParent;
7960        }
7961        info.setDrawingOrder(drawingOrderInParent);
7962    }
7963
7964    private static int numViewsForAccessibility(View view) {
7965        if (view != null) {
7966            if (view.includeForAccessibility()) {
7967                return 1;
7968            } else if (view instanceof ViewGroup) {
7969                return ((ViewGroup) view).getNumChildrenForAccessibility();
7970            }
7971        }
7972        return 0;
7973    }
7974
7975    private View findLabelForView(View view, int labeledId) {
7976        if (mMatchLabelForPredicate == null) {
7977            mMatchLabelForPredicate = new MatchLabelForPredicate();
7978        }
7979        mMatchLabelForPredicate.mLabeledId = labeledId;
7980        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7981    }
7982
7983    /**
7984     * Computes whether this view is visible to the user. Such a view is
7985     * attached, visible, all its predecessors are visible, it is not clipped
7986     * entirely by its predecessors, and has an alpha greater than zero.
7987     *
7988     * @return Whether the view is visible on the screen.
7989     *
7990     * @hide
7991     */
7992    protected boolean isVisibleToUser() {
7993        return isVisibleToUser(null);
7994    }
7995
7996    /**
7997     * Computes whether the given portion of this view is visible to the user.
7998     * Such a view is attached, visible, all its predecessors are visible,
7999     * has an alpha greater than zero, and the specified portion is not
8000     * clipped entirely by its predecessors.
8001     *
8002     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8003     *                    <code>null</code>, and the entire view will be tested in this case.
8004     *                    When <code>true</code> is returned by the function, the actual visible
8005     *                    region will be stored in this parameter; that is, if boundInView is fully
8006     *                    contained within the view, no modification will be made, otherwise regions
8007     *                    outside of the visible area of the view will be clipped.
8008     *
8009     * @return Whether the specified portion of the view is visible on the screen.
8010     *
8011     * @hide
8012     */
8013    protected boolean isVisibleToUser(Rect boundInView) {
8014        if (mAttachInfo != null) {
8015            // Attached to invisible window means this view is not visible.
8016            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8017                return false;
8018            }
8019            // An invisible predecessor or one with alpha zero means
8020            // that this view is not visible to the user.
8021            Object current = this;
8022            while (current instanceof View) {
8023                View view = (View) current;
8024                // We have attach info so this view is attached and there is no
8025                // need to check whether we reach to ViewRootImpl on the way up.
8026                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8027                        view.getVisibility() != VISIBLE) {
8028                    return false;
8029                }
8030                current = view.mParent;
8031            }
8032            // Check if the view is entirely covered by its predecessors.
8033            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8034            Point offset = mAttachInfo.mPoint;
8035            if (!getGlobalVisibleRect(visibleRect, offset)) {
8036                return false;
8037            }
8038            // Check if the visible portion intersects the rectangle of interest.
8039            if (boundInView != null) {
8040                visibleRect.offset(-offset.x, -offset.y);
8041                return boundInView.intersect(visibleRect);
8042            }
8043            return true;
8044        }
8045        return false;
8046    }
8047
8048    /**
8049     * Returns the delegate for implementing accessibility support via
8050     * composition. For more details see {@link AccessibilityDelegate}.
8051     *
8052     * @return The delegate, or null if none set.
8053     *
8054     * @hide
8055     */
8056    public AccessibilityDelegate getAccessibilityDelegate() {
8057        return mAccessibilityDelegate;
8058    }
8059
8060    /**
8061     * Sets a delegate for implementing accessibility support via composition
8062     * (as opposed to inheritance). For more details, see
8063     * {@link AccessibilityDelegate}.
8064     * <p>
8065     * <strong>Note:</strong> On platform versions prior to
8066     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8067     * views in the {@code android.widget.*} package are called <i>before</i>
8068     * host methods. This prevents certain properties such as class name from
8069     * being modified by overriding
8070     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8071     * as any changes will be overwritten by the host class.
8072     * <p>
8073     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8074     * methods are called <i>after</i> host methods, which all properties to be
8075     * modified without being overwritten by the host class.
8076     *
8077     * @param delegate the object to which accessibility method calls should be
8078     *                 delegated
8079     * @see AccessibilityDelegate
8080     */
8081    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8082        mAccessibilityDelegate = delegate;
8083    }
8084
8085    /**
8086     * Gets the provider for managing a virtual view hierarchy rooted at this View
8087     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8088     * that explore the window content.
8089     * <p>
8090     * If this method returns an instance, this instance is responsible for managing
8091     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8092     * View including the one representing the View itself. Similarly the returned
8093     * instance is responsible for performing accessibility actions on any virtual
8094     * view or the root view itself.
8095     * </p>
8096     * <p>
8097     * If an {@link AccessibilityDelegate} has been specified via calling
8098     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8099     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8100     * is responsible for handling this call.
8101     * </p>
8102     *
8103     * @return The provider.
8104     *
8105     * @see AccessibilityNodeProvider
8106     */
8107    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8108        if (mAccessibilityDelegate != null) {
8109            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8110        } else {
8111            return null;
8112        }
8113    }
8114
8115    /**
8116     * Gets the unique identifier of this view on the screen for accessibility purposes.
8117     *
8118     * @return The view accessibility id.
8119     *
8120     * @hide
8121     */
8122    public int getAccessibilityViewId() {
8123        if (mAccessibilityViewId == NO_ID) {
8124            mAccessibilityViewId = sNextAccessibilityViewId++;
8125        }
8126        return mAccessibilityViewId;
8127    }
8128
8129    /**
8130     * Gets the unique identifier of the window in which this View reseides.
8131     *
8132     * @return The window accessibility id.
8133     *
8134     * @hide
8135     */
8136    public int getAccessibilityWindowId() {
8137        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8138                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8139    }
8140
8141    /**
8142     * Returns the {@link View}'s content description.
8143     * <p>
8144     * <strong>Note:</strong> Do not override this method, as it will have no
8145     * effect on the content description presented to accessibility services.
8146     * You must call {@link #setContentDescription(CharSequence)} to modify the
8147     * content description.
8148     *
8149     * @return the content description
8150     * @see #setContentDescription(CharSequence)
8151     * @attr ref android.R.styleable#View_contentDescription
8152     */
8153    @ViewDebug.ExportedProperty(category = "accessibility")
8154    public CharSequence getContentDescription() {
8155        return mContentDescription;
8156    }
8157
8158    /**
8159     * Sets the {@link View}'s content description.
8160     * <p>
8161     * A content description briefly describes the view and is primarily used
8162     * for accessibility support to determine how a view should be presented to
8163     * the user. In the case of a view with no textual representation, such as
8164     * {@link android.widget.ImageButton}, a useful content description
8165     * explains what the view does. For example, an image button with a phone
8166     * icon that is used to place a call may use "Call" as its content
8167     * description. An image of a floppy disk that is used to save a file may
8168     * use "Save".
8169     *
8170     * @param contentDescription The content description.
8171     * @see #getContentDescription()
8172     * @attr ref android.R.styleable#View_contentDescription
8173     */
8174    @RemotableViewMethod
8175    public void setContentDescription(CharSequence contentDescription) {
8176        if (mContentDescription == null) {
8177            if (contentDescription == null) {
8178                return;
8179            }
8180        } else if (mContentDescription.equals(contentDescription)) {
8181            return;
8182        }
8183        mContentDescription = contentDescription;
8184        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8185        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8186            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8187            notifySubtreeAccessibilityStateChangedIfNeeded();
8188        } else {
8189            notifyViewAccessibilityStateChangedIfNeeded(
8190                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8191        }
8192    }
8193
8194    /**
8195     * Sets the id of a view before which this one is visited in accessibility traversal.
8196     * A screen-reader must visit the content of this view before the content of the one
8197     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8198     * will traverse the entire content of B before traversing the entire content of A,
8199     * regardles of what traversal strategy it is using.
8200     * <p>
8201     * Views that do not have specified before/after relationships are traversed in order
8202     * determined by the screen-reader.
8203     * </p>
8204     * <p>
8205     * Setting that this view is before a view that is not important for accessibility
8206     * or if this view is not important for accessibility will have no effect as the
8207     * screen-reader is not aware of unimportant views.
8208     * </p>
8209     *
8210     * @param beforeId The id of a view this one precedes in accessibility traversal.
8211     *
8212     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8213     *
8214     * @see #setImportantForAccessibility(int)
8215     */
8216    @RemotableViewMethod
8217    public void setAccessibilityTraversalBefore(int beforeId) {
8218        if (mAccessibilityTraversalBeforeId == beforeId) {
8219            return;
8220        }
8221        mAccessibilityTraversalBeforeId = beforeId;
8222        notifyViewAccessibilityStateChangedIfNeeded(
8223                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8224    }
8225
8226    /**
8227     * Gets the id of a view before which this one is visited in accessibility traversal.
8228     *
8229     * @return The id of a view this one precedes in accessibility traversal if
8230     *         specified, otherwise {@link #NO_ID}.
8231     *
8232     * @see #setAccessibilityTraversalBefore(int)
8233     */
8234    public int getAccessibilityTraversalBefore() {
8235        return mAccessibilityTraversalBeforeId;
8236    }
8237
8238    /**
8239     * Sets the id of a view after which this one is visited in accessibility traversal.
8240     * A screen-reader must visit the content of the other view before the content of this
8241     * one. For example, if view B is set to be after view A, then a screen-reader
8242     * will traverse the entire content of A before traversing the entire content of B,
8243     * regardles of what traversal strategy it is using.
8244     * <p>
8245     * Views that do not have specified before/after relationships are traversed in order
8246     * determined by the screen-reader.
8247     * </p>
8248     * <p>
8249     * Setting that this view is after a view that is not important for accessibility
8250     * or if this view is not important for accessibility will have no effect as the
8251     * screen-reader is not aware of unimportant views.
8252     * </p>
8253     *
8254     * @param afterId The id of a view this one succedees in accessibility traversal.
8255     *
8256     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8257     *
8258     * @see #setImportantForAccessibility(int)
8259     */
8260    @RemotableViewMethod
8261    public void setAccessibilityTraversalAfter(int afterId) {
8262        if (mAccessibilityTraversalAfterId == afterId) {
8263            return;
8264        }
8265        mAccessibilityTraversalAfterId = afterId;
8266        notifyViewAccessibilityStateChangedIfNeeded(
8267                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8268    }
8269
8270    /**
8271     * Gets the id of a view after which this one is visited in accessibility traversal.
8272     *
8273     * @return The id of a view this one succeedes in accessibility traversal if
8274     *         specified, otherwise {@link #NO_ID}.
8275     *
8276     * @see #setAccessibilityTraversalAfter(int)
8277     */
8278    public int getAccessibilityTraversalAfter() {
8279        return mAccessibilityTraversalAfterId;
8280    }
8281
8282    /**
8283     * Gets the id of a view for which this view serves as a label for
8284     * accessibility purposes.
8285     *
8286     * @return The labeled view id.
8287     */
8288    @ViewDebug.ExportedProperty(category = "accessibility")
8289    public int getLabelFor() {
8290        return mLabelForId;
8291    }
8292
8293    /**
8294     * Sets the id of a view for which this view serves as a label for
8295     * accessibility purposes.
8296     *
8297     * @param id The labeled view id.
8298     */
8299    @RemotableViewMethod
8300    public void setLabelFor(@IdRes int id) {
8301        if (mLabelForId == id) {
8302            return;
8303        }
8304        mLabelForId = id;
8305        if (mLabelForId != View.NO_ID
8306                && mID == View.NO_ID) {
8307            mID = generateViewId();
8308        }
8309        notifyViewAccessibilityStateChangedIfNeeded(
8310                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8311    }
8312
8313    /**
8314     * Invoked whenever this view loses focus, either by losing window focus or by losing
8315     * focus within its window. This method can be used to clear any state tied to the
8316     * focus. For instance, if a button is held pressed with the trackball and the window
8317     * loses focus, this method can be used to cancel the press.
8318     *
8319     * Subclasses of View overriding this method should always call super.onFocusLost().
8320     *
8321     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8322     * @see #onWindowFocusChanged(boolean)
8323     *
8324     * @hide pending API council approval
8325     */
8326    @CallSuper
8327    protected void onFocusLost() {
8328        resetPressedState();
8329    }
8330
8331    private void resetPressedState() {
8332        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8333            return;
8334        }
8335
8336        if (isPressed()) {
8337            setPressed(false);
8338
8339            if (!mHasPerformedLongPress) {
8340                removeLongPressCallback();
8341            }
8342        }
8343    }
8344
8345    /**
8346     * Returns true if this view has focus
8347     *
8348     * @return True if this view has focus, false otherwise.
8349     */
8350    @ViewDebug.ExportedProperty(category = "focus")
8351    public boolean isFocused() {
8352        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8353    }
8354
8355    /**
8356     * Find the view in the hierarchy rooted at this view that currently has
8357     * focus.
8358     *
8359     * @return The view that currently has focus, or null if no focused view can
8360     *         be found.
8361     */
8362    public View findFocus() {
8363        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8364    }
8365
8366    /**
8367     * Indicates whether this view is one of the set of scrollable containers in
8368     * its window.
8369     *
8370     * @return whether this view is one of the set of scrollable containers in
8371     * its window
8372     *
8373     * @attr ref android.R.styleable#View_isScrollContainer
8374     */
8375    public boolean isScrollContainer() {
8376        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8377    }
8378
8379    /**
8380     * Change whether this view is one of the set of scrollable containers in
8381     * its window.  This will be used to determine whether the window can
8382     * resize or must pan when a soft input area is open -- scrollable
8383     * containers allow the window to use resize mode since the container
8384     * will appropriately shrink.
8385     *
8386     * @attr ref android.R.styleable#View_isScrollContainer
8387     */
8388    public void setScrollContainer(boolean isScrollContainer) {
8389        if (isScrollContainer) {
8390            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8391                mAttachInfo.mScrollContainers.add(this);
8392                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8393            }
8394            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8395        } else {
8396            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8397                mAttachInfo.mScrollContainers.remove(this);
8398            }
8399            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8400        }
8401    }
8402
8403    /**
8404     * Returns the quality of the drawing cache.
8405     *
8406     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8407     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8408     *
8409     * @see #setDrawingCacheQuality(int)
8410     * @see #setDrawingCacheEnabled(boolean)
8411     * @see #isDrawingCacheEnabled()
8412     *
8413     * @attr ref android.R.styleable#View_drawingCacheQuality
8414     */
8415    @DrawingCacheQuality
8416    public int getDrawingCacheQuality() {
8417        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8418    }
8419
8420    /**
8421     * Set the drawing cache quality of this view. This value is used only when the
8422     * drawing cache is enabled
8423     *
8424     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8425     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8426     *
8427     * @see #getDrawingCacheQuality()
8428     * @see #setDrawingCacheEnabled(boolean)
8429     * @see #isDrawingCacheEnabled()
8430     *
8431     * @attr ref android.R.styleable#View_drawingCacheQuality
8432     */
8433    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8434        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8435    }
8436
8437    /**
8438     * Returns whether the screen should remain on, corresponding to the current
8439     * value of {@link #KEEP_SCREEN_ON}.
8440     *
8441     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8442     *
8443     * @see #setKeepScreenOn(boolean)
8444     *
8445     * @attr ref android.R.styleable#View_keepScreenOn
8446     */
8447    public boolean getKeepScreenOn() {
8448        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8449    }
8450
8451    /**
8452     * Controls whether the screen should remain on, modifying the
8453     * value of {@link #KEEP_SCREEN_ON}.
8454     *
8455     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8456     *
8457     * @see #getKeepScreenOn()
8458     *
8459     * @attr ref android.R.styleable#View_keepScreenOn
8460     */
8461    public void setKeepScreenOn(boolean keepScreenOn) {
8462        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8463    }
8464
8465    /**
8466     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8467     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8468     *
8469     * @attr ref android.R.styleable#View_nextFocusLeft
8470     */
8471    public int getNextFocusLeftId() {
8472        return mNextFocusLeftId;
8473    }
8474
8475    /**
8476     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8477     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8478     * decide automatically.
8479     *
8480     * @attr ref android.R.styleable#View_nextFocusLeft
8481     */
8482    public void setNextFocusLeftId(int nextFocusLeftId) {
8483        mNextFocusLeftId = nextFocusLeftId;
8484    }
8485
8486    /**
8487     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8488     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8489     *
8490     * @attr ref android.R.styleable#View_nextFocusRight
8491     */
8492    public int getNextFocusRightId() {
8493        return mNextFocusRightId;
8494    }
8495
8496    /**
8497     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8498     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8499     * decide automatically.
8500     *
8501     * @attr ref android.R.styleable#View_nextFocusRight
8502     */
8503    public void setNextFocusRightId(int nextFocusRightId) {
8504        mNextFocusRightId = nextFocusRightId;
8505    }
8506
8507    /**
8508     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8509     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8510     *
8511     * @attr ref android.R.styleable#View_nextFocusUp
8512     */
8513    public int getNextFocusUpId() {
8514        return mNextFocusUpId;
8515    }
8516
8517    /**
8518     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8519     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8520     * decide automatically.
8521     *
8522     * @attr ref android.R.styleable#View_nextFocusUp
8523     */
8524    public void setNextFocusUpId(int nextFocusUpId) {
8525        mNextFocusUpId = nextFocusUpId;
8526    }
8527
8528    /**
8529     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8530     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8531     *
8532     * @attr ref android.R.styleable#View_nextFocusDown
8533     */
8534    public int getNextFocusDownId() {
8535        return mNextFocusDownId;
8536    }
8537
8538    /**
8539     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8540     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8541     * decide automatically.
8542     *
8543     * @attr ref android.R.styleable#View_nextFocusDown
8544     */
8545    public void setNextFocusDownId(int nextFocusDownId) {
8546        mNextFocusDownId = nextFocusDownId;
8547    }
8548
8549    /**
8550     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8551     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8552     *
8553     * @attr ref android.R.styleable#View_nextFocusForward
8554     */
8555    public int getNextFocusForwardId() {
8556        return mNextFocusForwardId;
8557    }
8558
8559    /**
8560     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8561     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8562     * decide automatically.
8563     *
8564     * @attr ref android.R.styleable#View_nextFocusForward
8565     */
8566    public void setNextFocusForwardId(int nextFocusForwardId) {
8567        mNextFocusForwardId = nextFocusForwardId;
8568    }
8569
8570    /**
8571     * Gets the id of the root of the next keyboard navigation cluster.
8572     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8573     * decide automatically.
8574     *
8575     * @attr ref android.R.styleable#View_nextClusterForward
8576     */
8577    public int getNextClusterForwardId() {
8578        return mNextClusterForwardId;
8579    }
8580
8581    /**
8582     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8583     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8584     * decide automatically.
8585     *
8586     * @attr ref android.R.styleable#View_nextClusterForward
8587     */
8588    public void setNextClusterForwardId(int nextClusterForwardId) {
8589        mNextClusterForwardId = nextClusterForwardId;
8590    }
8591
8592    /**
8593     * Returns the visibility of this view and all of its ancestors
8594     *
8595     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8596     */
8597    public boolean isShown() {
8598        View current = this;
8599        //noinspection ConstantConditions
8600        do {
8601            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8602                return false;
8603            }
8604            ViewParent parent = current.mParent;
8605            if (parent == null) {
8606                return false; // We are not attached to the view root
8607            }
8608            if (!(parent instanceof View)) {
8609                return true;
8610            }
8611            current = (View) parent;
8612        } while (current != null);
8613
8614        return false;
8615    }
8616
8617    /**
8618     * Called by the view hierarchy when the content insets for a window have
8619     * changed, to allow it to adjust its content to fit within those windows.
8620     * The content insets tell you the space that the status bar, input method,
8621     * and other system windows infringe on the application's window.
8622     *
8623     * <p>You do not normally need to deal with this function, since the default
8624     * window decoration given to applications takes care of applying it to the
8625     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8626     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8627     * and your content can be placed under those system elements.  You can then
8628     * use this method within your view hierarchy if you have parts of your UI
8629     * which you would like to ensure are not being covered.
8630     *
8631     * <p>The default implementation of this method simply applies the content
8632     * insets to the view's padding, consuming that content (modifying the
8633     * insets to be 0), and returning true.  This behavior is off by default, but can
8634     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8635     *
8636     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8637     * insets object is propagated down the hierarchy, so any changes made to it will
8638     * be seen by all following views (including potentially ones above in
8639     * the hierarchy since this is a depth-first traversal).  The first view
8640     * that returns true will abort the entire traversal.
8641     *
8642     * <p>The default implementation works well for a situation where it is
8643     * used with a container that covers the entire window, allowing it to
8644     * apply the appropriate insets to its content on all edges.  If you need
8645     * a more complicated layout (such as two different views fitting system
8646     * windows, one on the top of the window, and one on the bottom),
8647     * you can override the method and handle the insets however you would like.
8648     * Note that the insets provided by the framework are always relative to the
8649     * far edges of the window, not accounting for the location of the called view
8650     * within that window.  (In fact when this method is called you do not yet know
8651     * where the layout will place the view, as it is done before layout happens.)
8652     *
8653     * <p>Note: unlike many View methods, there is no dispatch phase to this
8654     * call.  If you are overriding it in a ViewGroup and want to allow the
8655     * call to continue to your children, you must be sure to call the super
8656     * implementation.
8657     *
8658     * <p>Here is a sample layout that makes use of fitting system windows
8659     * to have controls for a video view placed inside of the window decorations
8660     * that it hides and shows.  This can be used with code like the second
8661     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8662     *
8663     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8664     *
8665     * @param insets Current content insets of the window.  Prior to
8666     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8667     * the insets or else you and Android will be unhappy.
8668     *
8669     * @return {@code true} if this view applied the insets and it should not
8670     * continue propagating further down the hierarchy, {@code false} otherwise.
8671     * @see #getFitsSystemWindows()
8672     * @see #setFitsSystemWindows(boolean)
8673     * @see #setSystemUiVisibility(int)
8674     *
8675     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8676     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8677     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8678     * to implement handling their own insets.
8679     */
8680    @Deprecated
8681    protected boolean fitSystemWindows(Rect insets) {
8682        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8683            if (insets == null) {
8684                // Null insets by definition have already been consumed.
8685                // This call cannot apply insets since there are none to apply,
8686                // so return false.
8687                return false;
8688            }
8689            // If we're not in the process of dispatching the newer apply insets call,
8690            // that means we're not in the compatibility path. Dispatch into the newer
8691            // apply insets path and take things from there.
8692            try {
8693                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8694                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8695            } finally {
8696                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8697            }
8698        } else {
8699            // We're being called from the newer apply insets path.
8700            // Perform the standard fallback behavior.
8701            return fitSystemWindowsInt(insets);
8702        }
8703    }
8704
8705    private boolean fitSystemWindowsInt(Rect insets) {
8706        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8707            mUserPaddingStart = UNDEFINED_PADDING;
8708            mUserPaddingEnd = UNDEFINED_PADDING;
8709            Rect localInsets = sThreadLocal.get();
8710            if (localInsets == null) {
8711                localInsets = new Rect();
8712                sThreadLocal.set(localInsets);
8713            }
8714            boolean res = computeFitSystemWindows(insets, localInsets);
8715            mUserPaddingLeftInitial = localInsets.left;
8716            mUserPaddingRightInitial = localInsets.right;
8717            internalSetPadding(localInsets.left, localInsets.top,
8718                    localInsets.right, localInsets.bottom);
8719            return res;
8720        }
8721        return false;
8722    }
8723
8724    /**
8725     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8726     *
8727     * <p>This method should be overridden by views that wish to apply a policy different from or
8728     * in addition to the default behavior. Clients that wish to force a view subtree
8729     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8730     *
8731     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8732     * it will be called during dispatch instead of this method. The listener may optionally
8733     * call this method from its own implementation if it wishes to apply the view's default
8734     * insets policy in addition to its own.</p>
8735     *
8736     * <p>Implementations of this method should either return the insets parameter unchanged
8737     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8738     * that this view applied itself. This allows new inset types added in future platform
8739     * versions to pass through existing implementations unchanged without being erroneously
8740     * consumed.</p>
8741     *
8742     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8743     * property is set then the view will consume the system window insets and apply them
8744     * as padding for the view.</p>
8745     *
8746     * @param insets Insets to apply
8747     * @return The supplied insets with any applied insets consumed
8748     */
8749    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8750        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8751            // We weren't called from within a direct call to fitSystemWindows,
8752            // call into it as a fallback in case we're in a class that overrides it
8753            // and has logic to perform.
8754            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8755                return insets.consumeSystemWindowInsets();
8756            }
8757        } else {
8758            // We were called from within a direct call to fitSystemWindows.
8759            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8760                return insets.consumeSystemWindowInsets();
8761            }
8762        }
8763        return insets;
8764    }
8765
8766    /**
8767     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8768     * window insets to this view. The listener's
8769     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8770     * method will be called instead of the view's
8771     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8772     *
8773     * @param listener Listener to set
8774     *
8775     * @see #onApplyWindowInsets(WindowInsets)
8776     */
8777    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8778        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8779    }
8780
8781    /**
8782     * Request to apply the given window insets to this view or another view in its subtree.
8783     *
8784     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8785     * obscured by window decorations or overlays. This can include the status and navigation bars,
8786     * action bars, input methods and more. New inset categories may be added in the future.
8787     * The method returns the insets provided minus any that were applied by this view or its
8788     * children.</p>
8789     *
8790     * <p>Clients wishing to provide custom behavior should override the
8791     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8792     * {@link OnApplyWindowInsetsListener} via the
8793     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8794     * method.</p>
8795     *
8796     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8797     * </p>
8798     *
8799     * @param insets Insets to apply
8800     * @return The provided insets minus the insets that were consumed
8801     */
8802    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8803        try {
8804            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8805            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8806                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8807            } else {
8808                return onApplyWindowInsets(insets);
8809            }
8810        } finally {
8811            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8812        }
8813    }
8814
8815    /**
8816     * Compute the view's coordinate within the surface.
8817     *
8818     * <p>Computes the coordinates of this view in its surface. The argument
8819     * must be an array of two integers. After the method returns, the array
8820     * contains the x and y location in that order.</p>
8821     * @hide
8822     * @param location an array of two integers in which to hold the coordinates
8823     */
8824    public void getLocationInSurface(@Size(2) int[] location) {
8825        getLocationInWindow(location);
8826        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8827            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8828            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8829        }
8830    }
8831
8832    /**
8833     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8834     * only available if the view is attached.
8835     *
8836     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8837     */
8838    public WindowInsets getRootWindowInsets() {
8839        if (mAttachInfo != null) {
8840            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8841        }
8842        return null;
8843    }
8844
8845    /**
8846     * @hide Compute the insets that should be consumed by this view and the ones
8847     * that should propagate to those under it.
8848     */
8849    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8850        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8851                || mAttachInfo == null
8852                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8853                        && !mAttachInfo.mOverscanRequested)) {
8854            outLocalInsets.set(inoutInsets);
8855            inoutInsets.set(0, 0, 0, 0);
8856            return true;
8857        } else {
8858            // The application wants to take care of fitting system window for
8859            // the content...  however we still need to take care of any overscan here.
8860            final Rect overscan = mAttachInfo.mOverscanInsets;
8861            outLocalInsets.set(overscan);
8862            inoutInsets.left -= overscan.left;
8863            inoutInsets.top -= overscan.top;
8864            inoutInsets.right -= overscan.right;
8865            inoutInsets.bottom -= overscan.bottom;
8866            return false;
8867        }
8868    }
8869
8870    /**
8871     * Compute insets that should be consumed by this view and the ones that should propagate
8872     * to those under it.
8873     *
8874     * @param in Insets currently being processed by this View, likely received as a parameter
8875     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8876     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8877     *                       by this view
8878     * @return Insets that should be passed along to views under this one
8879     */
8880    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8881        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8882                || mAttachInfo == null
8883                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8884            outLocalInsets.set(in.getSystemWindowInsets());
8885            return in.consumeSystemWindowInsets();
8886        } else {
8887            outLocalInsets.set(0, 0, 0, 0);
8888            return in;
8889        }
8890    }
8891
8892    /**
8893     * Sets whether or not this view should account for system screen decorations
8894     * such as the status bar and inset its content; that is, controlling whether
8895     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8896     * executed.  See that method for more details.
8897     *
8898     * <p>Note that if you are providing your own implementation of
8899     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8900     * flag to true -- your implementation will be overriding the default
8901     * implementation that checks this flag.
8902     *
8903     * @param fitSystemWindows If true, then the default implementation of
8904     * {@link #fitSystemWindows(Rect)} will be executed.
8905     *
8906     * @attr ref android.R.styleable#View_fitsSystemWindows
8907     * @see #getFitsSystemWindows()
8908     * @see #fitSystemWindows(Rect)
8909     * @see #setSystemUiVisibility(int)
8910     */
8911    public void setFitsSystemWindows(boolean fitSystemWindows) {
8912        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8913    }
8914
8915    /**
8916     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8917     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8918     * will be executed.
8919     *
8920     * @return {@code true} if the default implementation of
8921     * {@link #fitSystemWindows(Rect)} will be executed.
8922     *
8923     * @attr ref android.R.styleable#View_fitsSystemWindows
8924     * @see #setFitsSystemWindows(boolean)
8925     * @see #fitSystemWindows(Rect)
8926     * @see #setSystemUiVisibility(int)
8927     */
8928    @ViewDebug.ExportedProperty
8929    public boolean getFitsSystemWindows() {
8930        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8931    }
8932
8933    /** @hide */
8934    public boolean fitsSystemWindows() {
8935        return getFitsSystemWindows();
8936    }
8937
8938    /**
8939     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8940     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8941     */
8942    @Deprecated
8943    public void requestFitSystemWindows() {
8944        if (mParent != null) {
8945            mParent.requestFitSystemWindows();
8946        }
8947    }
8948
8949    /**
8950     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8951     */
8952    public void requestApplyInsets() {
8953        requestFitSystemWindows();
8954    }
8955
8956    /**
8957     * For use by PhoneWindow to make its own system window fitting optional.
8958     * @hide
8959     */
8960    public void makeOptionalFitsSystemWindows() {
8961        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8962    }
8963
8964    /**
8965     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8966     * treat them as such.
8967     * @hide
8968     */
8969    public void getOutsets(Rect outOutsetRect) {
8970        if (mAttachInfo != null) {
8971            outOutsetRect.set(mAttachInfo.mOutsets);
8972        } else {
8973            outOutsetRect.setEmpty();
8974        }
8975    }
8976
8977    /**
8978     * Returns the visibility status for this view.
8979     *
8980     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8981     * @attr ref android.R.styleable#View_visibility
8982     */
8983    @ViewDebug.ExportedProperty(mapping = {
8984        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8985        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8986        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8987    })
8988    @Visibility
8989    public int getVisibility() {
8990        return mViewFlags & VISIBILITY_MASK;
8991    }
8992
8993    /**
8994     * Set the visibility state of this view.
8995     *
8996     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8997     * @attr ref android.R.styleable#View_visibility
8998     */
8999    @RemotableViewMethod
9000    public void setVisibility(@Visibility int visibility) {
9001        setFlags(visibility, VISIBILITY_MASK);
9002    }
9003
9004    /**
9005     * Returns the enabled status for this view. The interpretation of the
9006     * enabled state varies by subclass.
9007     *
9008     * @return True if this view is enabled, false otherwise.
9009     */
9010    @ViewDebug.ExportedProperty
9011    public boolean isEnabled() {
9012        return (mViewFlags & ENABLED_MASK) == ENABLED;
9013    }
9014
9015    /**
9016     * Set the enabled state of this view. The interpretation of the enabled
9017     * state varies by subclass.
9018     *
9019     * @param enabled True if this view is enabled, false otherwise.
9020     */
9021    @RemotableViewMethod
9022    public void setEnabled(boolean enabled) {
9023        if (enabled == isEnabled()) return;
9024
9025        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9026
9027        /*
9028         * The View most likely has to change its appearance, so refresh
9029         * the drawable state.
9030         */
9031        refreshDrawableState();
9032
9033        // Invalidate too, since the default behavior for views is to be
9034        // be drawn at 50% alpha rather than to change the drawable.
9035        invalidate(true);
9036
9037        if (!enabled) {
9038            cancelPendingInputEvents();
9039        }
9040    }
9041
9042    /**
9043     * Set whether this view can receive the focus.
9044     * <p>
9045     * Setting this to false will also ensure that this view is not focusable
9046     * in touch mode.
9047     *
9048     * @param focusable If true, this view can receive the focus.
9049     *
9050     * @see #setFocusableInTouchMode(boolean)
9051     * @see #setFocusable(int)
9052     * @attr ref android.R.styleable#View_focusable
9053     */
9054    public void setFocusable(boolean focusable) {
9055        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9056    }
9057
9058    /**
9059     * Sets whether this view can receive focus.
9060     * <p>
9061     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9062     * automatically based on the view's interactivity. This is the default.
9063     * <p>
9064     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9065     * in touch mode.
9066     *
9067     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9068     *                  or {@link #FOCUSABLE_AUTO}.
9069     * @see #setFocusableInTouchMode(boolean)
9070     * @attr ref android.R.styleable#View_focusable
9071     */
9072    public void setFocusable(@Focusable int focusable) {
9073        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9074            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9075        }
9076        setFlags(focusable, FOCUSABLE_MASK);
9077    }
9078
9079    /**
9080     * Set whether this view can receive focus while in touch mode.
9081     *
9082     * Setting this to true will also ensure that this view is focusable.
9083     *
9084     * @param focusableInTouchMode If true, this view can receive the focus while
9085     *   in touch mode.
9086     *
9087     * @see #setFocusable(boolean)
9088     * @attr ref android.R.styleable#View_focusableInTouchMode
9089     */
9090    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9091        // Focusable in touch mode should always be set before the focusable flag
9092        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9093        // which, in touch mode, will not successfully request focus on this view
9094        // because the focusable in touch mode flag is not set
9095        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9096
9097        // Clear FOCUSABLE_AUTO if set.
9098        if (focusableInTouchMode) {
9099            // Clears FOCUSABLE_AUTO if set.
9100            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9101        }
9102    }
9103
9104    /**
9105     * Set autofill mode for the view.
9106     *
9107     * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
9108     *                     or {@link #AUTOFILL_MODE_MANUAL}.
9109     * @attr ref android.R.styleable#View_autofillMode
9110     */
9111    public void setAutofillMode(@AutofillMode int autofillMode) {
9112        Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
9113                AUTOFILL_MODE_MANUAL, "autofillMode");
9114
9115        mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
9116        mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
9117    }
9118
9119    /**
9120     * Sets the a hint that helps the autofill service to select the appropriate data to fill the
9121     * view.
9122     *
9123     * @param autofillHint The autofill hint to set. If the array is emtpy, {@code null} is set.
9124     * @attr ref android.R.styleable#View_autofillHint
9125     */
9126    public void setAutofillHint(@Nullable String... autofillHint) {
9127        if (autofillHint == null || autofillHint.length == 0) {
9128            mAutofillHint = null;
9129        } else {
9130            mAutofillHint = autofillHint;
9131        }
9132    }
9133
9134    /**
9135     * Set whether this view should have sound effects enabled for events such as
9136     * clicking and touching.
9137     *
9138     * <p>You may wish to disable sound effects for a view if you already play sounds,
9139     * for instance, a dial key that plays dtmf tones.
9140     *
9141     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9142     * @see #isSoundEffectsEnabled()
9143     * @see #playSoundEffect(int)
9144     * @attr ref android.R.styleable#View_soundEffectsEnabled
9145     */
9146    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9147        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9148    }
9149
9150    /**
9151     * @return whether this view should have sound effects enabled for events such as
9152     *     clicking and touching.
9153     *
9154     * @see #setSoundEffectsEnabled(boolean)
9155     * @see #playSoundEffect(int)
9156     * @attr ref android.R.styleable#View_soundEffectsEnabled
9157     */
9158    @ViewDebug.ExportedProperty
9159    public boolean isSoundEffectsEnabled() {
9160        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9161    }
9162
9163    /**
9164     * Set whether this view should have haptic feedback for events such as
9165     * long presses.
9166     *
9167     * <p>You may wish to disable haptic feedback if your view already controls
9168     * its own haptic feedback.
9169     *
9170     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9171     * @see #isHapticFeedbackEnabled()
9172     * @see #performHapticFeedback(int)
9173     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9174     */
9175    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9176        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9177    }
9178
9179    /**
9180     * @return whether this view should have haptic feedback enabled for events
9181     * long presses.
9182     *
9183     * @see #setHapticFeedbackEnabled(boolean)
9184     * @see #performHapticFeedback(int)
9185     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9186     */
9187    @ViewDebug.ExportedProperty
9188    public boolean isHapticFeedbackEnabled() {
9189        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9190    }
9191
9192    /**
9193     * Returns the layout direction for this view.
9194     *
9195     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9196     *   {@link #LAYOUT_DIRECTION_RTL},
9197     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9198     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9199     *
9200     * @attr ref android.R.styleable#View_layoutDirection
9201     *
9202     * @hide
9203     */
9204    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9205        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9206        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9207        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9208        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9209    })
9210    @LayoutDir
9211    public int getRawLayoutDirection() {
9212        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9213    }
9214
9215    /**
9216     * Set the layout direction for this view. This will propagate a reset of layout direction
9217     * resolution to the view's children and resolve layout direction for this view.
9218     *
9219     * @param layoutDirection the layout direction to set. Should be one of:
9220     *
9221     * {@link #LAYOUT_DIRECTION_LTR},
9222     * {@link #LAYOUT_DIRECTION_RTL},
9223     * {@link #LAYOUT_DIRECTION_INHERIT},
9224     * {@link #LAYOUT_DIRECTION_LOCALE}.
9225     *
9226     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9227     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9228     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9229     *
9230     * @attr ref android.R.styleable#View_layoutDirection
9231     */
9232    @RemotableViewMethod
9233    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9234        if (getRawLayoutDirection() != layoutDirection) {
9235            // Reset the current layout direction and the resolved one
9236            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9237            resetRtlProperties();
9238            // Set the new layout direction (filtered)
9239            mPrivateFlags2 |=
9240                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9241            // We need to resolve all RTL properties as they all depend on layout direction
9242            resolveRtlPropertiesIfNeeded();
9243            requestLayout();
9244            invalidate(true);
9245        }
9246    }
9247
9248    /**
9249     * Returns the resolved layout direction for this view.
9250     *
9251     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9252     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9253     *
9254     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9255     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9256     *
9257     * @attr ref android.R.styleable#View_layoutDirection
9258     */
9259    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9260        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9261        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9262    })
9263    @ResolvedLayoutDir
9264    public int getLayoutDirection() {
9265        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9266        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9267            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9268            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9269        }
9270        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9271                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9272    }
9273
9274    /**
9275     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9276     * layout attribute and/or the inherited value from the parent
9277     *
9278     * @return true if the layout is right-to-left.
9279     *
9280     * @hide
9281     */
9282    @ViewDebug.ExportedProperty(category = "layout")
9283    public boolean isLayoutRtl() {
9284        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9285    }
9286
9287    /**
9288     * Indicates whether the view is currently tracking transient state that the
9289     * app should not need to concern itself with saving and restoring, but that
9290     * the framework should take special note to preserve when possible.
9291     *
9292     * <p>A view with transient state cannot be trivially rebound from an external
9293     * data source, such as an adapter binding item views in a list. This may be
9294     * because the view is performing an animation, tracking user selection
9295     * of content, or similar.</p>
9296     *
9297     * @return true if the view has transient state
9298     */
9299    @ViewDebug.ExportedProperty(category = "layout")
9300    public boolean hasTransientState() {
9301        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9302    }
9303
9304    /**
9305     * Set whether this view is currently tracking transient state that the
9306     * framework should attempt to preserve when possible. This flag is reference counted,
9307     * so every call to setHasTransientState(true) should be paired with a later call
9308     * to setHasTransientState(false).
9309     *
9310     * <p>A view with transient state cannot be trivially rebound from an external
9311     * data source, such as an adapter binding item views in a list. This may be
9312     * because the view is performing an animation, tracking user selection
9313     * of content, or similar.</p>
9314     *
9315     * @param hasTransientState true if this view has transient state
9316     */
9317    public void setHasTransientState(boolean hasTransientState) {
9318        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9319                mTransientStateCount - 1;
9320        if (mTransientStateCount < 0) {
9321            mTransientStateCount = 0;
9322            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9323                    "unmatched pair of setHasTransientState calls");
9324        } else if ((hasTransientState && mTransientStateCount == 1) ||
9325                (!hasTransientState && mTransientStateCount == 0)) {
9326            // update flag if we've just incremented up from 0 or decremented down to 0
9327            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9328                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9329            if (mParent != null) {
9330                try {
9331                    mParent.childHasTransientStateChanged(this, hasTransientState);
9332                } catch (AbstractMethodError e) {
9333                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9334                            " does not fully implement ViewParent", e);
9335                }
9336            }
9337        }
9338    }
9339
9340    /**
9341     * Returns true if this view is currently attached to a window.
9342     */
9343    public boolean isAttachedToWindow() {
9344        return mAttachInfo != null;
9345    }
9346
9347    /**
9348     * Returns true if this view has been through at least one layout since it
9349     * was last attached to or detached from a window.
9350     */
9351    public boolean isLaidOut() {
9352        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9353    }
9354
9355    /**
9356     * If this view doesn't do any drawing on its own, set this flag to
9357     * allow further optimizations. By default, this flag is not set on
9358     * View, but could be set on some View subclasses such as ViewGroup.
9359     *
9360     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9361     * you should clear this flag.
9362     *
9363     * @param willNotDraw whether or not this View draw on its own
9364     */
9365    public void setWillNotDraw(boolean willNotDraw) {
9366        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9367    }
9368
9369    /**
9370     * Returns whether or not this View draws on its own.
9371     *
9372     * @return true if this view has nothing to draw, false otherwise
9373     */
9374    @ViewDebug.ExportedProperty(category = "drawing")
9375    public boolean willNotDraw() {
9376        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9377    }
9378
9379    /**
9380     * When a View's drawing cache is enabled, drawing is redirected to an
9381     * offscreen bitmap. Some views, like an ImageView, must be able to
9382     * bypass this mechanism if they already draw a single bitmap, to avoid
9383     * unnecessary usage of the memory.
9384     *
9385     * @param willNotCacheDrawing true if this view does not cache its
9386     *        drawing, false otherwise
9387     */
9388    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9389        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9390    }
9391
9392    /**
9393     * Returns whether or not this View can cache its drawing or not.
9394     *
9395     * @return true if this view does not cache its drawing, false otherwise
9396     */
9397    @ViewDebug.ExportedProperty(category = "drawing")
9398    public boolean willNotCacheDrawing() {
9399        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9400    }
9401
9402    /**
9403     * Indicates whether this view reacts to click events or not.
9404     *
9405     * @return true if the view is clickable, false otherwise
9406     *
9407     * @see #setClickable(boolean)
9408     * @attr ref android.R.styleable#View_clickable
9409     */
9410    @ViewDebug.ExportedProperty
9411    public boolean isClickable() {
9412        return (mViewFlags & CLICKABLE) == CLICKABLE;
9413    }
9414
9415    /**
9416     * Enables or disables click events for this view. When a view
9417     * is clickable it will change its state to "pressed" on every click.
9418     * Subclasses should set the view clickable to visually react to
9419     * user's clicks.
9420     *
9421     * @param clickable true to make the view clickable, false otherwise
9422     *
9423     * @see #isClickable()
9424     * @attr ref android.R.styleable#View_clickable
9425     */
9426    public void setClickable(boolean clickable) {
9427        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9428    }
9429
9430    /**
9431     * Indicates whether this view reacts to long click events or not.
9432     *
9433     * @return true if the view is long clickable, false otherwise
9434     *
9435     * @see #setLongClickable(boolean)
9436     * @attr ref android.R.styleable#View_longClickable
9437     */
9438    public boolean isLongClickable() {
9439        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9440    }
9441
9442    /**
9443     * Enables or disables long click events for this view. When a view is long
9444     * clickable it reacts to the user holding down the button for a longer
9445     * duration than a tap. This event can either launch the listener or a
9446     * context menu.
9447     *
9448     * @param longClickable true to make the view long clickable, false otherwise
9449     * @see #isLongClickable()
9450     * @attr ref android.R.styleable#View_longClickable
9451     */
9452    public void setLongClickable(boolean longClickable) {
9453        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9454    }
9455
9456    /**
9457     * Indicates whether this view reacts to context clicks or not.
9458     *
9459     * @return true if the view is context clickable, false otherwise
9460     * @see #setContextClickable(boolean)
9461     * @attr ref android.R.styleable#View_contextClickable
9462     */
9463    public boolean isContextClickable() {
9464        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9465    }
9466
9467    /**
9468     * Enables or disables context clicking for this view. This event can launch the listener.
9469     *
9470     * @param contextClickable true to make the view react to a context click, false otherwise
9471     * @see #isContextClickable()
9472     * @attr ref android.R.styleable#View_contextClickable
9473     */
9474    public void setContextClickable(boolean contextClickable) {
9475        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9476    }
9477
9478    /**
9479     * Sets the pressed state for this view and provides a touch coordinate for
9480     * animation hinting.
9481     *
9482     * @param pressed Pass true to set the View's internal state to "pressed",
9483     *            or false to reverts the View's internal state from a
9484     *            previously set "pressed" state.
9485     * @param x The x coordinate of the touch that caused the press
9486     * @param y The y coordinate of the touch that caused the press
9487     */
9488    private void setPressed(boolean pressed, float x, float y) {
9489        if (pressed) {
9490            drawableHotspotChanged(x, y);
9491        }
9492
9493        setPressed(pressed);
9494    }
9495
9496    /**
9497     * Sets the pressed state for this view.
9498     *
9499     * @see #isClickable()
9500     * @see #setClickable(boolean)
9501     *
9502     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9503     *        the View's internal state from a previously set "pressed" state.
9504     */
9505    public void setPressed(boolean pressed) {
9506        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9507
9508        if (pressed) {
9509            mPrivateFlags |= PFLAG_PRESSED;
9510        } else {
9511            mPrivateFlags &= ~PFLAG_PRESSED;
9512        }
9513
9514        if (needsRefresh) {
9515            refreshDrawableState();
9516        }
9517        dispatchSetPressed(pressed);
9518    }
9519
9520    /**
9521     * Dispatch setPressed to all of this View's children.
9522     *
9523     * @see #setPressed(boolean)
9524     *
9525     * @param pressed The new pressed state
9526     */
9527    protected void dispatchSetPressed(boolean pressed) {
9528    }
9529
9530    /**
9531     * Indicates whether the view is currently in pressed state. Unless
9532     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9533     * the pressed state.
9534     *
9535     * @see #setPressed(boolean)
9536     * @see #isClickable()
9537     * @see #setClickable(boolean)
9538     *
9539     * @return true if the view is currently pressed, false otherwise
9540     */
9541    @ViewDebug.ExportedProperty
9542    public boolean isPressed() {
9543        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9544    }
9545
9546    /**
9547     * @hide
9548     * Indicates whether this view will participate in data collection through
9549     * {@link ViewStructure}.  If true, it will not provide any data
9550     * for itself or its children.  If false, the normal data collection will be allowed.
9551     *
9552     * @return Returns false if assist data collection is not blocked, else true.
9553     *
9554     * @see #setAssistBlocked(boolean)
9555     * @attr ref android.R.styleable#View_assistBlocked
9556     */
9557    public boolean isAssistBlocked() {
9558        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9559    }
9560
9561    /**
9562     * @hide
9563     * Indicates whether this view will participate in data collection through
9564     * {@link ViewStructure} for autofill purposes.
9565     *
9566     * <p>If {@code true}, it will not provide any data for itself or its children.
9567     * <p>If {@code false}, the normal data collection will be allowed.
9568     *
9569     * @return Returns {@code false} if assist data collection for autofill is not blocked,
9570     * else {@code true}.
9571     *
9572     * TODO(b/33197203): update / remove javadoc tags below
9573     * @see #setAssistBlocked(boolean)
9574     * @attr ref android.R.styleable#View_assistBlocked
9575     */
9576    public boolean isAutofillBlocked() {
9577        return false; // TODO(b/33197203): properly implement it
9578    }
9579
9580    /**
9581     * @hide
9582     * Controls whether assist data collection from this view and its children is enabled
9583     * (that is, whether {@link #onProvideStructure} and
9584     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9585     * allowing normal assist collection.  Setting this to false will disable assist collection.
9586     *
9587     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9588     * (the default) to allow it.
9589     *
9590     * @see #isAssistBlocked()
9591     * @see #onProvideStructure
9592     * @see #onProvideVirtualStructure
9593     * @attr ref android.R.styleable#View_assistBlocked
9594     */
9595    public void setAssistBlocked(boolean enabled) {
9596        if (enabled) {
9597            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9598        } else {
9599            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9600        }
9601    }
9602
9603    /**
9604     * Indicates whether this view will save its state (that is,
9605     * whether its {@link #onSaveInstanceState} method will be called).
9606     *
9607     * @return Returns true if the view state saving is enabled, else false.
9608     *
9609     * @see #setSaveEnabled(boolean)
9610     * @attr ref android.R.styleable#View_saveEnabled
9611     */
9612    public boolean isSaveEnabled() {
9613        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9614    }
9615
9616    /**
9617     * Controls whether the saving of this view's state is
9618     * enabled (that is, whether its {@link #onSaveInstanceState} method
9619     * will be called).  Note that even if freezing is enabled, the
9620     * view still must have an id assigned to it (via {@link #setId(int)})
9621     * for its state to be saved.  This flag can only disable the
9622     * saving of this view; any child views may still have their state saved.
9623     *
9624     * @param enabled Set to false to <em>disable</em> state saving, or true
9625     * (the default) to allow it.
9626     *
9627     * @see #isSaveEnabled()
9628     * @see #setId(int)
9629     * @see #onSaveInstanceState()
9630     * @attr ref android.R.styleable#View_saveEnabled
9631     */
9632    public void setSaveEnabled(boolean enabled) {
9633        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9634    }
9635
9636    /**
9637     * Gets whether the framework should discard touches when the view's
9638     * window is obscured by another visible window.
9639     * Refer to the {@link View} security documentation for more details.
9640     *
9641     * @return True if touch filtering is enabled.
9642     *
9643     * @see #setFilterTouchesWhenObscured(boolean)
9644     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9645     */
9646    @ViewDebug.ExportedProperty
9647    public boolean getFilterTouchesWhenObscured() {
9648        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9649    }
9650
9651    /**
9652     * Sets whether the framework should discard touches when the view's
9653     * window is obscured by another visible window.
9654     * Refer to the {@link View} security documentation for more details.
9655     *
9656     * @param enabled True if touch filtering should be enabled.
9657     *
9658     * @see #getFilterTouchesWhenObscured
9659     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9660     */
9661    public void setFilterTouchesWhenObscured(boolean enabled) {
9662        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9663                FILTER_TOUCHES_WHEN_OBSCURED);
9664    }
9665
9666    /**
9667     * Indicates whether the entire hierarchy under this view will save its
9668     * state when a state saving traversal occurs from its parent.  The default
9669     * is true; if false, these views will not be saved unless
9670     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9671     *
9672     * @return Returns true if the view state saving from parent is enabled, else false.
9673     *
9674     * @see #setSaveFromParentEnabled(boolean)
9675     */
9676    public boolean isSaveFromParentEnabled() {
9677        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9678    }
9679
9680    /**
9681     * Controls whether the entire hierarchy under this view will save its
9682     * state when a state saving traversal occurs from its parent.  The default
9683     * is true; if false, these views will not be saved unless
9684     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9685     *
9686     * @param enabled Set to false to <em>disable</em> state saving, or true
9687     * (the default) to allow it.
9688     *
9689     * @see #isSaveFromParentEnabled()
9690     * @see #setId(int)
9691     * @see #onSaveInstanceState()
9692     */
9693    public void setSaveFromParentEnabled(boolean enabled) {
9694        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9695    }
9696
9697
9698    /**
9699     * Returns whether this View is currently able to take focus.
9700     *
9701     * @return True if this view can take focus, or false otherwise.
9702     */
9703    @ViewDebug.ExportedProperty(category = "focus")
9704    public final boolean isFocusable() {
9705        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9706    }
9707
9708    /**
9709     * Returns the focusable setting for this view.
9710     *
9711     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9712     * @attr ref android.R.styleable#View_focusable
9713     */
9714    @ViewDebug.ExportedProperty(mapping = {
9715            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9716            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9717            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9718            })
9719    @Focusable
9720    public int getFocusable() {
9721        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9722    }
9723
9724    /**
9725     * When a view is focusable, it may not want to take focus when in touch mode.
9726     * For example, a button would like focus when the user is navigating via a D-pad
9727     * so that the user can click on it, but once the user starts touching the screen,
9728     * the button shouldn't take focus
9729     * @return Whether the view is focusable in touch mode.
9730     * @attr ref android.R.styleable#View_focusableInTouchMode
9731     */
9732    @ViewDebug.ExportedProperty
9733    public final boolean isFocusableInTouchMode() {
9734        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9735    }
9736
9737    /**
9738     * Returns the autofill mode for this view.
9739     *
9740     * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
9741     * {@link #AUTOFILL_MODE_MANUAL}.
9742     * @attr ref android.R.styleable#View_autofillMode
9743     */
9744    @ViewDebug.ExportedProperty(mapping = {
9745            @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
9746            @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
9747            @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
9748            })
9749    @AutofillMode
9750    public int getAutofillMode() {
9751        return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
9752    }
9753
9754    /**
9755     * Returns the resolved autofill mode for this view.
9756     *
9757     * This is the same as {@link #getAutofillMode()} but if the mode is
9758     * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
9759     *
9760     * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
9761     *         fill mode can not be resolved e.g. {@link #getAutofillMode()} is
9762     *         {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
9763     *         {@link #AUTOFILL_MODE_AUTO} is returned.
9764     */
9765    public @AutofillMode int getResolvedAutofillMode() {
9766        @AutofillMode int autofillMode = getAutofillMode();
9767
9768        if (autofillMode == AUTOFILL_MODE_INHERIT) {
9769            if (mParent == null) {
9770                return AUTOFILL_MODE_AUTO;
9771            } else {
9772                return mParent.getResolvedAutofillMode();
9773            }
9774        } else {
9775            return autofillMode;
9776        }
9777    }
9778
9779    /**
9780     * Find the nearest view in the specified direction that can take focus.
9781     * This does not actually give focus to that view.
9782     *
9783     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9784     *
9785     * @return The nearest focusable in the specified direction, or null if none
9786     *         can be found.
9787     */
9788    public View focusSearch(@FocusRealDirection int direction) {
9789        if (mParent != null) {
9790            return mParent.focusSearch(this, direction);
9791        } else {
9792            return null;
9793        }
9794    }
9795
9796    /**
9797     * Returns whether this View is a root of a keyboard navigation cluster.
9798     *
9799     * @return True if this view is a root of a cluster, or false otherwise.
9800     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9801     */
9802    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9803    public final boolean isKeyboardNavigationCluster() {
9804        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9805    }
9806
9807    /**
9808     * Set whether this view is a root of a keyboard navigation cluster.
9809     *
9810     * @param isCluster If true, this view is a root of a cluster.
9811     *
9812     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9813     */
9814    public void setKeyboardNavigationCluster(boolean isCluster) {
9815        if (isCluster) {
9816            mPrivateFlags3 |= PFLAG3_CLUSTER;
9817        } else {
9818            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9819        }
9820    }
9821
9822    /**
9823     * Sets this View as the one which receives focus the next time cluster navigation jumps
9824     * to the cluster containing this View. This does NOT change focus even if the cluster
9825     * containing this view is current.
9826     *
9827     * @hide
9828     */
9829    public void setFocusedInCluster() {
9830        if (mParent instanceof ViewGroup) {
9831            ((ViewGroup) mParent).setFocusInCluster(this);
9832        }
9833    }
9834
9835    /**
9836     * Returns whether this View should receive focus when the focus is restored for the view
9837     * hierarchy containing this view.
9838     * <p>
9839     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9840     * window or serves as a target of cluster navigation.
9841     *
9842     * @see #restoreDefaultFocus(int)
9843     *
9844     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9845     * @attr ref android.R.styleable#View_focusedByDefault
9846     */
9847    @ViewDebug.ExportedProperty(category = "focusedByDefault")
9848    public final boolean isFocusedByDefault() {
9849        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9850    }
9851
9852    /**
9853     * Sets whether this View should receive focus when the focus is restored for the view
9854     * hierarchy containing this view.
9855     * <p>
9856     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9857     * window or serves as a target of cluster navigation.
9858     *
9859     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9860     *                           {@code false} otherwise.
9861     *
9862     * @see #restoreDefaultFocus(int)
9863     *
9864     * @attr ref android.R.styleable#View_focusedByDefault
9865     */
9866    public void setFocusedByDefault(boolean isFocusedByDefault) {
9867        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9868            return;
9869        }
9870
9871        if (isFocusedByDefault) {
9872            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9873        } else {
9874            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9875        }
9876
9877        if (mParent instanceof ViewGroup) {
9878            if (isFocusedByDefault) {
9879                ((ViewGroup) mParent).setDefaultFocus(this);
9880            } else {
9881                ((ViewGroup) mParent).clearDefaultFocus(this);
9882            }
9883        }
9884    }
9885
9886    /**
9887     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9888     *
9889     * @return {@code true} if this view has default focus, {@code false} otherwise
9890     */
9891    boolean hasDefaultFocus() {
9892        return isFocusedByDefault();
9893    }
9894
9895    /**
9896     * Find the nearest keyboard navigation cluster in the specified direction.
9897     * This does not actually give focus to that cluster.
9898     *
9899     * @param currentCluster The starting point of the search. Null means the current cluster is not
9900     *                       found yet
9901     * @param direction Direction to look
9902     *
9903     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9904     *         can be found
9905     */
9906    public View keyboardNavigationClusterSearch(View currentCluster,
9907            @FocusDirection int direction) {
9908        if (isKeyboardNavigationCluster()) {
9909            currentCluster = this;
9910        }
9911        if (isRootNamespace()) {
9912            // Root namespace means we should consider ourselves the top of the
9913            // tree for group searching; otherwise we could be group searching
9914            // into other tabs.  see LocalActivityManager and TabHost for more info.
9915            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9916                    this, currentCluster, direction);
9917        } else if (mParent != null) {
9918            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9919        }
9920        return null;
9921    }
9922
9923    /**
9924     * This method is the last chance for the focused view and its ancestors to
9925     * respond to an arrow key. This is called when the focused view did not
9926     * consume the key internally, nor could the view system find a new view in
9927     * the requested direction to give focus to.
9928     *
9929     * @param focused The currently focused view.
9930     * @param direction The direction focus wants to move. One of FOCUS_UP,
9931     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9932     * @return True if the this view consumed this unhandled move.
9933     */
9934    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9935        return false;
9936    }
9937
9938    /**
9939     * If a user manually specified the next view id for a particular direction,
9940     * use the root to look up the view.
9941     * @param root The root view of the hierarchy containing this view.
9942     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9943     * or FOCUS_BACKWARD.
9944     * @return The user specified next view, or null if there is none.
9945     */
9946    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9947        switch (direction) {
9948            case FOCUS_LEFT:
9949                if (mNextFocusLeftId == View.NO_ID) return null;
9950                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9951            case FOCUS_RIGHT:
9952                if (mNextFocusRightId == View.NO_ID) return null;
9953                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9954            case FOCUS_UP:
9955                if (mNextFocusUpId == View.NO_ID) return null;
9956                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9957            case FOCUS_DOWN:
9958                if (mNextFocusDownId == View.NO_ID) return null;
9959                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9960            case FOCUS_FORWARD:
9961                if (mNextFocusForwardId == View.NO_ID) return null;
9962                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9963            case FOCUS_BACKWARD: {
9964                if (mID == View.NO_ID) return null;
9965                final int id = mID;
9966                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9967                    @Override
9968                    public boolean test(View t) {
9969                        return t.mNextFocusForwardId == id;
9970                    }
9971                });
9972            }
9973        }
9974        return null;
9975    }
9976
9977    private View findViewInsideOutShouldExist(View root, int id) {
9978        if (mMatchIdPredicate == null) {
9979            mMatchIdPredicate = new MatchIdPredicate();
9980        }
9981        mMatchIdPredicate.mId = id;
9982        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
9983        if (result == null) {
9984            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
9985        }
9986        return result;
9987    }
9988
9989    /**
9990     * Find and return all focusable views that are descendants of this view,
9991     * possibly including this view if it is focusable itself.
9992     *
9993     * @param direction The direction of the focus
9994     * @return A list of focusable views
9995     */
9996    public ArrayList<View> getFocusables(@FocusDirection int direction) {
9997        ArrayList<View> result = new ArrayList<View>(24);
9998        addFocusables(result, direction);
9999        return result;
10000    }
10001
10002    /**
10003     * Add any focusable views that are descendants of this view (possibly
10004     * including this view if it is focusable itself) to views.  If we are in touch mode,
10005     * only add views that are also focusable in touch mode.
10006     *
10007     * @param views Focusable views found so far
10008     * @param direction The direction of the focus
10009     */
10010    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10011        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10012    }
10013
10014    /**
10015     * Adds any focusable views that are descendants of this view (possibly
10016     * including this view if it is focusable itself) to views. This method
10017     * adds all focusable views regardless if we are in touch mode or
10018     * only views focusable in touch mode if we are in touch mode or
10019     * only views that can take accessibility focus if accessibility is enabled
10020     * depending on the focusable mode parameter.
10021     *
10022     * @param views Focusable views found so far or null if all we are interested is
10023     *        the number of focusables.
10024     * @param direction The direction of the focus.
10025     * @param focusableMode The type of focusables to be added.
10026     *
10027     * @see #FOCUSABLES_ALL
10028     * @see #FOCUSABLES_TOUCH_MODE
10029     */
10030    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10031            @FocusableMode int focusableMode) {
10032        if (views == null) {
10033            return;
10034        }
10035        if (!isFocusable()) {
10036            return;
10037        }
10038        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10039                && !isFocusableInTouchMode()) {
10040            return;
10041        }
10042        views.add(this);
10043    }
10044
10045    /**
10046     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10047     * including this view if it is a cluster root itself) to views.
10048     *
10049     * @param views Keyboard navigation cluster roots found so far
10050     * @param direction Direction to look
10051     */
10052    public void addKeyboardNavigationClusters(
10053            @NonNull Collection<View> views,
10054            int direction) {
10055        if (!isKeyboardNavigationCluster()) {
10056            return;
10057        }
10058        if (!hasFocusable()) {
10059            return;
10060        }
10061        views.add(this);
10062    }
10063
10064    /**
10065     * Finds the Views that contain given text. The containment is case insensitive.
10066     * The search is performed by either the text that the View renders or the content
10067     * description that describes the view for accessibility purposes and the view does
10068     * not render or both. Clients can specify how the search is to be performed via
10069     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10070     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10071     *
10072     * @param outViews The output list of matching Views.
10073     * @param searched The text to match against.
10074     *
10075     * @see #FIND_VIEWS_WITH_TEXT
10076     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10077     * @see #setContentDescription(CharSequence)
10078     */
10079    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10080            @FindViewFlags int flags) {
10081        if (getAccessibilityNodeProvider() != null) {
10082            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10083                outViews.add(this);
10084            }
10085        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10086                && (searched != null && searched.length() > 0)
10087                && (mContentDescription != null && mContentDescription.length() > 0)) {
10088            String searchedLowerCase = searched.toString().toLowerCase();
10089            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10090            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10091                outViews.add(this);
10092            }
10093        }
10094    }
10095
10096    /**
10097     * Find and return all touchable views that are descendants of this view,
10098     * possibly including this view if it is touchable itself.
10099     *
10100     * @return A list of touchable views
10101     */
10102    public ArrayList<View> getTouchables() {
10103        ArrayList<View> result = new ArrayList<View>();
10104        addTouchables(result);
10105        return result;
10106    }
10107
10108    /**
10109     * Add any touchable views that are descendants of this view (possibly
10110     * including this view if it is touchable itself) to views.
10111     *
10112     * @param views Touchable views found so far
10113     */
10114    public void addTouchables(ArrayList<View> views) {
10115        final int viewFlags = mViewFlags;
10116
10117        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10118                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10119                && (viewFlags & ENABLED_MASK) == ENABLED) {
10120            views.add(this);
10121        }
10122    }
10123
10124    /**
10125     * Returns whether this View is accessibility focused.
10126     *
10127     * @return True if this View is accessibility focused.
10128     */
10129    public boolean isAccessibilityFocused() {
10130        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10131    }
10132
10133    /**
10134     * Call this to try to give accessibility focus to this view.
10135     *
10136     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10137     * returns false or the view is no visible or the view already has accessibility
10138     * focus.
10139     *
10140     * See also {@link #focusSearch(int)}, which is what you call to say that you
10141     * have focus, and you want your parent to look for the next one.
10142     *
10143     * @return Whether this view actually took accessibility focus.
10144     *
10145     * @hide
10146     */
10147    public boolean requestAccessibilityFocus() {
10148        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10149        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10150            return false;
10151        }
10152        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10153            return false;
10154        }
10155        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10156            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10157            ViewRootImpl viewRootImpl = getViewRootImpl();
10158            if (viewRootImpl != null) {
10159                viewRootImpl.setAccessibilityFocus(this, null);
10160            }
10161            invalidate();
10162            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10163            return true;
10164        }
10165        return false;
10166    }
10167
10168    /**
10169     * Call this to try to clear accessibility focus of this view.
10170     *
10171     * See also {@link #focusSearch(int)}, which is what you call to say that you
10172     * have focus, and you want your parent to look for the next one.
10173     *
10174     * @hide
10175     */
10176    public void clearAccessibilityFocus() {
10177        clearAccessibilityFocusNoCallbacks(0);
10178
10179        // Clear the global reference of accessibility focus if this view or
10180        // any of its descendants had accessibility focus. This will NOT send
10181        // an event or update internal state if focus is cleared from a
10182        // descendant view, which may leave views in inconsistent states.
10183        final ViewRootImpl viewRootImpl = getViewRootImpl();
10184        if (viewRootImpl != null) {
10185            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10186            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10187                viewRootImpl.setAccessibilityFocus(null, null);
10188            }
10189        }
10190    }
10191
10192    private void sendAccessibilityHoverEvent(int eventType) {
10193        // Since we are not delivering to a client accessibility events from not
10194        // important views (unless the clinet request that) we need to fire the
10195        // event from the deepest view exposed to the client. As a consequence if
10196        // the user crosses a not exposed view the client will see enter and exit
10197        // of the exposed predecessor followed by and enter and exit of that same
10198        // predecessor when entering and exiting the not exposed descendant. This
10199        // is fine since the client has a clear idea which view is hovered at the
10200        // price of a couple more events being sent. This is a simple and
10201        // working solution.
10202        View source = this;
10203        while (true) {
10204            if (source.includeForAccessibility()) {
10205                source.sendAccessibilityEvent(eventType);
10206                return;
10207            }
10208            ViewParent parent = source.getParent();
10209            if (parent instanceof View) {
10210                source = (View) parent;
10211            } else {
10212                return;
10213            }
10214        }
10215    }
10216
10217    /**
10218     * Clears accessibility focus without calling any callback methods
10219     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10220     * is used separately from that one for clearing accessibility focus when
10221     * giving this focus to another view.
10222     *
10223     * @param action The action, if any, that led to focus being cleared. Set to
10224     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10225     * the window.
10226     */
10227    void clearAccessibilityFocusNoCallbacks(int action) {
10228        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10229            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10230            invalidate();
10231            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10232                AccessibilityEvent event = AccessibilityEvent.obtain(
10233                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10234                event.setAction(action);
10235                if (mAccessibilityDelegate != null) {
10236                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10237                } else {
10238                    sendAccessibilityEventUnchecked(event);
10239                }
10240            }
10241        }
10242    }
10243
10244    /**
10245     * Call this to try to give focus to a specific view or to one of its
10246     * descendants.
10247     *
10248     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10249     * false), or if it is focusable and it is not focusable in touch mode
10250     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10251     *
10252     * See also {@link #focusSearch(int)}, which is what you call to say that you
10253     * have focus, and you want your parent to look for the next one.
10254     *
10255     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10256     * {@link #FOCUS_DOWN} and <code>null</code>.
10257     *
10258     * @return Whether this view or one of its descendants actually took focus.
10259     */
10260    public final boolean requestFocus() {
10261        return requestFocus(View.FOCUS_DOWN);
10262    }
10263
10264    /**
10265     * This will request focus for whichever View was last focused within this
10266     * cluster before a focus-jump out of it.
10267     *
10268     * @hide
10269     */
10270    @TestApi
10271    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10272        // Prioritize focusableByDefault over algorithmic focus selection.
10273        if (restoreDefaultFocus()) {
10274            return true;
10275        }
10276        return requestFocus(direction);
10277    }
10278
10279    /**
10280     * This will request focus for whichever View not in a cluster was last focused before a
10281     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10282     * the "first" focusable view it finds.
10283     *
10284     * @hide
10285     */
10286    @TestApi
10287    public boolean restoreFocusNotInCluster() {
10288        return requestFocus(View.FOCUS_DOWN);
10289    }
10290
10291    /**
10292     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10293     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10294     *
10295     * @return Whether this view or one of its descendants actually took focus
10296     */
10297    public boolean restoreDefaultFocus() {
10298        return requestFocus(View.FOCUS_DOWN);
10299    }
10300
10301    /**
10302     * Call this to try to give focus to a specific view or to one of its
10303     * descendants and give it a hint about what direction focus is heading.
10304     *
10305     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10306     * false), or if it is focusable and it is not focusable in touch mode
10307     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10308     *
10309     * See also {@link #focusSearch(int)}, which is what you call to say that you
10310     * have focus, and you want your parent to look for the next one.
10311     *
10312     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10313     * <code>null</code> set for the previously focused rectangle.
10314     *
10315     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10316     * @return Whether this view or one of its descendants actually took focus.
10317     */
10318    public final boolean requestFocus(int direction) {
10319        return requestFocus(direction, null);
10320    }
10321
10322    /**
10323     * Call this to try to give focus to a specific view or to one of its descendants
10324     * and give it hints about the direction and a specific rectangle that the focus
10325     * is coming from.  The rectangle can help give larger views a finer grained hint
10326     * about where focus is coming from, and therefore, where to show selection, or
10327     * forward focus change internally.
10328     *
10329     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10330     * false), or if it is focusable and it is not focusable in touch mode
10331     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10332     *
10333     * A View will not take focus if it is not visible.
10334     *
10335     * A View will not take focus if one of its parents has
10336     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10337     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10338     *
10339     * See also {@link #focusSearch(int)}, which is what you call to say that you
10340     * have focus, and you want your parent to look for the next one.
10341     *
10342     * You may wish to override this method if your custom {@link View} has an internal
10343     * {@link View} that it wishes to forward the request to.
10344     *
10345     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10346     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10347     *        to give a finer grained hint about where focus is coming from.  May be null
10348     *        if there is no hint.
10349     * @return Whether this view or one of its descendants actually took focus.
10350     */
10351    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10352        return requestFocusNoSearch(direction, previouslyFocusedRect);
10353    }
10354
10355    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10356        // need to be focusable
10357        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10358                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10359            return false;
10360        }
10361
10362        // need to be focusable in touch mode if in touch mode
10363        if (isInTouchMode() &&
10364            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10365               return false;
10366        }
10367
10368        // need to not have any parents blocking us
10369        if (hasAncestorThatBlocksDescendantFocus()) {
10370            return false;
10371        }
10372
10373        handleFocusGainInternal(direction, previouslyFocusedRect);
10374        return true;
10375    }
10376
10377    /**
10378     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10379     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10380     * touch mode to request focus when they are touched.
10381     *
10382     * @return Whether this view or one of its descendants actually took focus.
10383     *
10384     * @see #isInTouchMode()
10385     *
10386     */
10387    public final boolean requestFocusFromTouch() {
10388        // Leave touch mode if we need to
10389        if (isInTouchMode()) {
10390            ViewRootImpl viewRoot = getViewRootImpl();
10391            if (viewRoot != null) {
10392                viewRoot.ensureTouchMode(false);
10393            }
10394        }
10395        return requestFocus(View.FOCUS_DOWN);
10396    }
10397
10398    /**
10399     * @return Whether any ancestor of this view blocks descendant focus.
10400     */
10401    private boolean hasAncestorThatBlocksDescendantFocus() {
10402        final boolean focusableInTouchMode = isFocusableInTouchMode();
10403        ViewParent ancestor = mParent;
10404        while (ancestor instanceof ViewGroup) {
10405            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10406            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10407                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10408                return true;
10409            } else {
10410                ancestor = vgAncestor.getParent();
10411            }
10412        }
10413        return false;
10414    }
10415
10416    /**
10417     * Gets the mode for determining whether this View is important for accessibility.
10418     * A view is important for accessibility if it fires accessibility events and if it
10419     * is reported to accessibility services that query the screen.
10420     *
10421     * @return The mode for determining whether a view is important for accessibility, one
10422     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10423     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10424     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10425     *
10426     * @attr ref android.R.styleable#View_importantForAccessibility
10427     *
10428     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10429     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10430     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10431     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10432     */
10433    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10434            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10435            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10436            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10437            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10438                    to = "noHideDescendants")
10439        })
10440    public int getImportantForAccessibility() {
10441        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10442                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10443    }
10444
10445    /**
10446     * Sets the live region mode for this view. This indicates to accessibility
10447     * services whether they should automatically notify the user about changes
10448     * to the view's content description or text, or to the content descriptions
10449     * or text of the view's children (where applicable).
10450     * <p>
10451     * For example, in a login screen with a TextView that displays an "incorrect
10452     * password" notification, that view should be marked as a live region with
10453     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10454     * <p>
10455     * To disable change notifications for this view, use
10456     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10457     * mode for most views.
10458     * <p>
10459     * To indicate that the user should be notified of changes, use
10460     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10461     * <p>
10462     * If the view's changes should interrupt ongoing speech and notify the user
10463     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10464     *
10465     * @param mode The live region mode for this view, one of:
10466     *        <ul>
10467     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10468     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10469     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10470     *        </ul>
10471     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10472     */
10473    public void setAccessibilityLiveRegion(int mode) {
10474        if (mode != getAccessibilityLiveRegion()) {
10475            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10476            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10477                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10478            notifyViewAccessibilityStateChangedIfNeeded(
10479                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10480        }
10481    }
10482
10483    /**
10484     * Gets the live region mode for this View.
10485     *
10486     * @return The live region mode for the view.
10487     *
10488     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10489     *
10490     * @see #setAccessibilityLiveRegion(int)
10491     */
10492    public int getAccessibilityLiveRegion() {
10493        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10494                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10495    }
10496
10497    /**
10498     * Sets how to determine whether this view is important for accessibility
10499     * which is if it fires accessibility events and if it is reported to
10500     * accessibility services that query the screen.
10501     *
10502     * @param mode How to determine whether this view is important for accessibility.
10503     *
10504     * @attr ref android.R.styleable#View_importantForAccessibility
10505     *
10506     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10507     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10508     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10509     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10510     */
10511    public void setImportantForAccessibility(int mode) {
10512        final int oldMode = getImportantForAccessibility();
10513        if (mode != oldMode) {
10514            final boolean hideDescendants =
10515                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10516
10517            // If this node or its descendants are no longer important, try to
10518            // clear accessibility focus.
10519            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10520                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10521                if (focusHost != null) {
10522                    focusHost.clearAccessibilityFocus();
10523                }
10524            }
10525
10526            // If we're moving between AUTO and another state, we might not need
10527            // to send a subtree changed notification. We'll store the computed
10528            // importance, since we'll need to check it later to make sure.
10529            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10530                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10531            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10532            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10533            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10534                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10535            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10536                notifySubtreeAccessibilityStateChangedIfNeeded();
10537            } else {
10538                notifyViewAccessibilityStateChangedIfNeeded(
10539                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10540            }
10541        }
10542    }
10543
10544    /**
10545     * Returns the view within this view's hierarchy that is hosting
10546     * accessibility focus.
10547     *
10548     * @param searchDescendants whether to search for focus in descendant views
10549     * @return the view hosting accessibility focus, or {@code null}
10550     */
10551    private View findAccessibilityFocusHost(boolean searchDescendants) {
10552        if (isAccessibilityFocusedViewOrHost()) {
10553            return this;
10554        }
10555
10556        if (searchDescendants) {
10557            final ViewRootImpl viewRoot = getViewRootImpl();
10558            if (viewRoot != null) {
10559                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10560                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10561                    return focusHost;
10562                }
10563            }
10564        }
10565
10566        return null;
10567    }
10568
10569    /**
10570     * Computes whether this view should be exposed for accessibility. In
10571     * general, views that are interactive or provide information are exposed
10572     * while views that serve only as containers are hidden.
10573     * <p>
10574     * If an ancestor of this view has importance
10575     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10576     * returns <code>false</code>.
10577     * <p>
10578     * Otherwise, the value is computed according to the view's
10579     * {@link #getImportantForAccessibility()} value:
10580     * <ol>
10581     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10582     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10583     * </code>
10584     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10585     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10586     * view satisfies any of the following:
10587     * <ul>
10588     * <li>Is actionable, e.g. {@link #isClickable()},
10589     * {@link #isLongClickable()}, or {@link #isFocusable()}
10590     * <li>Has an {@link AccessibilityDelegate}
10591     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10592     * {@link OnKeyListener}, etc.
10593     * <li>Is an accessibility live region, e.g.
10594     * {@link #getAccessibilityLiveRegion()} is not
10595     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10596     * </ul>
10597     * </ol>
10598     *
10599     * @return Whether the view is exposed for accessibility.
10600     * @see #setImportantForAccessibility(int)
10601     * @see #getImportantForAccessibility()
10602     */
10603    public boolean isImportantForAccessibility() {
10604        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10605                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10606        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10607                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10608            return false;
10609        }
10610
10611        // Check parent mode to ensure we're not hidden.
10612        ViewParent parent = mParent;
10613        while (parent instanceof View) {
10614            if (((View) parent).getImportantForAccessibility()
10615                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10616                return false;
10617            }
10618            parent = parent.getParent();
10619        }
10620
10621        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10622                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10623                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10624    }
10625
10626    /**
10627     * Gets the parent for accessibility purposes. Note that the parent for
10628     * accessibility is not necessary the immediate parent. It is the first
10629     * predecessor that is important for accessibility.
10630     *
10631     * @return The parent for accessibility purposes.
10632     */
10633    public ViewParent getParentForAccessibility() {
10634        if (mParent instanceof View) {
10635            View parentView = (View) mParent;
10636            if (parentView.includeForAccessibility()) {
10637                return mParent;
10638            } else {
10639                return mParent.getParentForAccessibility();
10640            }
10641        }
10642        return null;
10643    }
10644
10645    /**
10646     * Adds the children of this View relevant for accessibility to the given list
10647     * as output. Since some Views are not important for accessibility the added
10648     * child views are not necessarily direct children of this view, rather they are
10649     * the first level of descendants important for accessibility.
10650     *
10651     * @param outChildren The output list that will receive children for accessibility.
10652     */
10653    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10654
10655    }
10656
10657    /**
10658     * Whether to regard this view for accessibility. A view is regarded for
10659     * accessibility if it is important for accessibility or the querying
10660     * accessibility service has explicitly requested that view not
10661     * important for accessibility are regarded.
10662     *
10663     * @return Whether to regard the view for accessibility.
10664     *
10665     * @hide
10666     */
10667    public boolean includeForAccessibility() {
10668        if (mAttachInfo != null) {
10669            return (mAttachInfo.mAccessibilityFetchFlags
10670                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10671                    || isImportantForAccessibility();
10672        }
10673        return false;
10674    }
10675
10676    /**
10677     * Returns whether the View is considered actionable from
10678     * accessibility perspective. Such view are important for
10679     * accessibility.
10680     *
10681     * @return True if the view is actionable for accessibility.
10682     *
10683     * @hide
10684     */
10685    public boolean isActionableForAccessibility() {
10686        return (isClickable() || isLongClickable() || isFocusable());
10687    }
10688
10689    /**
10690     * Returns whether the View has registered callbacks which makes it
10691     * important for accessibility.
10692     *
10693     * @return True if the view is actionable for accessibility.
10694     */
10695    private boolean hasListenersForAccessibility() {
10696        ListenerInfo info = getListenerInfo();
10697        return mTouchDelegate != null || info.mOnKeyListener != null
10698                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10699                || info.mOnHoverListener != null || info.mOnDragListener != null;
10700    }
10701
10702    /**
10703     * Notifies that the accessibility state of this view changed. The change
10704     * is local to this view and does not represent structural changes such
10705     * as children and parent. For example, the view became focusable. The
10706     * notification is at at most once every
10707     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10708     * to avoid unnecessary load to the system. Also once a view has a pending
10709     * notification this method is a NOP until the notification has been sent.
10710     *
10711     * @hide
10712     */
10713    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10714        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10715            return;
10716        }
10717        if (mSendViewStateChangedAccessibilityEvent == null) {
10718            mSendViewStateChangedAccessibilityEvent =
10719                    new SendViewStateChangedAccessibilityEvent();
10720        }
10721        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10722    }
10723
10724    /**
10725     * Notifies that the accessibility state of this view changed. The change
10726     * is *not* local to this view and does represent structural changes such
10727     * as children and parent. For example, the view size changed. The
10728     * notification is at at most once every
10729     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10730     * to avoid unnecessary load to the system. Also once a view has a pending
10731     * notification this method is a NOP until the notification has been sent.
10732     *
10733     * @hide
10734     */
10735    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10736        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10737            return;
10738        }
10739        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10740            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10741            if (mParent != null) {
10742                try {
10743                    mParent.notifySubtreeAccessibilityStateChanged(
10744                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10745                } catch (AbstractMethodError e) {
10746                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10747                            " does not fully implement ViewParent", e);
10748                }
10749            }
10750        }
10751    }
10752
10753    /**
10754     * Change the visibility of the View without triggering any other changes. This is
10755     * important for transitions, where visibility changes should not adjust focus or
10756     * trigger a new layout. This is only used when the visibility has already been changed
10757     * and we need a transient value during an animation. When the animation completes,
10758     * the original visibility value is always restored.
10759     *
10760     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10761     * @hide
10762     */
10763    public void setTransitionVisibility(@Visibility int visibility) {
10764        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10765    }
10766
10767    /**
10768     * Reset the flag indicating the accessibility state of the subtree rooted
10769     * at this view changed.
10770     */
10771    void resetSubtreeAccessibilityStateChanged() {
10772        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10773    }
10774
10775    /**
10776     * Report an accessibility action to this view's parents for delegated processing.
10777     *
10778     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10779     * call this method to delegate an accessibility action to a supporting parent. If the parent
10780     * returns true from its
10781     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10782     * method this method will return true to signify that the action was consumed.</p>
10783     *
10784     * <p>This method is useful for implementing nested scrolling child views. If
10785     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10786     * a custom view implementation may invoke this method to allow a parent to consume the
10787     * scroll first. If this method returns true the custom view should skip its own scrolling
10788     * behavior.</p>
10789     *
10790     * @param action Accessibility action to delegate
10791     * @param arguments Optional action arguments
10792     * @return true if the action was consumed by a parent
10793     */
10794    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10795        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10796            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10797                return true;
10798            }
10799        }
10800        return false;
10801    }
10802
10803    /**
10804     * Performs the specified accessibility action on the view. For
10805     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10806     * <p>
10807     * If an {@link AccessibilityDelegate} has been specified via calling
10808     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10809     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10810     * is responsible for handling this call.
10811     * </p>
10812     *
10813     * <p>The default implementation will delegate
10814     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10815     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10816     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10817     *
10818     * @param action The action to perform.
10819     * @param arguments Optional action arguments.
10820     * @return Whether the action was performed.
10821     */
10822    public boolean performAccessibilityAction(int action, Bundle arguments) {
10823      if (mAccessibilityDelegate != null) {
10824          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10825      } else {
10826          return performAccessibilityActionInternal(action, arguments);
10827      }
10828    }
10829
10830   /**
10831    * @see #performAccessibilityAction(int, Bundle)
10832    *
10833    * Note: Called from the default {@link AccessibilityDelegate}.
10834    *
10835    * @hide
10836    */
10837    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10838        if (isNestedScrollingEnabled()
10839                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10840                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10841                || action == R.id.accessibilityActionScrollUp
10842                || action == R.id.accessibilityActionScrollLeft
10843                || action == R.id.accessibilityActionScrollDown
10844                || action == R.id.accessibilityActionScrollRight)) {
10845            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10846                return true;
10847            }
10848        }
10849
10850        switch (action) {
10851            case AccessibilityNodeInfo.ACTION_CLICK: {
10852                if (isClickable()) {
10853                    performClick();
10854                    return true;
10855                }
10856            } break;
10857            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10858                if (isLongClickable()) {
10859                    performLongClick();
10860                    return true;
10861                }
10862            } break;
10863            case AccessibilityNodeInfo.ACTION_FOCUS: {
10864                if (!hasFocus()) {
10865                    // Get out of touch mode since accessibility
10866                    // wants to move focus around.
10867                    getViewRootImpl().ensureTouchMode(false);
10868                    return requestFocus();
10869                }
10870            } break;
10871            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10872                if (hasFocus()) {
10873                    clearFocus();
10874                    return !isFocused();
10875                }
10876            } break;
10877            case AccessibilityNodeInfo.ACTION_SELECT: {
10878                if (!isSelected()) {
10879                    setSelected(true);
10880                    return isSelected();
10881                }
10882            } break;
10883            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10884                if (isSelected()) {
10885                    setSelected(false);
10886                    return !isSelected();
10887                }
10888            } break;
10889            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10890                if (!isAccessibilityFocused()) {
10891                    return requestAccessibilityFocus();
10892                }
10893            } break;
10894            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10895                if (isAccessibilityFocused()) {
10896                    clearAccessibilityFocus();
10897                    return true;
10898                }
10899            } break;
10900            case AccessibilityNodeInfo.ACTION_NEXT_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, true, extendSelection);
10907                }
10908            } break;
10909            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10910                if (arguments != null) {
10911                    final int granularity = arguments.getInt(
10912                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10913                    final boolean extendSelection = arguments.getBoolean(
10914                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10915                    return traverseAtGranularity(granularity, false, extendSelection);
10916                }
10917            } break;
10918            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10919                CharSequence text = getIterableTextForAccessibility();
10920                if (text == null) {
10921                    return false;
10922                }
10923                final int start = (arguments != null) ? arguments.getInt(
10924                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10925                final int end = (arguments != null) ? arguments.getInt(
10926                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10927                // Only cursor position can be specified (selection length == 0)
10928                if ((getAccessibilitySelectionStart() != start
10929                        || getAccessibilitySelectionEnd() != end)
10930                        && (start == end)) {
10931                    setAccessibilitySelection(start, end);
10932                    notifyViewAccessibilityStateChangedIfNeeded(
10933                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10934                    return true;
10935                }
10936            } break;
10937            case R.id.accessibilityActionShowOnScreen: {
10938                if (mAttachInfo != null) {
10939                    final Rect r = mAttachInfo.mTmpInvalRect;
10940                    getDrawingRect(r);
10941                    return requestRectangleOnScreen(r, true);
10942                }
10943            } break;
10944            case R.id.accessibilityActionContextClick: {
10945                if (isContextClickable()) {
10946                    performContextClick();
10947                    return true;
10948                }
10949            } break;
10950        }
10951        return false;
10952    }
10953
10954    private boolean traverseAtGranularity(int granularity, boolean forward,
10955            boolean extendSelection) {
10956        CharSequence text = getIterableTextForAccessibility();
10957        if (text == null || text.length() == 0) {
10958            return false;
10959        }
10960        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
10961        if (iterator == null) {
10962            return false;
10963        }
10964        int current = getAccessibilitySelectionEnd();
10965        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10966            current = forward ? 0 : text.length();
10967        }
10968        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
10969        if (range == null) {
10970            return false;
10971        }
10972        final int segmentStart = range[0];
10973        final int segmentEnd = range[1];
10974        int selectionStart;
10975        int selectionEnd;
10976        if (extendSelection && isAccessibilitySelectionExtendable()) {
10977            selectionStart = getAccessibilitySelectionStart();
10978            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10979                selectionStart = forward ? segmentStart : segmentEnd;
10980            }
10981            selectionEnd = forward ? segmentEnd : segmentStart;
10982        } else {
10983            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
10984        }
10985        setAccessibilitySelection(selectionStart, selectionEnd);
10986        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
10987                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
10988        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
10989        return true;
10990    }
10991
10992    /**
10993     * Gets the text reported for accessibility purposes.
10994     *
10995     * @return The accessibility text.
10996     *
10997     * @hide
10998     */
10999    public CharSequence getIterableTextForAccessibility() {
11000        return getContentDescription();
11001    }
11002
11003    /**
11004     * Gets whether accessibility selection can be extended.
11005     *
11006     * @return If selection is extensible.
11007     *
11008     * @hide
11009     */
11010    public boolean isAccessibilitySelectionExtendable() {
11011        return false;
11012    }
11013
11014    /**
11015     * @hide
11016     */
11017    public int getAccessibilitySelectionStart() {
11018        return mAccessibilityCursorPosition;
11019    }
11020
11021    /**
11022     * @hide
11023     */
11024    public int getAccessibilitySelectionEnd() {
11025        return getAccessibilitySelectionStart();
11026    }
11027
11028    /**
11029     * @hide
11030     */
11031    public void setAccessibilitySelection(int start, int end) {
11032        if (start ==  end && end == mAccessibilityCursorPosition) {
11033            return;
11034        }
11035        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11036            mAccessibilityCursorPosition = start;
11037        } else {
11038            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11039        }
11040        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11041    }
11042
11043    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11044            int fromIndex, int toIndex) {
11045        if (mParent == null) {
11046            return;
11047        }
11048        AccessibilityEvent event = AccessibilityEvent.obtain(
11049                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11050        onInitializeAccessibilityEvent(event);
11051        onPopulateAccessibilityEvent(event);
11052        event.setFromIndex(fromIndex);
11053        event.setToIndex(toIndex);
11054        event.setAction(action);
11055        event.setMovementGranularity(granularity);
11056        mParent.requestSendAccessibilityEvent(this, event);
11057    }
11058
11059    /**
11060     * @hide
11061     */
11062    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11063        switch (granularity) {
11064            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11065                CharSequence text = getIterableTextForAccessibility();
11066                if (text != null && text.length() > 0) {
11067                    CharacterTextSegmentIterator iterator =
11068                        CharacterTextSegmentIterator.getInstance(
11069                                mContext.getResources().getConfiguration().locale);
11070                    iterator.initialize(text.toString());
11071                    return iterator;
11072                }
11073            } break;
11074            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11075                CharSequence text = getIterableTextForAccessibility();
11076                if (text != null && text.length() > 0) {
11077                    WordTextSegmentIterator iterator =
11078                        WordTextSegmentIterator.getInstance(
11079                                mContext.getResources().getConfiguration().locale);
11080                    iterator.initialize(text.toString());
11081                    return iterator;
11082                }
11083            } break;
11084            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11085                CharSequence text = getIterableTextForAccessibility();
11086                if (text != null && text.length() > 0) {
11087                    ParagraphTextSegmentIterator iterator =
11088                        ParagraphTextSegmentIterator.getInstance();
11089                    iterator.initialize(text.toString());
11090                    return iterator;
11091                }
11092            } break;
11093        }
11094        return null;
11095    }
11096
11097    /**
11098     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11099     * and {@link #onFinishTemporaryDetach()}.
11100     *
11101     * <p>This method always returns {@code true} when called directly or indirectly from
11102     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11103     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11104     * <ul>
11105     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11106     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11107     * </ul>
11108     * </p>
11109     *
11110     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11111     * and {@link #onFinishTemporaryDetach()}.
11112     */
11113    public final boolean isTemporarilyDetached() {
11114        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11115    }
11116
11117    /**
11118     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11119     * a container View.
11120     */
11121    @CallSuper
11122    public void dispatchStartTemporaryDetach() {
11123        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11124        notifyEnterOrExitForAutoFillIfNeeded(false);
11125        onStartTemporaryDetach();
11126    }
11127
11128    /**
11129     * This is called when a container is going to temporarily detach a child, with
11130     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11131     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11132     * {@link #onDetachedFromWindow()} when the container is done.
11133     */
11134    public void onStartTemporaryDetach() {
11135        removeUnsetPressCallback();
11136        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11137    }
11138
11139    /**
11140     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11141     * a container View.
11142     */
11143    @CallSuper
11144    public void dispatchFinishTemporaryDetach() {
11145        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11146        onFinishTemporaryDetach();
11147        if (hasWindowFocus() && hasFocus()) {
11148            InputMethodManager.getInstance().focusIn(this);
11149        }
11150        notifyEnterOrExitForAutoFillIfNeeded(true);
11151    }
11152
11153    /**
11154     * Called after {@link #onStartTemporaryDetach} when the container is done
11155     * changing the view.
11156     */
11157    public void onFinishTemporaryDetach() {
11158    }
11159
11160    /**
11161     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11162     * for this view's window.  Returns null if the view is not currently attached
11163     * to the window.  Normally you will not need to use this directly, but
11164     * just use the standard high-level event callbacks like
11165     * {@link #onKeyDown(int, KeyEvent)}.
11166     */
11167    public KeyEvent.DispatcherState getKeyDispatcherState() {
11168        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11169    }
11170
11171    /**
11172     * Dispatch a key event before it is processed by any input method
11173     * associated with the view hierarchy.  This can be used to intercept
11174     * key events in special situations before the IME consumes them; a
11175     * typical example would be handling the BACK key to update the application's
11176     * UI instead of allowing the IME to see it and close itself.
11177     *
11178     * @param event The key event to be dispatched.
11179     * @return True if the event was handled, false otherwise.
11180     */
11181    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11182        return onKeyPreIme(event.getKeyCode(), event);
11183    }
11184
11185    /**
11186     * Dispatch a key event to the next view on the focus path. This path runs
11187     * from the top of the view tree down to the currently focused view. If this
11188     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11189     * the next node down the focus path. This method also fires any key
11190     * listeners.
11191     *
11192     * @param event The key event to be dispatched.
11193     * @return True if the event was handled, false otherwise.
11194     */
11195    public boolean dispatchKeyEvent(KeyEvent event) {
11196        if (mInputEventConsistencyVerifier != null) {
11197            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11198        }
11199
11200        // Give any attached key listener a first crack at the event.
11201        //noinspection SimplifiableIfStatement
11202        ListenerInfo li = mListenerInfo;
11203        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11204                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11205            return true;
11206        }
11207
11208        if (event.dispatch(this, mAttachInfo != null
11209                ? mAttachInfo.mKeyDispatchState : null, this)) {
11210            return true;
11211        }
11212
11213        if (mInputEventConsistencyVerifier != null) {
11214            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11215        }
11216        return false;
11217    }
11218
11219    /**
11220     * Dispatches a key shortcut event.
11221     *
11222     * @param event The key event to be dispatched.
11223     * @return True if the event was handled by the view, false otherwise.
11224     */
11225    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11226        return onKeyShortcut(event.getKeyCode(), event);
11227    }
11228
11229    /**
11230     * Pass the touch screen motion event down to the target view, or this
11231     * view if it is the target.
11232     *
11233     * @param event The motion event to be dispatched.
11234     * @return True if the event was handled by the view, false otherwise.
11235     */
11236    public boolean dispatchTouchEvent(MotionEvent event) {
11237        // If the event should be handled by accessibility focus first.
11238        if (event.isTargetAccessibilityFocus()) {
11239            // We don't have focus or no virtual descendant has it, do not handle the event.
11240            if (!isAccessibilityFocusedViewOrHost()) {
11241                return false;
11242            }
11243            // We have focus and got the event, then use normal event dispatch.
11244            event.setTargetAccessibilityFocus(false);
11245        }
11246
11247        boolean result = false;
11248
11249        if (mInputEventConsistencyVerifier != null) {
11250            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11251        }
11252
11253        final int actionMasked = event.getActionMasked();
11254        if (actionMasked == MotionEvent.ACTION_DOWN) {
11255            // Defensive cleanup for new gesture
11256            stopNestedScroll();
11257        }
11258
11259        if (onFilterTouchEventForSecurity(event)) {
11260            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11261                result = true;
11262            }
11263            //noinspection SimplifiableIfStatement
11264            ListenerInfo li = mListenerInfo;
11265            if (li != null && li.mOnTouchListener != null
11266                    && (mViewFlags & ENABLED_MASK) == ENABLED
11267                    && li.mOnTouchListener.onTouch(this, event)) {
11268                result = true;
11269            }
11270
11271            if (!result && onTouchEvent(event)) {
11272                result = true;
11273            }
11274        }
11275
11276        if (!result && mInputEventConsistencyVerifier != null) {
11277            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11278        }
11279
11280        // Clean up after nested scrolls if this is the end of a gesture;
11281        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11282        // of the gesture.
11283        if (actionMasked == MotionEvent.ACTION_UP ||
11284                actionMasked == MotionEvent.ACTION_CANCEL ||
11285                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11286            stopNestedScroll();
11287        }
11288
11289        return result;
11290    }
11291
11292    boolean isAccessibilityFocusedViewOrHost() {
11293        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11294                .getAccessibilityFocusedHost() == this);
11295    }
11296
11297    /**
11298     * Filter the touch event to apply security policies.
11299     *
11300     * @param event The motion event to be filtered.
11301     * @return True if the event should be dispatched, false if the event should be dropped.
11302     *
11303     * @see #getFilterTouchesWhenObscured
11304     */
11305    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11306        //noinspection RedundantIfStatement
11307        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11308                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11309            // Window is obscured, drop this touch.
11310            return false;
11311        }
11312        return true;
11313    }
11314
11315    /**
11316     * Pass a trackball motion event down to the focused view.
11317     *
11318     * @param event The motion event to be dispatched.
11319     * @return True if the event was handled by the view, false otherwise.
11320     */
11321    public boolean dispatchTrackballEvent(MotionEvent event) {
11322        if (mInputEventConsistencyVerifier != null) {
11323            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11324        }
11325
11326        return onTrackballEvent(event);
11327    }
11328
11329    /**
11330     * Pass a captured pointer event down to the focused view.
11331     *
11332     * @param event The motion event to be dispatched.
11333     * @return True if the event was handled by the view, false otherwise.
11334     */
11335    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11336        if (!hasPointerCapture()) {
11337            return false;
11338        }
11339        //noinspection SimplifiableIfStatement
11340        ListenerInfo li = mListenerInfo;
11341        if (li != null && li.mOnCapturedPointerListener != null
11342                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11343            return true;
11344        }
11345        return onCapturedPointerEvent(event);
11346    }
11347
11348    /**
11349     * Dispatch a generic motion event.
11350     * <p>
11351     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11352     * are delivered to the view under the pointer.  All other generic motion events are
11353     * delivered to the focused view.  Hover events are handled specially and are delivered
11354     * to {@link #onHoverEvent(MotionEvent)}.
11355     * </p>
11356     *
11357     * @param event The motion event to be dispatched.
11358     * @return True if the event was handled by the view, false otherwise.
11359     */
11360    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11361        if (mInputEventConsistencyVerifier != null) {
11362            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11363        }
11364
11365        final int source = event.getSource();
11366        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11367            final int action = event.getAction();
11368            if (action == MotionEvent.ACTION_HOVER_ENTER
11369                    || action == MotionEvent.ACTION_HOVER_MOVE
11370                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11371                if (dispatchHoverEvent(event)) {
11372                    return true;
11373                }
11374            } else if (dispatchGenericPointerEvent(event)) {
11375                return true;
11376            }
11377        } else if (dispatchGenericFocusedEvent(event)) {
11378            return true;
11379        }
11380
11381        if (dispatchGenericMotionEventInternal(event)) {
11382            return true;
11383        }
11384
11385        if (mInputEventConsistencyVerifier != null) {
11386            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11387        }
11388        return false;
11389    }
11390
11391    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11392        //noinspection SimplifiableIfStatement
11393        ListenerInfo li = mListenerInfo;
11394        if (li != null && li.mOnGenericMotionListener != null
11395                && (mViewFlags & ENABLED_MASK) == ENABLED
11396                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11397            return true;
11398        }
11399
11400        if (onGenericMotionEvent(event)) {
11401            return true;
11402        }
11403
11404        final int actionButton = event.getActionButton();
11405        switch (event.getActionMasked()) {
11406            case MotionEvent.ACTION_BUTTON_PRESS:
11407                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11408                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11409                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11410                    if (performContextClick(event.getX(), event.getY())) {
11411                        mInContextButtonPress = true;
11412                        setPressed(true, event.getX(), event.getY());
11413                        removeTapCallback();
11414                        removeLongPressCallback();
11415                        return true;
11416                    }
11417                }
11418                break;
11419
11420            case MotionEvent.ACTION_BUTTON_RELEASE:
11421                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11422                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11423                    mInContextButtonPress = false;
11424                    mIgnoreNextUpEvent = true;
11425                }
11426                break;
11427        }
11428
11429        if (mInputEventConsistencyVerifier != null) {
11430            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11431        }
11432        return false;
11433    }
11434
11435    /**
11436     * Dispatch a hover event.
11437     * <p>
11438     * Do not call this method directly.
11439     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11440     * </p>
11441     *
11442     * @param event The motion event to be dispatched.
11443     * @return True if the event was handled by the view, false otherwise.
11444     */
11445    protected boolean dispatchHoverEvent(MotionEvent event) {
11446        ListenerInfo li = mListenerInfo;
11447        //noinspection SimplifiableIfStatement
11448        if (li != null && li.mOnHoverListener != null
11449                && (mViewFlags & ENABLED_MASK) == ENABLED
11450                && li.mOnHoverListener.onHover(this, event)) {
11451            return true;
11452        }
11453
11454        return onHoverEvent(event);
11455    }
11456
11457    /**
11458     * Returns true if the view has a child to which it has recently sent
11459     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11460     * it does not have a hovered child, then it must be the innermost hovered view.
11461     * @hide
11462     */
11463    protected boolean hasHoveredChild() {
11464        return false;
11465    }
11466
11467    /**
11468     * Dispatch a generic motion event to the view under the first pointer.
11469     * <p>
11470     * Do not call this method directly.
11471     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11472     * </p>
11473     *
11474     * @param event The motion event to be dispatched.
11475     * @return True if the event was handled by the view, false otherwise.
11476     */
11477    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11478        return false;
11479    }
11480
11481    /**
11482     * Dispatch a generic motion event to the currently focused view.
11483     * <p>
11484     * Do not call this method directly.
11485     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11486     * </p>
11487     *
11488     * @param event The motion event to be dispatched.
11489     * @return True if the event was handled by the view, false otherwise.
11490     */
11491    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11492        return false;
11493    }
11494
11495    /**
11496     * Dispatch a pointer event.
11497     * <p>
11498     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11499     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11500     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11501     * and should not be expected to handle other pointing device features.
11502     * </p>
11503     *
11504     * @param event The motion event to be dispatched.
11505     * @return True if the event was handled by the view, false otherwise.
11506     * @hide
11507     */
11508    public final boolean dispatchPointerEvent(MotionEvent event) {
11509        if (event.isTouchEvent()) {
11510            return dispatchTouchEvent(event);
11511        } else {
11512            return dispatchGenericMotionEvent(event);
11513        }
11514    }
11515
11516    /**
11517     * Called when the window containing this view gains or loses window focus.
11518     * ViewGroups should override to route to their children.
11519     *
11520     * @param hasFocus True if the window containing this view now has focus,
11521     *        false otherwise.
11522     */
11523    public void dispatchWindowFocusChanged(boolean hasFocus) {
11524        onWindowFocusChanged(hasFocus);
11525    }
11526
11527    /**
11528     * Called when the window containing this view gains or loses focus.  Note
11529     * that this is separate from view focus: to receive key events, both
11530     * your view and its window must have focus.  If a window is displayed
11531     * on top of yours that takes input focus, then your own window will lose
11532     * focus but the view focus will remain unchanged.
11533     *
11534     * @param hasWindowFocus True if the window containing this view now has
11535     *        focus, false otherwise.
11536     */
11537    public void onWindowFocusChanged(boolean hasWindowFocus) {
11538        InputMethodManager imm = InputMethodManager.peekInstance();
11539        if (!hasWindowFocus) {
11540            if (isPressed()) {
11541                setPressed(false);
11542            }
11543            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11544            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11545                imm.focusOut(this);
11546            }
11547            removeLongPressCallback();
11548            removeTapCallback();
11549            onFocusLost();
11550        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11551            imm.focusIn(this);
11552        }
11553
11554        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11555
11556        refreshDrawableState();
11557    }
11558
11559    /**
11560     * Returns true if this view is in a window that currently has window focus.
11561     * Note that this is not the same as the view itself having focus.
11562     *
11563     * @return True if this view is in a window that currently has window focus.
11564     */
11565    public boolean hasWindowFocus() {
11566        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11567    }
11568
11569    /**
11570     * Dispatch a view visibility change down the view hierarchy.
11571     * ViewGroups should override to route to their children.
11572     * @param changedView The view whose visibility changed. Could be 'this' or
11573     * an ancestor view.
11574     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11575     * {@link #INVISIBLE} or {@link #GONE}.
11576     */
11577    protected void dispatchVisibilityChanged(@NonNull View changedView,
11578            @Visibility int visibility) {
11579        onVisibilityChanged(changedView, visibility);
11580    }
11581
11582    /**
11583     * Called when the visibility of the view or an ancestor of the view has
11584     * changed.
11585     *
11586     * @param changedView The view whose visibility changed. May be
11587     *                    {@code this} or an ancestor view.
11588     * @param visibility The new visibility, one of {@link #VISIBLE},
11589     *                   {@link #INVISIBLE} or {@link #GONE}.
11590     */
11591    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11592    }
11593
11594    /**
11595     * Dispatch a hint about whether this view is displayed. For instance, when
11596     * a View moves out of the screen, it might receives a display hint indicating
11597     * the view is not displayed. Applications should not <em>rely</em> on this hint
11598     * as there is no guarantee that they will receive one.
11599     *
11600     * @param hint A hint about whether or not this view is displayed:
11601     * {@link #VISIBLE} or {@link #INVISIBLE}.
11602     */
11603    public void dispatchDisplayHint(@Visibility int hint) {
11604        onDisplayHint(hint);
11605    }
11606
11607    /**
11608     * Gives this view a hint about whether is displayed or not. For instance, when
11609     * a View moves out of the screen, it might receives a display hint indicating
11610     * the view is not displayed. Applications should not <em>rely</em> on this hint
11611     * as there is no guarantee that they will receive one.
11612     *
11613     * @param hint A hint about whether or not this view is displayed:
11614     * {@link #VISIBLE} or {@link #INVISIBLE}.
11615     */
11616    protected void onDisplayHint(@Visibility int hint) {
11617    }
11618
11619    /**
11620     * Dispatch a window visibility change down the view hierarchy.
11621     * ViewGroups should override to route to their children.
11622     *
11623     * @param visibility The new visibility of the window.
11624     *
11625     * @see #onWindowVisibilityChanged(int)
11626     */
11627    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11628        onWindowVisibilityChanged(visibility);
11629    }
11630
11631    /**
11632     * Called when the window containing has change its visibility
11633     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11634     * that this tells you whether or not your window is being made visible
11635     * to the window manager; this does <em>not</em> tell you whether or not
11636     * your window is obscured by other windows on the screen, even if it
11637     * is itself visible.
11638     *
11639     * @param visibility The new visibility of the window.
11640     */
11641    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11642        if (visibility == VISIBLE) {
11643            initialAwakenScrollBars();
11644        }
11645    }
11646
11647    /**
11648     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11649     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11650     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11651     *
11652     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11653     *                  ancestors or by window visibility
11654     * @return true if this view is visible to the user, not counting clipping or overlapping
11655     */
11656    boolean dispatchVisibilityAggregated(boolean isVisible) {
11657        final boolean thisVisible = getVisibility() == VISIBLE;
11658        // If we're not visible but something is telling us we are, ignore it.
11659        if (thisVisible || !isVisible) {
11660            onVisibilityAggregated(isVisible);
11661        }
11662        return thisVisible && isVisible;
11663    }
11664
11665    /**
11666     * Called when the user-visibility of this View is potentially affected by a change
11667     * to this view itself, an ancestor view or the window this view is attached to.
11668     *
11669     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11670     *                  and this view's window is also visible
11671     */
11672    @CallSuper
11673    public void onVisibilityAggregated(boolean isVisible) {
11674        if (isVisible && mAttachInfo != null) {
11675            initialAwakenScrollBars();
11676        }
11677
11678        final Drawable dr = mBackground;
11679        if (dr != null && isVisible != dr.isVisible()) {
11680            dr.setVisible(isVisible, false);
11681        }
11682        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11683        if (fg != null && isVisible != fg.isVisible()) {
11684            fg.setVisible(isVisible, false);
11685        }
11686    }
11687
11688    /**
11689     * Returns the current visibility of the window this view is attached to
11690     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11691     *
11692     * @return Returns the current visibility of the view's window.
11693     */
11694    @Visibility
11695    public int getWindowVisibility() {
11696        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11697    }
11698
11699    /**
11700     * Retrieve the overall visible display size in which the window this view is
11701     * attached to has been positioned in.  This takes into account screen
11702     * decorations above the window, for both cases where the window itself
11703     * is being position inside of them or the window is being placed under
11704     * then and covered insets are used for the window to position its content
11705     * inside.  In effect, this tells you the available area where content can
11706     * be placed and remain visible to users.
11707     *
11708     * <p>This function requires an IPC back to the window manager to retrieve
11709     * the requested information, so should not be used in performance critical
11710     * code like drawing.
11711     *
11712     * @param outRect Filled in with the visible display frame.  If the view
11713     * is not attached to a window, this is simply the raw display size.
11714     */
11715    public void getWindowVisibleDisplayFrame(Rect outRect) {
11716        if (mAttachInfo != null) {
11717            try {
11718                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11719            } catch (RemoteException e) {
11720                return;
11721            }
11722            // XXX This is really broken, and probably all needs to be done
11723            // in the window manager, and we need to know more about whether
11724            // we want the area behind or in front of the IME.
11725            final Rect insets = mAttachInfo.mVisibleInsets;
11726            outRect.left += insets.left;
11727            outRect.top += insets.top;
11728            outRect.right -= insets.right;
11729            outRect.bottom -= insets.bottom;
11730            return;
11731        }
11732        // The view is not attached to a display so we don't have a context.
11733        // Make a best guess about the display size.
11734        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11735        d.getRectSize(outRect);
11736    }
11737
11738    /**
11739     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11740     * is currently in without any insets.
11741     *
11742     * @hide
11743     */
11744    public void getWindowDisplayFrame(Rect outRect) {
11745        if (mAttachInfo != null) {
11746            try {
11747                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11748            } catch (RemoteException e) {
11749                return;
11750            }
11751            return;
11752        }
11753        // The view is not attached to a display so we don't have a context.
11754        // Make a best guess about the display size.
11755        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11756        d.getRectSize(outRect);
11757    }
11758
11759    /**
11760     * Dispatch a notification about a resource configuration change down
11761     * the view hierarchy.
11762     * ViewGroups should override to route to their children.
11763     *
11764     * @param newConfig The new resource configuration.
11765     *
11766     * @see #onConfigurationChanged(android.content.res.Configuration)
11767     */
11768    public void dispatchConfigurationChanged(Configuration newConfig) {
11769        onConfigurationChanged(newConfig);
11770    }
11771
11772    /**
11773     * Called when the current configuration of the resources being used
11774     * by the application have changed.  You can use this to decide when
11775     * to reload resources that can changed based on orientation and other
11776     * configuration characteristics.  You only need to use this if you are
11777     * not relying on the normal {@link android.app.Activity} mechanism of
11778     * recreating the activity instance upon a configuration change.
11779     *
11780     * @param newConfig The new resource configuration.
11781     */
11782    protected void onConfigurationChanged(Configuration newConfig) {
11783    }
11784
11785    /**
11786     * Private function to aggregate all per-view attributes in to the view
11787     * root.
11788     */
11789    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11790        performCollectViewAttributes(attachInfo, visibility);
11791    }
11792
11793    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11794        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11795            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11796                attachInfo.mKeepScreenOn = true;
11797            }
11798            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11799            ListenerInfo li = mListenerInfo;
11800            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11801                attachInfo.mHasSystemUiListeners = true;
11802            }
11803        }
11804    }
11805
11806    void needGlobalAttributesUpdate(boolean force) {
11807        final AttachInfo ai = mAttachInfo;
11808        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11809            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11810                    || ai.mHasSystemUiListeners) {
11811                ai.mRecomputeGlobalAttributes = true;
11812            }
11813        }
11814    }
11815
11816    /**
11817     * Returns whether the device is currently in touch mode.  Touch mode is entered
11818     * once the user begins interacting with the device by touch, and affects various
11819     * things like whether focus is always visible to the user.
11820     *
11821     * @return Whether the device is in touch mode.
11822     */
11823    @ViewDebug.ExportedProperty
11824    public boolean isInTouchMode() {
11825        if (mAttachInfo != null) {
11826            return mAttachInfo.mInTouchMode;
11827        } else {
11828            return ViewRootImpl.isInTouchMode();
11829        }
11830    }
11831
11832    /**
11833     * Returns the context the view is running in, through which it can
11834     * access the current theme, resources, etc.
11835     *
11836     * @return The view's Context.
11837     */
11838    @ViewDebug.CapturedViewProperty
11839    public final Context getContext() {
11840        return mContext;
11841    }
11842
11843    /**
11844     * Handle a key event before it is processed by any input method
11845     * associated with the view hierarchy.  This can be used to intercept
11846     * key events in special situations before the IME consumes them; a
11847     * typical example would be handling the BACK key to update the application's
11848     * UI instead of allowing the IME to see it and close itself.
11849     *
11850     * @param keyCode The value in event.getKeyCode().
11851     * @param event Description of the key event.
11852     * @return If you handled the event, return true. If you want to allow the
11853     *         event to be handled by the next receiver, return false.
11854     */
11855    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11856        return false;
11857    }
11858
11859    /**
11860     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11861     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11862     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11863     * is released, if the view is enabled and clickable.
11864     * <p>
11865     * Key presses in software keyboards will generally NOT trigger this
11866     * listener, although some may elect to do so in some situations. Do not
11867     * rely on this to catch software key presses.
11868     *
11869     * @param keyCode a key code that represents the button pressed, from
11870     *                {@link android.view.KeyEvent}
11871     * @param event the KeyEvent object that defines the button action
11872     */
11873    public boolean onKeyDown(int keyCode, KeyEvent event) {
11874        if (KeyEvent.isConfirmKey(keyCode)) {
11875            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11876                return true;
11877            }
11878
11879            if (event.getRepeatCount() == 0) {
11880                // Long clickable items don't necessarily have to be clickable.
11881                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11882                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11883                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11884                    // For the purposes of menu anchoring and drawable hotspots,
11885                    // key events are considered to be at the center of the view.
11886                    final float x = getWidth() / 2f;
11887                    final float y = getHeight() / 2f;
11888                    if (clickable) {
11889                        setPressed(true, x, y);
11890                    }
11891                    checkForLongClick(0, x, y);
11892                    return true;
11893                }
11894            }
11895        }
11896
11897        return false;
11898    }
11899
11900    /**
11901     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11902     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11903     * the event).
11904     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11905     * although some may elect to do so in some situations. Do not rely on this to
11906     * catch software key presses.
11907     */
11908    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11909        return false;
11910    }
11911
11912    /**
11913     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11914     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11915     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11916     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11917     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11918     * although some may elect to do so in some situations. Do not rely on this to
11919     * catch software key presses.
11920     *
11921     * @param keyCode A key code that represents the button pressed, from
11922     *                {@link android.view.KeyEvent}.
11923     * @param event   The KeyEvent object that defines the button action.
11924     */
11925    public boolean onKeyUp(int keyCode, KeyEvent event) {
11926        if (KeyEvent.isConfirmKey(keyCode)) {
11927            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11928                return true;
11929            }
11930            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
11931                setPressed(false);
11932
11933                if (!mHasPerformedLongPress) {
11934                    // This is a tap, so remove the longpress check
11935                    removeLongPressCallback();
11936                    if (!event.isCanceled()) {
11937                        return performClick();
11938                    }
11939                }
11940            }
11941        }
11942        return false;
11943    }
11944
11945    /**
11946     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
11947     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
11948     * the event).
11949     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11950     * although some may elect to do so in some situations. Do not rely on this to
11951     * catch software key presses.
11952     *
11953     * @param keyCode     A key code that represents the button pressed, from
11954     *                    {@link android.view.KeyEvent}.
11955     * @param repeatCount The number of times the action was made.
11956     * @param event       The KeyEvent object that defines the button action.
11957     */
11958    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
11959        return false;
11960    }
11961
11962    /**
11963     * Called on the focused view when a key shortcut event is not handled.
11964     * Override this method to implement local key shortcuts for the View.
11965     * Key shortcuts can also be implemented by setting the
11966     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
11967     *
11968     * @param keyCode The value in event.getKeyCode().
11969     * @param event Description of the key event.
11970     * @return If you handled the event, return true. If you want to allow the
11971     *         event to be handled by the next receiver, return false.
11972     */
11973    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
11974        return false;
11975    }
11976
11977    /**
11978     * Check whether the called view is a text editor, in which case it
11979     * would make sense to automatically display a soft input window for
11980     * it.  Subclasses should override this if they implement
11981     * {@link #onCreateInputConnection(EditorInfo)} to return true if
11982     * a call on that method would return a non-null InputConnection, and
11983     * they are really a first-class editor that the user would normally
11984     * start typing on when the go into a window containing your view.
11985     *
11986     * <p>The default implementation always returns false.  This does
11987     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
11988     * will not be called or the user can not otherwise perform edits on your
11989     * view; it is just a hint to the system that this is not the primary
11990     * purpose of this view.
11991     *
11992     * @return Returns true if this view is a text editor, else false.
11993     */
11994    public boolean onCheckIsTextEditor() {
11995        return false;
11996    }
11997
11998    /**
11999     * Create a new InputConnection for an InputMethod to interact
12000     * with the view.  The default implementation returns null, since it doesn't
12001     * support input methods.  You can override this to implement such support.
12002     * This is only needed for views that take focus and text input.
12003     *
12004     * <p>When implementing this, you probably also want to implement
12005     * {@link #onCheckIsTextEditor()} to indicate you will return a
12006     * non-null InputConnection.</p>
12007     *
12008     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12009     * object correctly and in its entirety, so that the connected IME can rely
12010     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12011     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12012     * must be filled in with the correct cursor position for IMEs to work correctly
12013     * with your application.</p>
12014     *
12015     * @param outAttrs Fill in with attribute information about the connection.
12016     */
12017    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12018        return null;
12019    }
12020
12021    /**
12022     * Called by the {@link android.view.inputmethod.InputMethodManager}
12023     * when a view who is not the current
12024     * input connection target is trying to make a call on the manager.  The
12025     * default implementation returns false; you can override this to return
12026     * true for certain views if you are performing InputConnection proxying
12027     * to them.
12028     * @param view The View that is making the InputMethodManager call.
12029     * @return Return true to allow the call, false to reject.
12030     */
12031    public boolean checkInputConnectionProxy(View view) {
12032        return false;
12033    }
12034
12035    /**
12036     * Show the context menu for this view. It is not safe to hold on to the
12037     * menu after returning from this method.
12038     *
12039     * You should normally not overload this method. Overload
12040     * {@link #onCreateContextMenu(ContextMenu)} or define an
12041     * {@link OnCreateContextMenuListener} to add items to the context menu.
12042     *
12043     * @param menu The context menu to populate
12044     */
12045    public void createContextMenu(ContextMenu menu) {
12046        ContextMenuInfo menuInfo = getContextMenuInfo();
12047
12048        // Sets the current menu info so all items added to menu will have
12049        // my extra info set.
12050        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12051
12052        onCreateContextMenu(menu);
12053        ListenerInfo li = mListenerInfo;
12054        if (li != null && li.mOnCreateContextMenuListener != null) {
12055            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12056        }
12057
12058        // Clear the extra information so subsequent items that aren't mine don't
12059        // have my extra info.
12060        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12061
12062        if (mParent != null) {
12063            mParent.createContextMenu(menu);
12064        }
12065    }
12066
12067    /**
12068     * Views should implement this if they have extra information to associate
12069     * with the context menu. The return result is supplied as a parameter to
12070     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12071     * callback.
12072     *
12073     * @return Extra information about the item for which the context menu
12074     *         should be shown. This information will vary across different
12075     *         subclasses of View.
12076     */
12077    protected ContextMenuInfo getContextMenuInfo() {
12078        return null;
12079    }
12080
12081    /**
12082     * Views should implement this if the view itself is going to add items to
12083     * the context menu.
12084     *
12085     * @param menu the context menu to populate
12086     */
12087    protected void onCreateContextMenu(ContextMenu menu) {
12088    }
12089
12090    /**
12091     * Implement this method to handle trackball motion events.  The
12092     * <em>relative</em> movement of the trackball since the last event
12093     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12094     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12095     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12096     * they will often be fractional values, representing the more fine-grained
12097     * movement information available from a trackball).
12098     *
12099     * @param event The motion event.
12100     * @return True if the event was handled, false otherwise.
12101     */
12102    public boolean onTrackballEvent(MotionEvent event) {
12103        return false;
12104    }
12105
12106    /**
12107     * Implement this method to handle generic motion events.
12108     * <p>
12109     * Generic motion events describe joystick movements, mouse hovers, track pad
12110     * touches, scroll wheel movements and other input events.  The
12111     * {@link MotionEvent#getSource() source} of the motion event specifies
12112     * the class of input that was received.  Implementations of this method
12113     * must examine the bits in the source before processing the event.
12114     * The following code example shows how this is done.
12115     * </p><p>
12116     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12117     * are delivered to the view under the pointer.  All other generic motion events are
12118     * delivered to the focused view.
12119     * </p>
12120     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12121     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12122     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12123     *             // process the joystick movement...
12124     *             return true;
12125     *         }
12126     *     }
12127     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12128     *         switch (event.getAction()) {
12129     *             case MotionEvent.ACTION_HOVER_MOVE:
12130     *                 // process the mouse hover movement...
12131     *                 return true;
12132     *             case MotionEvent.ACTION_SCROLL:
12133     *                 // process the scroll wheel movement...
12134     *                 return true;
12135     *         }
12136     *     }
12137     *     return super.onGenericMotionEvent(event);
12138     * }</pre>
12139     *
12140     * @param event The generic motion event being processed.
12141     * @return True if the event was handled, false otherwise.
12142     */
12143    public boolean onGenericMotionEvent(MotionEvent event) {
12144        return false;
12145    }
12146
12147    /**
12148     * Implement this method to handle hover events.
12149     * <p>
12150     * This method is called whenever a pointer is hovering into, over, or out of the
12151     * bounds of a view and the view is not currently being touched.
12152     * Hover events are represented as pointer events with action
12153     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12154     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12155     * </p>
12156     * <ul>
12157     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12158     * when the pointer enters the bounds of the view.</li>
12159     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12160     * when the pointer has already entered the bounds of the view and has moved.</li>
12161     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12162     * when the pointer has exited the bounds of the view or when the pointer is
12163     * about to go down due to a button click, tap, or similar user action that
12164     * causes the view to be touched.</li>
12165     * </ul>
12166     * <p>
12167     * The view should implement this method to return true to indicate that it is
12168     * handling the hover event, such as by changing its drawable state.
12169     * </p><p>
12170     * The default implementation calls {@link #setHovered} to update the hovered state
12171     * of the view when a hover enter or hover exit event is received, if the view
12172     * is enabled and is clickable.  The default implementation also sends hover
12173     * accessibility events.
12174     * </p>
12175     *
12176     * @param event The motion event that describes the hover.
12177     * @return True if the view handled the hover event.
12178     *
12179     * @see #isHovered
12180     * @see #setHovered
12181     * @see #onHoverChanged
12182     */
12183    public boolean onHoverEvent(MotionEvent event) {
12184        // The root view may receive hover (or touch) events that are outside the bounds of
12185        // the window.  This code ensures that we only send accessibility events for
12186        // hovers that are actually within the bounds of the root view.
12187        final int action = event.getActionMasked();
12188        if (!mSendingHoverAccessibilityEvents) {
12189            if ((action == MotionEvent.ACTION_HOVER_ENTER
12190                    || action == MotionEvent.ACTION_HOVER_MOVE)
12191                    && !hasHoveredChild()
12192                    && pointInView(event.getX(), event.getY())) {
12193                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12194                mSendingHoverAccessibilityEvents = true;
12195            }
12196        } else {
12197            if (action == MotionEvent.ACTION_HOVER_EXIT
12198                    || (action == MotionEvent.ACTION_MOVE
12199                            && !pointInView(event.getX(), event.getY()))) {
12200                mSendingHoverAccessibilityEvents = false;
12201                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12202            }
12203        }
12204
12205        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12206                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12207                && isOnScrollbar(event.getX(), event.getY())) {
12208            awakenScrollBars();
12209        }
12210
12211        // If we consider ourself hoverable, or if we we're already hovered,
12212        // handle changing state in response to ENTER and EXIT events.
12213        if (isHoverable() || isHovered()) {
12214            switch (action) {
12215                case MotionEvent.ACTION_HOVER_ENTER:
12216                    setHovered(true);
12217                    break;
12218                case MotionEvent.ACTION_HOVER_EXIT:
12219                    setHovered(false);
12220                    break;
12221            }
12222
12223            // Dispatch the event to onGenericMotionEvent before returning true.
12224            // This is to provide compatibility with existing applications that
12225            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12226            // break because of the new default handling for hoverable views
12227            // in onHoverEvent.
12228            // Note that onGenericMotionEvent will be called by default when
12229            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12230            dispatchGenericMotionEventInternal(event);
12231            // The event was already handled by calling setHovered(), so always
12232            // return true.
12233            return true;
12234        }
12235
12236        return false;
12237    }
12238
12239    /**
12240     * Returns true if the view should handle {@link #onHoverEvent}
12241     * by calling {@link #setHovered} to change its hovered state.
12242     *
12243     * @return True if the view is hoverable.
12244     */
12245    private boolean isHoverable() {
12246        final int viewFlags = mViewFlags;
12247        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12248            return false;
12249        }
12250
12251        return (viewFlags & CLICKABLE) == CLICKABLE
12252                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12253                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12254    }
12255
12256    /**
12257     * Returns true if the view is currently hovered.
12258     *
12259     * @return True if the view is currently hovered.
12260     *
12261     * @see #setHovered
12262     * @see #onHoverChanged
12263     */
12264    @ViewDebug.ExportedProperty
12265    public boolean isHovered() {
12266        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12267    }
12268
12269    /**
12270     * Sets whether the view is currently hovered.
12271     * <p>
12272     * Calling this method also changes the drawable state of the view.  This
12273     * enables the view to react to hover by using different drawable resources
12274     * to change its appearance.
12275     * </p><p>
12276     * The {@link #onHoverChanged} method is called when the hovered state changes.
12277     * </p>
12278     *
12279     * @param hovered True if the view is hovered.
12280     *
12281     * @see #isHovered
12282     * @see #onHoverChanged
12283     */
12284    public void setHovered(boolean hovered) {
12285        if (hovered) {
12286            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12287                mPrivateFlags |= PFLAG_HOVERED;
12288                refreshDrawableState();
12289                onHoverChanged(true);
12290            }
12291        } else {
12292            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12293                mPrivateFlags &= ~PFLAG_HOVERED;
12294                refreshDrawableState();
12295                onHoverChanged(false);
12296            }
12297        }
12298    }
12299
12300    /**
12301     * Implement this method to handle hover state changes.
12302     * <p>
12303     * This method is called whenever the hover state changes as a result of a
12304     * call to {@link #setHovered}.
12305     * </p>
12306     *
12307     * @param hovered The current hover state, as returned by {@link #isHovered}.
12308     *
12309     * @see #isHovered
12310     * @see #setHovered
12311     */
12312    public void onHoverChanged(boolean hovered) {
12313    }
12314
12315    /**
12316     * Handles scroll bar dragging by mouse input.
12317     *
12318     * @hide
12319     * @param event The motion event.
12320     *
12321     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12322     */
12323    protected boolean handleScrollBarDragging(MotionEvent event) {
12324        if (mScrollCache == null) {
12325            return false;
12326        }
12327        final float x = event.getX();
12328        final float y = event.getY();
12329        final int action = event.getAction();
12330        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12331                && action != MotionEvent.ACTION_DOWN)
12332                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12333                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12334            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12335            return false;
12336        }
12337
12338        switch (action) {
12339            case MotionEvent.ACTION_MOVE:
12340                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12341                    return false;
12342                }
12343                if (mScrollCache.mScrollBarDraggingState
12344                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12345                    final Rect bounds = mScrollCache.mScrollBarBounds;
12346                    getVerticalScrollBarBounds(bounds, null);
12347                    final int range = computeVerticalScrollRange();
12348                    final int offset = computeVerticalScrollOffset();
12349                    final int extent = computeVerticalScrollExtent();
12350
12351                    final int thumbLength = ScrollBarUtils.getThumbLength(
12352                            bounds.height(), bounds.width(), extent, range);
12353                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12354                            bounds.height(), thumbLength, extent, range, offset);
12355
12356                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12357                    final float maxThumbOffset = bounds.height() - thumbLength;
12358                    final float newThumbOffset =
12359                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12360                    final int height = getHeight();
12361                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12362                            && height > 0 && extent > 0) {
12363                        final int newY = Math.round((range - extent)
12364                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12365                        if (newY != getScrollY()) {
12366                            mScrollCache.mScrollBarDraggingPos = y;
12367                            setScrollY(newY);
12368                        }
12369                    }
12370                    return true;
12371                }
12372                if (mScrollCache.mScrollBarDraggingState
12373                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12374                    final Rect bounds = mScrollCache.mScrollBarBounds;
12375                    getHorizontalScrollBarBounds(bounds, null);
12376                    final int range = computeHorizontalScrollRange();
12377                    final int offset = computeHorizontalScrollOffset();
12378                    final int extent = computeHorizontalScrollExtent();
12379
12380                    final int thumbLength = ScrollBarUtils.getThumbLength(
12381                            bounds.width(), bounds.height(), extent, range);
12382                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12383                            bounds.width(), thumbLength, extent, range, offset);
12384
12385                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12386                    final float maxThumbOffset = bounds.width() - thumbLength;
12387                    final float newThumbOffset =
12388                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12389                    final int width = getWidth();
12390                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12391                            && width > 0 && extent > 0) {
12392                        final int newX = Math.round((range - extent)
12393                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12394                        if (newX != getScrollX()) {
12395                            mScrollCache.mScrollBarDraggingPos = x;
12396                            setScrollX(newX);
12397                        }
12398                    }
12399                    return true;
12400                }
12401            case MotionEvent.ACTION_DOWN:
12402                if (mScrollCache.state == ScrollabilityCache.OFF) {
12403                    return false;
12404                }
12405                if (isOnVerticalScrollbarThumb(x, y)) {
12406                    mScrollCache.mScrollBarDraggingState =
12407                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12408                    mScrollCache.mScrollBarDraggingPos = y;
12409                    return true;
12410                }
12411                if (isOnHorizontalScrollbarThumb(x, y)) {
12412                    mScrollCache.mScrollBarDraggingState =
12413                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12414                    mScrollCache.mScrollBarDraggingPos = x;
12415                    return true;
12416                }
12417        }
12418        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12419        return false;
12420    }
12421
12422    /**
12423     * Implement this method to handle touch screen motion events.
12424     * <p>
12425     * If this method is used to detect click actions, it is recommended that
12426     * the actions be performed by implementing and calling
12427     * {@link #performClick()}. This will ensure consistent system behavior,
12428     * including:
12429     * <ul>
12430     * <li>obeying click sound preferences
12431     * <li>dispatching OnClickListener calls
12432     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12433     * accessibility features are enabled
12434     * </ul>
12435     *
12436     * @param event The motion event.
12437     * @return True if the event was handled, false otherwise.
12438     */
12439    public boolean onTouchEvent(MotionEvent event) {
12440        final float x = event.getX();
12441        final float y = event.getY();
12442        final int viewFlags = mViewFlags;
12443        final int action = event.getAction();
12444
12445        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12446                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12447                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12448
12449        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12450            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12451                setPressed(false);
12452            }
12453            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12454            // A disabled view that is clickable still consumes the touch
12455            // events, it just doesn't respond to them.
12456            return clickable;
12457        }
12458        if (mTouchDelegate != null) {
12459            if (mTouchDelegate.onTouchEvent(event)) {
12460                return true;
12461            }
12462        }
12463
12464        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12465            switch (action) {
12466                case MotionEvent.ACTION_UP:
12467                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12468                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12469                        handleTooltipUp();
12470                    }
12471                    if (!clickable) {
12472                        removeTapCallback();
12473                        removeLongPressCallback();
12474                        mInContextButtonPress = false;
12475                        mHasPerformedLongPress = false;
12476                        mIgnoreNextUpEvent = false;
12477                        break;
12478                    }
12479                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12480                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12481                        // take focus if we don't have it already and we should in
12482                        // touch mode.
12483                        boolean focusTaken = false;
12484                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12485                            focusTaken = requestFocus();
12486                        }
12487
12488                        if (prepressed) {
12489                            // The button is being released before we actually
12490                            // showed it as pressed.  Make it show the pressed
12491                            // state now (before scheduling the click) to ensure
12492                            // the user sees it.
12493                            setPressed(true, x, y);
12494                        }
12495
12496                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12497                            // This is a tap, so remove the longpress check
12498                            removeLongPressCallback();
12499
12500                            // Only perform take click actions if we were in the pressed state
12501                            if (!focusTaken) {
12502                                // Use a Runnable and post this rather than calling
12503                                // performClick directly. This lets other visual state
12504                                // of the view update before click actions start.
12505                                if (mPerformClick == null) {
12506                                    mPerformClick = new PerformClick();
12507                                }
12508                                if (!post(mPerformClick)) {
12509                                    performClick();
12510                                }
12511                            }
12512                        }
12513
12514                        if (mUnsetPressedState == null) {
12515                            mUnsetPressedState = new UnsetPressedState();
12516                        }
12517
12518                        if (prepressed) {
12519                            postDelayed(mUnsetPressedState,
12520                                    ViewConfiguration.getPressedStateDuration());
12521                        } else if (!post(mUnsetPressedState)) {
12522                            // If the post failed, unpress right now
12523                            mUnsetPressedState.run();
12524                        }
12525
12526                        removeTapCallback();
12527                    }
12528                    mIgnoreNextUpEvent = false;
12529                    break;
12530
12531                case MotionEvent.ACTION_DOWN:
12532                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12533                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12534                    }
12535                    mHasPerformedLongPress = false;
12536
12537                    if (!clickable) {
12538                        checkForLongClick(0, x, y);
12539                        break;
12540                    }
12541
12542                    if (performButtonActionOnTouchDown(event)) {
12543                        break;
12544                    }
12545
12546                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12547                    boolean isInScrollingContainer = isInScrollingContainer();
12548
12549                    // For views inside a scrolling container, delay the pressed feedback for
12550                    // a short period in case this is a scroll.
12551                    if (isInScrollingContainer) {
12552                        mPrivateFlags |= PFLAG_PREPRESSED;
12553                        if (mPendingCheckForTap == null) {
12554                            mPendingCheckForTap = new CheckForTap();
12555                        }
12556                        mPendingCheckForTap.x = event.getX();
12557                        mPendingCheckForTap.y = event.getY();
12558                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12559                    } else {
12560                        // Not inside a scrolling container, so show the feedback right away
12561                        setPressed(true, x, y);
12562                        checkForLongClick(0, x, y);
12563                    }
12564                    break;
12565
12566                case MotionEvent.ACTION_CANCEL:
12567                    if (clickable) {
12568                        setPressed(false);
12569                    }
12570                    removeTapCallback();
12571                    removeLongPressCallback();
12572                    mInContextButtonPress = false;
12573                    mHasPerformedLongPress = false;
12574                    mIgnoreNextUpEvent = false;
12575                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12576                    break;
12577
12578                case MotionEvent.ACTION_MOVE:
12579                    if (clickable) {
12580                        drawableHotspotChanged(x, y);
12581                    }
12582
12583                    // Be lenient about moving outside of buttons
12584                    if (!pointInView(x, y, mTouchSlop)) {
12585                        // Outside button
12586                        // Remove any future long press/tap checks
12587                        removeTapCallback();
12588                        removeLongPressCallback();
12589                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12590                            setPressed(false);
12591                        }
12592                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12593                    }
12594                    break;
12595            }
12596
12597            return true;
12598        }
12599
12600        return false;
12601    }
12602
12603    /**
12604     * @hide
12605     */
12606    public boolean isInScrollingContainer() {
12607        ViewParent p = getParent();
12608        while (p != null && p instanceof ViewGroup) {
12609            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12610                return true;
12611            }
12612            p = p.getParent();
12613        }
12614        return false;
12615    }
12616
12617    /**
12618     * Remove the longpress detection timer.
12619     */
12620    private void removeLongPressCallback() {
12621        if (mPendingCheckForLongPress != null) {
12622            removeCallbacks(mPendingCheckForLongPress);
12623        }
12624    }
12625
12626    /**
12627     * Remove the pending click action
12628     */
12629    private void removePerformClickCallback() {
12630        if (mPerformClick != null) {
12631            removeCallbacks(mPerformClick);
12632        }
12633    }
12634
12635    /**
12636     * Remove the prepress detection timer.
12637     */
12638    private void removeUnsetPressCallback() {
12639        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12640            setPressed(false);
12641            removeCallbacks(mUnsetPressedState);
12642        }
12643    }
12644
12645    /**
12646     * Remove the tap detection timer.
12647     */
12648    private void removeTapCallback() {
12649        if (mPendingCheckForTap != null) {
12650            mPrivateFlags &= ~PFLAG_PREPRESSED;
12651            removeCallbacks(mPendingCheckForTap);
12652        }
12653    }
12654
12655    /**
12656     * Cancels a pending long press.  Your subclass can use this if you
12657     * want the context menu to come up if the user presses and holds
12658     * at the same place, but you don't want it to come up if they press
12659     * and then move around enough to cause scrolling.
12660     */
12661    public void cancelLongPress() {
12662        removeLongPressCallback();
12663
12664        /*
12665         * The prepressed state handled by the tap callback is a display
12666         * construct, but the tap callback will post a long press callback
12667         * less its own timeout. Remove it here.
12668         */
12669        removeTapCallback();
12670    }
12671
12672    /**
12673     * Remove the pending callback for sending a
12674     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12675     */
12676    private void removeSendViewScrolledAccessibilityEventCallback() {
12677        if (mSendViewScrolledAccessibilityEvent != null) {
12678            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12679            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12680        }
12681    }
12682
12683    /**
12684     * Sets the TouchDelegate for this View.
12685     */
12686    public void setTouchDelegate(TouchDelegate delegate) {
12687        mTouchDelegate = delegate;
12688    }
12689
12690    /**
12691     * Gets the TouchDelegate for this View.
12692     */
12693    public TouchDelegate getTouchDelegate() {
12694        return mTouchDelegate;
12695    }
12696
12697    /**
12698     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12699     *
12700     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12701     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12702     * available. This method should only be called for touch events.
12703     *
12704     * <p class="note">This api is not intended for most applications. Buffered dispatch
12705     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12706     * streams will not improve your input latency. Side effects include: increased latency,
12707     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12708     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12709     * you.</p>
12710     */
12711    public final void requestUnbufferedDispatch(MotionEvent event) {
12712        final int action = event.getAction();
12713        if (mAttachInfo == null
12714                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12715                || !event.isTouchEvent()) {
12716            return;
12717        }
12718        mAttachInfo.mUnbufferedDispatchRequested = true;
12719    }
12720
12721    /**
12722     * Set flags controlling behavior of this view.
12723     *
12724     * @param flags Constant indicating the value which should be set
12725     * @param mask Constant indicating the bit range that should be changed
12726     */
12727    void setFlags(int flags, int mask) {
12728        final boolean accessibilityEnabled =
12729                AccessibilityManager.getInstance(mContext).isEnabled();
12730        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12731
12732        int old = mViewFlags;
12733        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12734
12735        int changed = mViewFlags ^ old;
12736        if (changed == 0) {
12737            return;
12738        }
12739        int privateFlags = mPrivateFlags;
12740
12741        // If focusable is auto, update the FOCUSABLE bit.
12742        int focusableChangedByAuto = 0;
12743        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12744                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12745            // Heuristic only takes into account whether view is clickable.
12746            final int newFocus;
12747            if ((mViewFlags & CLICKABLE) != 0) {
12748                newFocus = FOCUSABLE;
12749            } else {
12750                newFocus = NOT_FOCUSABLE;
12751            }
12752            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12753            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12754            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12755        }
12756
12757        /* Check if the FOCUSABLE bit has changed */
12758        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12759            if (((old & FOCUSABLE) == FOCUSABLE)
12760                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12761                /* Give up focus if we are no longer focusable */
12762                clearFocus();
12763            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12764                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12765                /*
12766                 * Tell the view system that we are now available to take focus
12767                 * if no one else already has it.
12768                 */
12769                if (mParent != null) {
12770                    ViewRootImpl viewRootImpl = getViewRootImpl();
12771                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12772                            || focusableChangedByAuto == 0
12773                            || viewRootImpl == null
12774                            || viewRootImpl.mThread == Thread.currentThread()) {
12775                        mParent.focusableViewAvailable(this);
12776                    }
12777                }
12778            }
12779        }
12780
12781        final int newVisibility = flags & VISIBILITY_MASK;
12782        if (newVisibility == VISIBLE) {
12783            if ((changed & VISIBILITY_MASK) != 0) {
12784                /*
12785                 * If this view is becoming visible, invalidate it in case it changed while
12786                 * it was not visible. Marking it drawn ensures that the invalidation will
12787                 * go through.
12788                 */
12789                mPrivateFlags |= PFLAG_DRAWN;
12790                invalidate(true);
12791
12792                needGlobalAttributesUpdate(true);
12793
12794                // a view becoming visible is worth notifying the parent
12795                // about in case nothing has focus.  even if this specific view
12796                // isn't focusable, it may contain something that is, so let
12797                // the root view try to give this focus if nothing else does.
12798                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12799                    mParent.focusableViewAvailable(this);
12800                }
12801            }
12802        }
12803
12804        /* Check if the GONE bit has changed */
12805        if ((changed & GONE) != 0) {
12806            needGlobalAttributesUpdate(false);
12807            requestLayout();
12808
12809            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12810                if (hasFocus()) clearFocus();
12811                clearAccessibilityFocus();
12812                destroyDrawingCache();
12813                if (mParent instanceof View) {
12814                    // GONE views noop invalidation, so invalidate the parent
12815                    ((View) mParent).invalidate(true);
12816                }
12817                // Mark the view drawn to ensure that it gets invalidated properly the next
12818                // time it is visible and gets invalidated
12819                mPrivateFlags |= PFLAG_DRAWN;
12820            }
12821            if (mAttachInfo != null) {
12822                mAttachInfo.mViewVisibilityChanged = true;
12823            }
12824        }
12825
12826        /* Check if the VISIBLE bit has changed */
12827        if ((changed & INVISIBLE) != 0) {
12828            needGlobalAttributesUpdate(false);
12829            /*
12830             * If this view is becoming invisible, set the DRAWN flag so that
12831             * the next invalidate() will not be skipped.
12832             */
12833            mPrivateFlags |= PFLAG_DRAWN;
12834
12835            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12836                // root view becoming invisible shouldn't clear focus and accessibility focus
12837                if (getRootView() != this) {
12838                    if (hasFocus()) clearFocus();
12839                    clearAccessibilityFocus();
12840                }
12841            }
12842            if (mAttachInfo != null) {
12843                mAttachInfo.mViewVisibilityChanged = true;
12844            }
12845        }
12846
12847        if ((changed & VISIBILITY_MASK) != 0) {
12848            // If the view is invisible, cleanup its display list to free up resources
12849            if (newVisibility != VISIBLE && mAttachInfo != null) {
12850                cleanupDraw();
12851            }
12852
12853            if (mParent instanceof ViewGroup) {
12854                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12855                        (changed & VISIBILITY_MASK), newVisibility);
12856                ((View) mParent).invalidate(true);
12857            } else if (mParent != null) {
12858                mParent.invalidateChild(this, null);
12859            }
12860
12861            if (mAttachInfo != null) {
12862                dispatchVisibilityChanged(this, newVisibility);
12863
12864                // Aggregated visibility changes are dispatched to attached views
12865                // in visible windows where the parent is currently shown/drawn
12866                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12867                // discounting clipping or overlapping. This makes it a good place
12868                // to change animation states.
12869                if (mParent != null && getWindowVisibility() == VISIBLE &&
12870                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12871                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12872                }
12873                notifySubtreeAccessibilityStateChangedIfNeeded();
12874            }
12875        }
12876
12877        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12878            destroyDrawingCache();
12879        }
12880
12881        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12882            destroyDrawingCache();
12883            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12884            invalidateParentCaches();
12885        }
12886
12887        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12888            destroyDrawingCache();
12889            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12890        }
12891
12892        if ((changed & DRAW_MASK) != 0) {
12893            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12894                if (mBackground != null
12895                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12896                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12897                } else {
12898                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12899                }
12900            } else {
12901                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12902            }
12903            requestLayout();
12904            invalidate(true);
12905        }
12906
12907        if ((changed & KEEP_SCREEN_ON) != 0) {
12908            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12909                mParent.recomputeViewAttributes(this);
12910            }
12911        }
12912
12913        if (accessibilityEnabled) {
12914            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
12915                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
12916                    || (changed & CONTEXT_CLICKABLE) != 0) {
12917                if (oldIncludeForAccessibility != includeForAccessibility()) {
12918                    notifySubtreeAccessibilityStateChangedIfNeeded();
12919                } else {
12920                    notifyViewAccessibilityStateChangedIfNeeded(
12921                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12922                }
12923            } else if ((changed & ENABLED_MASK) != 0) {
12924                notifyViewAccessibilityStateChangedIfNeeded(
12925                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12926            }
12927        }
12928    }
12929
12930    /**
12931     * Change the view's z order in the tree, so it's on top of other sibling
12932     * views. This ordering change may affect layout, if the parent container
12933     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
12934     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
12935     * method should be followed by calls to {@link #requestLayout()} and
12936     * {@link View#invalidate()} on the view's parent to force the parent to redraw
12937     * with the new child ordering.
12938     *
12939     * @see ViewGroup#bringChildToFront(View)
12940     */
12941    public void bringToFront() {
12942        if (mParent != null) {
12943            mParent.bringChildToFront(this);
12944        }
12945    }
12946
12947    /**
12948     * This is called in response to an internal scroll in this view (i.e., the
12949     * view scrolled its own contents). This is typically as a result of
12950     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
12951     * called.
12952     *
12953     * @param l Current horizontal scroll origin.
12954     * @param t Current vertical scroll origin.
12955     * @param oldl Previous horizontal scroll origin.
12956     * @param oldt Previous vertical scroll origin.
12957     */
12958    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
12959        notifySubtreeAccessibilityStateChangedIfNeeded();
12960
12961        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12962            postSendViewScrolledAccessibilityEventCallback();
12963        }
12964
12965        mBackgroundSizeChanged = true;
12966        if (mForegroundInfo != null) {
12967            mForegroundInfo.mBoundsChanged = true;
12968        }
12969
12970        final AttachInfo ai = mAttachInfo;
12971        if (ai != null) {
12972            ai.mViewScrollChanged = true;
12973        }
12974
12975        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
12976            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
12977        }
12978    }
12979
12980    /**
12981     * Interface definition for a callback to be invoked when the scroll
12982     * X or Y positions of a view change.
12983     * <p>
12984     * <b>Note:</b> Some views handle scrolling independently from View and may
12985     * have their own separate listeners for scroll-type events. For example,
12986     * {@link android.widget.ListView ListView} allows clients to register an
12987     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
12988     * to listen for changes in list scroll position.
12989     *
12990     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
12991     */
12992    public interface OnScrollChangeListener {
12993        /**
12994         * Called when the scroll position of a view changes.
12995         *
12996         * @param v The view whose scroll position has changed.
12997         * @param scrollX Current horizontal scroll origin.
12998         * @param scrollY Current vertical scroll origin.
12999         * @param oldScrollX Previous horizontal scroll origin.
13000         * @param oldScrollY Previous vertical scroll origin.
13001         */
13002        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13003    }
13004
13005    /**
13006     * Interface definition for a callback to be invoked when the layout bounds of a view
13007     * changes due to layout processing.
13008     */
13009    public interface OnLayoutChangeListener {
13010        /**
13011         * Called when the layout bounds of a view changes due to layout processing.
13012         *
13013         * @param v The view whose bounds have changed.
13014         * @param left The new value of the view's left property.
13015         * @param top The new value of the view's top property.
13016         * @param right The new value of the view's right property.
13017         * @param bottom The new value of the view's bottom property.
13018         * @param oldLeft The previous value of the view's left property.
13019         * @param oldTop The previous value of the view's top property.
13020         * @param oldRight The previous value of the view's right property.
13021         * @param oldBottom The previous value of the view's bottom property.
13022         */
13023        void onLayoutChange(View v, int left, int top, int right, int bottom,
13024            int oldLeft, int oldTop, int oldRight, int oldBottom);
13025    }
13026
13027    /**
13028     * This is called during layout when the size of this view has changed. If
13029     * you were just added to the view hierarchy, you're called with the old
13030     * values of 0.
13031     *
13032     * @param w Current width of this view.
13033     * @param h Current height of this view.
13034     * @param oldw Old width of this view.
13035     * @param oldh Old height of this view.
13036     */
13037    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13038    }
13039
13040    /**
13041     * Called by draw to draw the child views. This may be overridden
13042     * by derived classes to gain control just before its children are drawn
13043     * (but after its own view has been drawn).
13044     * @param canvas the canvas on which to draw the view
13045     */
13046    protected void dispatchDraw(Canvas canvas) {
13047
13048    }
13049
13050    /**
13051     * Gets the parent of this view. Note that the parent is a
13052     * ViewParent and not necessarily a View.
13053     *
13054     * @return Parent of this view.
13055     */
13056    public final ViewParent getParent() {
13057        return mParent;
13058    }
13059
13060    /**
13061     * Set the horizontal scrolled position of your view. This will cause a call to
13062     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13063     * invalidated.
13064     * @param value the x position to scroll to
13065     */
13066    public void setScrollX(int value) {
13067        scrollTo(value, mScrollY);
13068    }
13069
13070    /**
13071     * Set the vertical scrolled position of your view. This will cause a call to
13072     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13073     * invalidated.
13074     * @param value the y position to scroll to
13075     */
13076    public void setScrollY(int value) {
13077        scrollTo(mScrollX, value);
13078    }
13079
13080    /**
13081     * Return the scrolled left position of this view. This is the left edge of
13082     * the displayed part of your view. You do not need to draw any pixels
13083     * farther left, since those are outside of the frame of your view on
13084     * screen.
13085     *
13086     * @return The left edge of the displayed part of your view, in pixels.
13087     */
13088    public final int getScrollX() {
13089        return mScrollX;
13090    }
13091
13092    /**
13093     * Return the scrolled top position of this view. This is the top edge of
13094     * the displayed part of your view. You do not need to draw any pixels above
13095     * it, since those are outside of the frame of your view on screen.
13096     *
13097     * @return The top edge of the displayed part of your view, in pixels.
13098     */
13099    public final int getScrollY() {
13100        return mScrollY;
13101    }
13102
13103    /**
13104     * Return the width of the your view.
13105     *
13106     * @return The width of your view, in pixels.
13107     */
13108    @ViewDebug.ExportedProperty(category = "layout")
13109    public final int getWidth() {
13110        return mRight - mLeft;
13111    }
13112
13113    /**
13114     * Return the height of your view.
13115     *
13116     * @return The height of your view, in pixels.
13117     */
13118    @ViewDebug.ExportedProperty(category = "layout")
13119    public final int getHeight() {
13120        return mBottom - mTop;
13121    }
13122
13123    /**
13124     * Return the visible drawing bounds of your view. Fills in the output
13125     * rectangle with the values from getScrollX(), getScrollY(),
13126     * getWidth(), and getHeight(). These bounds do not account for any
13127     * transformation properties currently set on the view, such as
13128     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13129     *
13130     * @param outRect The (scrolled) drawing bounds of the view.
13131     */
13132    public void getDrawingRect(Rect outRect) {
13133        outRect.left = mScrollX;
13134        outRect.top = mScrollY;
13135        outRect.right = mScrollX + (mRight - mLeft);
13136        outRect.bottom = mScrollY + (mBottom - mTop);
13137    }
13138
13139    /**
13140     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13141     * raw width component (that is the result is masked by
13142     * {@link #MEASURED_SIZE_MASK}).
13143     *
13144     * @return The raw measured width of this view.
13145     */
13146    public final int getMeasuredWidth() {
13147        return mMeasuredWidth & MEASURED_SIZE_MASK;
13148    }
13149
13150    /**
13151     * Return the full width measurement information for this view as computed
13152     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13153     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13154     * This should be used during measurement and layout calculations only. Use
13155     * {@link #getWidth()} to see how wide a view is after layout.
13156     *
13157     * @return The measured width of this view as a bit mask.
13158     */
13159    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13160            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13161                    name = "MEASURED_STATE_TOO_SMALL"),
13162    })
13163    public final int getMeasuredWidthAndState() {
13164        return mMeasuredWidth;
13165    }
13166
13167    /**
13168     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13169     * raw height component (that is the result is masked by
13170     * {@link #MEASURED_SIZE_MASK}).
13171     *
13172     * @return The raw measured height of this view.
13173     */
13174    public final int getMeasuredHeight() {
13175        return mMeasuredHeight & MEASURED_SIZE_MASK;
13176    }
13177
13178    /**
13179     * Return the full height measurement information for this view as computed
13180     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13181     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13182     * This should be used during measurement and layout calculations only. Use
13183     * {@link #getHeight()} to see how wide a view is after layout.
13184     *
13185     * @return The measured height of this view as a bit mask.
13186     */
13187    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13188            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13189                    name = "MEASURED_STATE_TOO_SMALL"),
13190    })
13191    public final int getMeasuredHeightAndState() {
13192        return mMeasuredHeight;
13193    }
13194
13195    /**
13196     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13197     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13198     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13199     * and the height component is at the shifted bits
13200     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13201     */
13202    public final int getMeasuredState() {
13203        return (mMeasuredWidth&MEASURED_STATE_MASK)
13204                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13205                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13206    }
13207
13208    /**
13209     * The transform matrix of this view, which is calculated based on the current
13210     * rotation, scale, and pivot properties.
13211     *
13212     * @see #getRotation()
13213     * @see #getScaleX()
13214     * @see #getScaleY()
13215     * @see #getPivotX()
13216     * @see #getPivotY()
13217     * @return The current transform matrix for the view
13218     */
13219    public Matrix getMatrix() {
13220        ensureTransformationInfo();
13221        final Matrix matrix = mTransformationInfo.mMatrix;
13222        mRenderNode.getMatrix(matrix);
13223        return matrix;
13224    }
13225
13226    /**
13227     * Returns true if the transform matrix is the identity matrix.
13228     * Recomputes the matrix if necessary.
13229     *
13230     * @return True if the transform matrix is the identity matrix, false otherwise.
13231     */
13232    final boolean hasIdentityMatrix() {
13233        return mRenderNode.hasIdentityMatrix();
13234    }
13235
13236    void ensureTransformationInfo() {
13237        if (mTransformationInfo == null) {
13238            mTransformationInfo = new TransformationInfo();
13239        }
13240    }
13241
13242    /**
13243     * Utility method to retrieve the inverse of the current mMatrix property.
13244     * We cache the matrix to avoid recalculating it when transform properties
13245     * have not changed.
13246     *
13247     * @return The inverse of the current matrix of this view.
13248     * @hide
13249     */
13250    public final Matrix getInverseMatrix() {
13251        ensureTransformationInfo();
13252        if (mTransformationInfo.mInverseMatrix == null) {
13253            mTransformationInfo.mInverseMatrix = new Matrix();
13254        }
13255        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13256        mRenderNode.getInverseMatrix(matrix);
13257        return matrix;
13258    }
13259
13260    /**
13261     * Gets the distance along the Z axis from the camera to this view.
13262     *
13263     * @see #setCameraDistance(float)
13264     *
13265     * @return The distance along the Z axis.
13266     */
13267    public float getCameraDistance() {
13268        final float dpi = mResources.getDisplayMetrics().densityDpi;
13269        return -(mRenderNode.getCameraDistance() * dpi);
13270    }
13271
13272    /**
13273     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13274     * views are drawn) from the camera to this view. The camera's distance
13275     * affects 3D transformations, for instance rotations around the X and Y
13276     * axis. If the rotationX or rotationY properties are changed and this view is
13277     * large (more than half the size of the screen), it is recommended to always
13278     * use a camera distance that's greater than the height (X axis rotation) or
13279     * the width (Y axis rotation) of this view.</p>
13280     *
13281     * <p>The distance of the camera from the view plane can have an affect on the
13282     * perspective distortion of the view when it is rotated around the x or y axis.
13283     * For example, a large distance will result in a large viewing angle, and there
13284     * will not be much perspective distortion of the view as it rotates. A short
13285     * distance may cause much more perspective distortion upon rotation, and can
13286     * also result in some drawing artifacts if the rotated view ends up partially
13287     * behind the camera (which is why the recommendation is to use a distance at
13288     * least as far as the size of the view, if the view is to be rotated.)</p>
13289     *
13290     * <p>The distance is expressed in "depth pixels." The default distance depends
13291     * on the screen density. For instance, on a medium density display, the
13292     * default distance is 1280. On a high density display, the default distance
13293     * is 1920.</p>
13294     *
13295     * <p>If you want to specify a distance that leads to visually consistent
13296     * results across various densities, use the following formula:</p>
13297     * <pre>
13298     * float scale = context.getResources().getDisplayMetrics().density;
13299     * view.setCameraDistance(distance * scale);
13300     * </pre>
13301     *
13302     * <p>The density scale factor of a high density display is 1.5,
13303     * and 1920 = 1280 * 1.5.</p>
13304     *
13305     * @param distance The distance in "depth pixels", if negative the opposite
13306     *        value is used
13307     *
13308     * @see #setRotationX(float)
13309     * @see #setRotationY(float)
13310     */
13311    public void setCameraDistance(float distance) {
13312        final float dpi = mResources.getDisplayMetrics().densityDpi;
13313
13314        invalidateViewProperty(true, false);
13315        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13316        invalidateViewProperty(false, false);
13317
13318        invalidateParentIfNeededAndWasQuickRejected();
13319    }
13320
13321    /**
13322     * The degrees that the view is rotated around the pivot point.
13323     *
13324     * @see #setRotation(float)
13325     * @see #getPivotX()
13326     * @see #getPivotY()
13327     *
13328     * @return The degrees of rotation.
13329     */
13330    @ViewDebug.ExportedProperty(category = "drawing")
13331    public float getRotation() {
13332        return mRenderNode.getRotation();
13333    }
13334
13335    /**
13336     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13337     * result in clockwise rotation.
13338     *
13339     * @param rotation The degrees of rotation.
13340     *
13341     * @see #getRotation()
13342     * @see #getPivotX()
13343     * @see #getPivotY()
13344     * @see #setRotationX(float)
13345     * @see #setRotationY(float)
13346     *
13347     * @attr ref android.R.styleable#View_rotation
13348     */
13349    public void setRotation(float rotation) {
13350        if (rotation != getRotation()) {
13351            // Double-invalidation is necessary to capture view's old and new areas
13352            invalidateViewProperty(true, false);
13353            mRenderNode.setRotation(rotation);
13354            invalidateViewProperty(false, true);
13355
13356            invalidateParentIfNeededAndWasQuickRejected();
13357            notifySubtreeAccessibilityStateChangedIfNeeded();
13358        }
13359    }
13360
13361    /**
13362     * The degrees that the view is rotated around the vertical axis through the pivot point.
13363     *
13364     * @see #getPivotX()
13365     * @see #getPivotY()
13366     * @see #setRotationY(float)
13367     *
13368     * @return The degrees of Y rotation.
13369     */
13370    @ViewDebug.ExportedProperty(category = "drawing")
13371    public float getRotationY() {
13372        return mRenderNode.getRotationY();
13373    }
13374
13375    /**
13376     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13377     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13378     * down the y axis.
13379     *
13380     * When rotating large views, it is recommended to adjust the camera distance
13381     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13382     *
13383     * @param rotationY The degrees of Y rotation.
13384     *
13385     * @see #getRotationY()
13386     * @see #getPivotX()
13387     * @see #getPivotY()
13388     * @see #setRotation(float)
13389     * @see #setRotationX(float)
13390     * @see #setCameraDistance(float)
13391     *
13392     * @attr ref android.R.styleable#View_rotationY
13393     */
13394    public void setRotationY(float rotationY) {
13395        if (rotationY != getRotationY()) {
13396            invalidateViewProperty(true, false);
13397            mRenderNode.setRotationY(rotationY);
13398            invalidateViewProperty(false, true);
13399
13400            invalidateParentIfNeededAndWasQuickRejected();
13401            notifySubtreeAccessibilityStateChangedIfNeeded();
13402        }
13403    }
13404
13405    /**
13406     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13407     *
13408     * @see #getPivotX()
13409     * @see #getPivotY()
13410     * @see #setRotationX(float)
13411     *
13412     * @return The degrees of X rotation.
13413     */
13414    @ViewDebug.ExportedProperty(category = "drawing")
13415    public float getRotationX() {
13416        return mRenderNode.getRotationX();
13417    }
13418
13419    /**
13420     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13421     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13422     * x axis.
13423     *
13424     * When rotating large views, it is recommended to adjust the camera distance
13425     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13426     *
13427     * @param rotationX The degrees of X rotation.
13428     *
13429     * @see #getRotationX()
13430     * @see #getPivotX()
13431     * @see #getPivotY()
13432     * @see #setRotation(float)
13433     * @see #setRotationY(float)
13434     * @see #setCameraDistance(float)
13435     *
13436     * @attr ref android.R.styleable#View_rotationX
13437     */
13438    public void setRotationX(float rotationX) {
13439        if (rotationX != getRotationX()) {
13440            invalidateViewProperty(true, false);
13441            mRenderNode.setRotationX(rotationX);
13442            invalidateViewProperty(false, true);
13443
13444            invalidateParentIfNeededAndWasQuickRejected();
13445            notifySubtreeAccessibilityStateChangedIfNeeded();
13446        }
13447    }
13448
13449    /**
13450     * The amount that the view is scaled in x around the pivot point, as a proportion of
13451     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13452     *
13453     * <p>By default, this is 1.0f.
13454     *
13455     * @see #getPivotX()
13456     * @see #getPivotY()
13457     * @return The scaling factor.
13458     */
13459    @ViewDebug.ExportedProperty(category = "drawing")
13460    public float getScaleX() {
13461        return mRenderNode.getScaleX();
13462    }
13463
13464    /**
13465     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13466     * the view's unscaled width. A value of 1 means that no scaling is applied.
13467     *
13468     * @param scaleX The scaling factor.
13469     * @see #getPivotX()
13470     * @see #getPivotY()
13471     *
13472     * @attr ref android.R.styleable#View_scaleX
13473     */
13474    public void setScaleX(float scaleX) {
13475        if (scaleX != getScaleX()) {
13476            invalidateViewProperty(true, false);
13477            mRenderNode.setScaleX(scaleX);
13478            invalidateViewProperty(false, true);
13479
13480            invalidateParentIfNeededAndWasQuickRejected();
13481            notifySubtreeAccessibilityStateChangedIfNeeded();
13482        }
13483    }
13484
13485    /**
13486     * The amount that the view is scaled in y around the pivot point, as a proportion of
13487     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13488     *
13489     * <p>By default, this is 1.0f.
13490     *
13491     * @see #getPivotX()
13492     * @see #getPivotY()
13493     * @return The scaling factor.
13494     */
13495    @ViewDebug.ExportedProperty(category = "drawing")
13496    public float getScaleY() {
13497        return mRenderNode.getScaleY();
13498    }
13499
13500    /**
13501     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13502     * the view's unscaled width. A value of 1 means that no scaling is applied.
13503     *
13504     * @param scaleY The scaling factor.
13505     * @see #getPivotX()
13506     * @see #getPivotY()
13507     *
13508     * @attr ref android.R.styleable#View_scaleY
13509     */
13510    public void setScaleY(float scaleY) {
13511        if (scaleY != getScaleY()) {
13512            invalidateViewProperty(true, false);
13513            mRenderNode.setScaleY(scaleY);
13514            invalidateViewProperty(false, true);
13515
13516            invalidateParentIfNeededAndWasQuickRejected();
13517            notifySubtreeAccessibilityStateChangedIfNeeded();
13518        }
13519    }
13520
13521    /**
13522     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13523     * and {@link #setScaleX(float) scaled}.
13524     *
13525     * @see #getRotation()
13526     * @see #getScaleX()
13527     * @see #getScaleY()
13528     * @see #getPivotY()
13529     * @return The x location of the pivot point.
13530     *
13531     * @attr ref android.R.styleable#View_transformPivotX
13532     */
13533    @ViewDebug.ExportedProperty(category = "drawing")
13534    public float getPivotX() {
13535        return mRenderNode.getPivotX();
13536    }
13537
13538    /**
13539     * Sets the x location of the point around which the view is
13540     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13541     * By default, the pivot point is centered on the object.
13542     * Setting this property disables this behavior and causes the view to use only the
13543     * explicitly set pivotX and pivotY values.
13544     *
13545     * @param pivotX The x location of the pivot point.
13546     * @see #getRotation()
13547     * @see #getScaleX()
13548     * @see #getScaleY()
13549     * @see #getPivotY()
13550     *
13551     * @attr ref android.R.styleable#View_transformPivotX
13552     */
13553    public void setPivotX(float pivotX) {
13554        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13555            invalidateViewProperty(true, false);
13556            mRenderNode.setPivotX(pivotX);
13557            invalidateViewProperty(false, true);
13558
13559            invalidateParentIfNeededAndWasQuickRejected();
13560        }
13561    }
13562
13563    /**
13564     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13565     * and {@link #setScaleY(float) scaled}.
13566     *
13567     * @see #getRotation()
13568     * @see #getScaleX()
13569     * @see #getScaleY()
13570     * @see #getPivotY()
13571     * @return The y location of the pivot point.
13572     *
13573     * @attr ref android.R.styleable#View_transformPivotY
13574     */
13575    @ViewDebug.ExportedProperty(category = "drawing")
13576    public float getPivotY() {
13577        return mRenderNode.getPivotY();
13578    }
13579
13580    /**
13581     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13582     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13583     * Setting this property disables this behavior and causes the view to use only the
13584     * explicitly set pivotX and pivotY values.
13585     *
13586     * @param pivotY The y location of the pivot point.
13587     * @see #getRotation()
13588     * @see #getScaleX()
13589     * @see #getScaleY()
13590     * @see #getPivotY()
13591     *
13592     * @attr ref android.R.styleable#View_transformPivotY
13593     */
13594    public void setPivotY(float pivotY) {
13595        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13596            invalidateViewProperty(true, false);
13597            mRenderNode.setPivotY(pivotY);
13598            invalidateViewProperty(false, true);
13599
13600            invalidateParentIfNeededAndWasQuickRejected();
13601        }
13602    }
13603
13604    /**
13605     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13606     * completely transparent and 1 means the view is completely opaque.
13607     *
13608     * <p>By default this is 1.0f.
13609     * @return The opacity of the view.
13610     */
13611    @ViewDebug.ExportedProperty(category = "drawing")
13612    public float getAlpha() {
13613        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13614    }
13615
13616    /**
13617     * Sets the behavior for overlapping rendering for this view (see {@link
13618     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13619     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13620     * providing the value which is then used internally. That is, when {@link
13621     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13622     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13623     * instead.
13624     *
13625     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13626     * instead of that returned by {@link #hasOverlappingRendering()}.
13627     *
13628     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13629     */
13630    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13631        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13632        if (hasOverlappingRendering) {
13633            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13634        } else {
13635            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13636        }
13637    }
13638
13639    /**
13640     * Returns the value for overlapping rendering that is used internally. This is either
13641     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13642     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13643     *
13644     * @return The value for overlapping rendering being used internally.
13645     */
13646    public final boolean getHasOverlappingRendering() {
13647        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13648                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13649                hasOverlappingRendering();
13650    }
13651
13652    /**
13653     * Returns whether this View has content which overlaps.
13654     *
13655     * <p>This function, intended to be overridden by specific View types, is an optimization when
13656     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13657     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13658     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13659     * directly. An example of overlapping rendering is a TextView with a background image, such as
13660     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13661     * ImageView with only the foreground image. The default implementation returns true; subclasses
13662     * should override if they have cases which can be optimized.</p>
13663     *
13664     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13665     * necessitates that a View return true if it uses the methods internally without passing the
13666     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13667     *
13668     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13669     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13670     *
13671     * @return true if the content in this view might overlap, false otherwise.
13672     */
13673    @ViewDebug.ExportedProperty(category = "drawing")
13674    public boolean hasOverlappingRendering() {
13675        return true;
13676    }
13677
13678    /**
13679     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13680     * completely transparent and 1 means the view is completely opaque.
13681     *
13682     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13683     * can have significant performance implications, especially for large views. It is best to use
13684     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13685     *
13686     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13687     * strongly recommended for performance reasons to either override
13688     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13689     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13690     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13691     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13692     * of rendering cost, even for simple or small views. Starting with
13693     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13694     * applied to the view at the rendering level.</p>
13695     *
13696     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13697     * responsible for applying the opacity itself.</p>
13698     *
13699     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13700     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13701     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13702     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13703     *
13704     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13705     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13706     * {@link #hasOverlappingRendering}.</p>
13707     *
13708     * @param alpha The opacity of the view.
13709     *
13710     * @see #hasOverlappingRendering()
13711     * @see #setLayerType(int, android.graphics.Paint)
13712     *
13713     * @attr ref android.R.styleable#View_alpha
13714     */
13715    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13716        ensureTransformationInfo();
13717        if (mTransformationInfo.mAlpha != alpha) {
13718            // Report visibility changes, which can affect children, to accessibility
13719            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13720                notifySubtreeAccessibilityStateChangedIfNeeded();
13721            }
13722            mTransformationInfo.mAlpha = alpha;
13723            if (onSetAlpha((int) (alpha * 255))) {
13724                mPrivateFlags |= PFLAG_ALPHA_SET;
13725                // subclass is handling alpha - don't optimize rendering cache invalidation
13726                invalidateParentCaches();
13727                invalidate(true);
13728            } else {
13729                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13730                invalidateViewProperty(true, false);
13731                mRenderNode.setAlpha(getFinalAlpha());
13732            }
13733        }
13734    }
13735
13736    /**
13737     * Faster version of setAlpha() which performs the same steps except there are
13738     * no calls to invalidate(). The caller of this function should perform proper invalidation
13739     * on the parent and this object. The return value indicates whether the subclass handles
13740     * alpha (the return value for onSetAlpha()).
13741     *
13742     * @param alpha The new value for the alpha property
13743     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13744     *         the new value for the alpha property is different from the old value
13745     */
13746    boolean setAlphaNoInvalidation(float alpha) {
13747        ensureTransformationInfo();
13748        if (mTransformationInfo.mAlpha != alpha) {
13749            mTransformationInfo.mAlpha = alpha;
13750            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13751            if (subclassHandlesAlpha) {
13752                mPrivateFlags |= PFLAG_ALPHA_SET;
13753                return true;
13754            } else {
13755                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13756                mRenderNode.setAlpha(getFinalAlpha());
13757            }
13758        }
13759        return false;
13760    }
13761
13762    /**
13763     * This property is hidden and intended only for use by the Fade transition, which
13764     * animates it to produce a visual translucency that does not side-effect (or get
13765     * affected by) the real alpha property. This value is composited with the other
13766     * alpha value (and the AlphaAnimation value, when that is present) to produce
13767     * a final visual translucency result, which is what is passed into the DisplayList.
13768     *
13769     * @hide
13770     */
13771    public void setTransitionAlpha(float alpha) {
13772        ensureTransformationInfo();
13773        if (mTransformationInfo.mTransitionAlpha != alpha) {
13774            mTransformationInfo.mTransitionAlpha = alpha;
13775            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13776            invalidateViewProperty(true, false);
13777            mRenderNode.setAlpha(getFinalAlpha());
13778        }
13779    }
13780
13781    /**
13782     * Calculates the visual alpha of this view, which is a combination of the actual
13783     * alpha value and the transitionAlpha value (if set).
13784     */
13785    private float getFinalAlpha() {
13786        if (mTransformationInfo != null) {
13787            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13788        }
13789        return 1;
13790    }
13791
13792    /**
13793     * This property is hidden and intended only for use by the Fade transition, which
13794     * animates it to produce a visual translucency that does not side-effect (or get
13795     * affected by) the real alpha property. This value is composited with the other
13796     * alpha value (and the AlphaAnimation value, when that is present) to produce
13797     * a final visual translucency result, which is what is passed into the DisplayList.
13798     *
13799     * @hide
13800     */
13801    @ViewDebug.ExportedProperty(category = "drawing")
13802    public float getTransitionAlpha() {
13803        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13804    }
13805
13806    /**
13807     * Top position of this view relative to its parent.
13808     *
13809     * @return The top of this view, in pixels.
13810     */
13811    @ViewDebug.CapturedViewProperty
13812    public final int getTop() {
13813        return mTop;
13814    }
13815
13816    /**
13817     * Sets the top position of this view relative to its parent. This method is meant to be called
13818     * by the layout system and should not generally be called otherwise, because the property
13819     * may be changed at any time by the layout.
13820     *
13821     * @param top The top of this view, in pixels.
13822     */
13823    public final void setTop(int top) {
13824        if (top != mTop) {
13825            final boolean matrixIsIdentity = hasIdentityMatrix();
13826            if (matrixIsIdentity) {
13827                if (mAttachInfo != null) {
13828                    int minTop;
13829                    int yLoc;
13830                    if (top < mTop) {
13831                        minTop = top;
13832                        yLoc = top - mTop;
13833                    } else {
13834                        minTop = mTop;
13835                        yLoc = 0;
13836                    }
13837                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13838                }
13839            } else {
13840                // Double-invalidation is necessary to capture view's old and new areas
13841                invalidate(true);
13842            }
13843
13844            int width = mRight - mLeft;
13845            int oldHeight = mBottom - mTop;
13846
13847            mTop = top;
13848            mRenderNode.setTop(mTop);
13849
13850            sizeChange(width, mBottom - mTop, width, oldHeight);
13851
13852            if (!matrixIsIdentity) {
13853                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13854                invalidate(true);
13855            }
13856            mBackgroundSizeChanged = true;
13857            if (mForegroundInfo != null) {
13858                mForegroundInfo.mBoundsChanged = true;
13859            }
13860            invalidateParentIfNeeded();
13861            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13862                // View was rejected last time it was drawn by its parent; this may have changed
13863                invalidateParentIfNeeded();
13864            }
13865        }
13866    }
13867
13868    /**
13869     * Bottom position of this view relative to its parent.
13870     *
13871     * @return The bottom of this view, in pixels.
13872     */
13873    @ViewDebug.CapturedViewProperty
13874    public final int getBottom() {
13875        return mBottom;
13876    }
13877
13878    /**
13879     * True if this view has changed since the last time being drawn.
13880     *
13881     * @return The dirty state of this view.
13882     */
13883    public boolean isDirty() {
13884        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13885    }
13886
13887    /**
13888     * Sets the bottom position of this view relative to its parent. This method is meant to be
13889     * called by the layout system and should not generally be called otherwise, because the
13890     * property may be changed at any time by the layout.
13891     *
13892     * @param bottom The bottom of this view, in pixels.
13893     */
13894    public final void setBottom(int bottom) {
13895        if (bottom != mBottom) {
13896            final boolean matrixIsIdentity = hasIdentityMatrix();
13897            if (matrixIsIdentity) {
13898                if (mAttachInfo != null) {
13899                    int maxBottom;
13900                    if (bottom < mBottom) {
13901                        maxBottom = mBottom;
13902                    } else {
13903                        maxBottom = bottom;
13904                    }
13905                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13906                }
13907            } else {
13908                // Double-invalidation is necessary to capture view's old and new areas
13909                invalidate(true);
13910            }
13911
13912            int width = mRight - mLeft;
13913            int oldHeight = mBottom - mTop;
13914
13915            mBottom = bottom;
13916            mRenderNode.setBottom(mBottom);
13917
13918            sizeChange(width, mBottom - mTop, width, oldHeight);
13919
13920            if (!matrixIsIdentity) {
13921                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13922                invalidate(true);
13923            }
13924            mBackgroundSizeChanged = true;
13925            if (mForegroundInfo != null) {
13926                mForegroundInfo.mBoundsChanged = true;
13927            }
13928            invalidateParentIfNeeded();
13929            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13930                // View was rejected last time it was drawn by its parent; this may have changed
13931                invalidateParentIfNeeded();
13932            }
13933        }
13934    }
13935
13936    /**
13937     * Left position of this view relative to its parent.
13938     *
13939     * @return The left edge of this view, in pixels.
13940     */
13941    @ViewDebug.CapturedViewProperty
13942    public final int getLeft() {
13943        return mLeft;
13944    }
13945
13946    /**
13947     * Sets the left position of this view relative to its parent. This method is meant to be called
13948     * by the layout system and should not generally be called otherwise, because the property
13949     * may be changed at any time by the layout.
13950     *
13951     * @param left The left of this view, in pixels.
13952     */
13953    public final void setLeft(int left) {
13954        if (left != mLeft) {
13955            final boolean matrixIsIdentity = hasIdentityMatrix();
13956            if (matrixIsIdentity) {
13957                if (mAttachInfo != null) {
13958                    int minLeft;
13959                    int xLoc;
13960                    if (left < mLeft) {
13961                        minLeft = left;
13962                        xLoc = left - mLeft;
13963                    } else {
13964                        minLeft = mLeft;
13965                        xLoc = 0;
13966                    }
13967                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
13968                }
13969            } else {
13970                // Double-invalidation is necessary to capture view's old and new areas
13971                invalidate(true);
13972            }
13973
13974            int oldWidth = mRight - mLeft;
13975            int height = mBottom - mTop;
13976
13977            mLeft = left;
13978            mRenderNode.setLeft(left);
13979
13980            sizeChange(mRight - mLeft, height, oldWidth, height);
13981
13982            if (!matrixIsIdentity) {
13983                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13984                invalidate(true);
13985            }
13986            mBackgroundSizeChanged = true;
13987            if (mForegroundInfo != null) {
13988                mForegroundInfo.mBoundsChanged = true;
13989            }
13990            invalidateParentIfNeeded();
13991            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13992                // View was rejected last time it was drawn by its parent; this may have changed
13993                invalidateParentIfNeeded();
13994            }
13995        }
13996    }
13997
13998    /**
13999     * Right position of this view relative to its parent.
14000     *
14001     * @return The right edge of this view, in pixels.
14002     */
14003    @ViewDebug.CapturedViewProperty
14004    public final int getRight() {
14005        return mRight;
14006    }
14007
14008    /**
14009     * Sets the right position of this view relative to its parent. This method is meant to be called
14010     * by the layout system and should not generally be called otherwise, because the property
14011     * may be changed at any time by the layout.
14012     *
14013     * @param right The right of this view, in pixels.
14014     */
14015    public final void setRight(int right) {
14016        if (right != mRight) {
14017            final boolean matrixIsIdentity = hasIdentityMatrix();
14018            if (matrixIsIdentity) {
14019                if (mAttachInfo != null) {
14020                    int maxRight;
14021                    if (right < mRight) {
14022                        maxRight = mRight;
14023                    } else {
14024                        maxRight = right;
14025                    }
14026                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14027                }
14028            } else {
14029                // Double-invalidation is necessary to capture view's old and new areas
14030                invalidate(true);
14031            }
14032
14033            int oldWidth = mRight - mLeft;
14034            int height = mBottom - mTop;
14035
14036            mRight = right;
14037            mRenderNode.setRight(mRight);
14038
14039            sizeChange(mRight - mLeft, height, oldWidth, height);
14040
14041            if (!matrixIsIdentity) {
14042                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14043                invalidate(true);
14044            }
14045            mBackgroundSizeChanged = true;
14046            if (mForegroundInfo != null) {
14047                mForegroundInfo.mBoundsChanged = true;
14048            }
14049            invalidateParentIfNeeded();
14050            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14051                // View was rejected last time it was drawn by its parent; this may have changed
14052                invalidateParentIfNeeded();
14053            }
14054        }
14055    }
14056
14057    /**
14058     * The visual x position of this view, in pixels. This is equivalent to the
14059     * {@link #setTranslationX(float) translationX} property plus the current
14060     * {@link #getLeft() left} property.
14061     *
14062     * @return The visual x position of this view, in pixels.
14063     */
14064    @ViewDebug.ExportedProperty(category = "drawing")
14065    public float getX() {
14066        return mLeft + getTranslationX();
14067    }
14068
14069    /**
14070     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14071     * {@link #setTranslationX(float) translationX} property to be the difference between
14072     * the x value passed in and the current {@link #getLeft() left} property.
14073     *
14074     * @param x The visual x position of this view, in pixels.
14075     */
14076    public void setX(float x) {
14077        setTranslationX(x - mLeft);
14078    }
14079
14080    /**
14081     * The visual y position of this view, in pixels. This is equivalent to the
14082     * {@link #setTranslationY(float) translationY} property plus the current
14083     * {@link #getTop() top} property.
14084     *
14085     * @return The visual y position of this view, in pixels.
14086     */
14087    @ViewDebug.ExportedProperty(category = "drawing")
14088    public float getY() {
14089        return mTop + getTranslationY();
14090    }
14091
14092    /**
14093     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14094     * {@link #setTranslationY(float) translationY} property to be the difference between
14095     * the y value passed in and the current {@link #getTop() top} property.
14096     *
14097     * @param y The visual y position of this view, in pixels.
14098     */
14099    public void setY(float y) {
14100        setTranslationY(y - mTop);
14101    }
14102
14103    /**
14104     * The visual z position of this view, in pixels. This is equivalent to the
14105     * {@link #setTranslationZ(float) translationZ} property plus the current
14106     * {@link #getElevation() elevation} property.
14107     *
14108     * @return The visual z position of this view, in pixels.
14109     */
14110    @ViewDebug.ExportedProperty(category = "drawing")
14111    public float getZ() {
14112        return getElevation() + getTranslationZ();
14113    }
14114
14115    /**
14116     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14117     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14118     * the x value passed in and the current {@link #getElevation() elevation} property.
14119     *
14120     * @param z The visual z position of this view, in pixels.
14121     */
14122    public void setZ(float z) {
14123        setTranslationZ(z - getElevation());
14124    }
14125
14126    /**
14127     * The base elevation of this view relative to its parent, in pixels.
14128     *
14129     * @return The base depth position of the view, in pixels.
14130     */
14131    @ViewDebug.ExportedProperty(category = "drawing")
14132    public float getElevation() {
14133        return mRenderNode.getElevation();
14134    }
14135
14136    /**
14137     * Sets the base elevation of this view, in pixels.
14138     *
14139     * @attr ref android.R.styleable#View_elevation
14140     */
14141    public void setElevation(float elevation) {
14142        if (elevation != getElevation()) {
14143            invalidateViewProperty(true, false);
14144            mRenderNode.setElevation(elevation);
14145            invalidateViewProperty(false, true);
14146
14147            invalidateParentIfNeededAndWasQuickRejected();
14148        }
14149    }
14150
14151    /**
14152     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14153     * This position is post-layout, in addition to wherever the object's
14154     * layout placed it.
14155     *
14156     * @return The horizontal position of this view relative to its left position, in pixels.
14157     */
14158    @ViewDebug.ExportedProperty(category = "drawing")
14159    public float getTranslationX() {
14160        return mRenderNode.getTranslationX();
14161    }
14162
14163    /**
14164     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14165     * This effectively positions the object post-layout, in addition to wherever the object's
14166     * layout placed it.
14167     *
14168     * @param translationX The horizontal position of this view relative to its left position,
14169     * in pixels.
14170     *
14171     * @attr ref android.R.styleable#View_translationX
14172     */
14173    public void setTranslationX(float translationX) {
14174        if (translationX != getTranslationX()) {
14175            invalidateViewProperty(true, false);
14176            mRenderNode.setTranslationX(translationX);
14177            invalidateViewProperty(false, true);
14178
14179            invalidateParentIfNeededAndWasQuickRejected();
14180            notifySubtreeAccessibilityStateChangedIfNeeded();
14181        }
14182    }
14183
14184    /**
14185     * The vertical location of this view relative to its {@link #getTop() top} position.
14186     * This position is post-layout, in addition to wherever the object's
14187     * layout placed it.
14188     *
14189     * @return The vertical position of this view relative to its top position,
14190     * in pixels.
14191     */
14192    @ViewDebug.ExportedProperty(category = "drawing")
14193    public float getTranslationY() {
14194        return mRenderNode.getTranslationY();
14195    }
14196
14197    /**
14198     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14199     * This effectively positions the object post-layout, in addition to wherever the object's
14200     * layout placed it.
14201     *
14202     * @param translationY The vertical position of this view relative to its top position,
14203     * in pixels.
14204     *
14205     * @attr ref android.R.styleable#View_translationY
14206     */
14207    public void setTranslationY(float translationY) {
14208        if (translationY != getTranslationY()) {
14209            invalidateViewProperty(true, false);
14210            mRenderNode.setTranslationY(translationY);
14211            invalidateViewProperty(false, true);
14212
14213            invalidateParentIfNeededAndWasQuickRejected();
14214            notifySubtreeAccessibilityStateChangedIfNeeded();
14215        }
14216    }
14217
14218    /**
14219     * The depth location of this view relative to its {@link #getElevation() elevation}.
14220     *
14221     * @return The depth of this view relative to its elevation.
14222     */
14223    @ViewDebug.ExportedProperty(category = "drawing")
14224    public float getTranslationZ() {
14225        return mRenderNode.getTranslationZ();
14226    }
14227
14228    /**
14229     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14230     *
14231     * @attr ref android.R.styleable#View_translationZ
14232     */
14233    public void setTranslationZ(float translationZ) {
14234        if (translationZ != getTranslationZ()) {
14235            invalidateViewProperty(true, false);
14236            mRenderNode.setTranslationZ(translationZ);
14237            invalidateViewProperty(false, true);
14238
14239            invalidateParentIfNeededAndWasQuickRejected();
14240        }
14241    }
14242
14243    /** @hide */
14244    public void setAnimationMatrix(Matrix matrix) {
14245        invalidateViewProperty(true, false);
14246        mRenderNode.setAnimationMatrix(matrix);
14247        invalidateViewProperty(false, true);
14248
14249        invalidateParentIfNeededAndWasQuickRejected();
14250    }
14251
14252    /**
14253     * Returns the current StateListAnimator if exists.
14254     *
14255     * @return StateListAnimator or null if it does not exists
14256     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14257     */
14258    public StateListAnimator getStateListAnimator() {
14259        return mStateListAnimator;
14260    }
14261
14262    /**
14263     * Attaches the provided StateListAnimator to this View.
14264     * <p>
14265     * Any previously attached StateListAnimator will be detached.
14266     *
14267     * @param stateListAnimator The StateListAnimator to update the view
14268     * @see android.animation.StateListAnimator
14269     */
14270    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14271        if (mStateListAnimator == stateListAnimator) {
14272            return;
14273        }
14274        if (mStateListAnimator != null) {
14275            mStateListAnimator.setTarget(null);
14276        }
14277        mStateListAnimator = stateListAnimator;
14278        if (stateListAnimator != null) {
14279            stateListAnimator.setTarget(this);
14280            if (isAttachedToWindow()) {
14281                stateListAnimator.setState(getDrawableState());
14282            }
14283        }
14284    }
14285
14286    /**
14287     * Returns whether the Outline should be used to clip the contents of the View.
14288     * <p>
14289     * Note that this flag will only be respected if the View's Outline returns true from
14290     * {@link Outline#canClip()}.
14291     *
14292     * @see #setOutlineProvider(ViewOutlineProvider)
14293     * @see #setClipToOutline(boolean)
14294     */
14295    public final boolean getClipToOutline() {
14296        return mRenderNode.getClipToOutline();
14297    }
14298
14299    /**
14300     * Sets whether the View's Outline should be used to clip the contents of the View.
14301     * <p>
14302     * Only a single non-rectangular clip can be applied on a View at any time.
14303     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14304     * circular reveal} animation take priority over Outline clipping, and
14305     * child Outline clipping takes priority over Outline clipping done by a
14306     * parent.
14307     * <p>
14308     * Note that this flag will only be respected if the View's Outline returns true from
14309     * {@link Outline#canClip()}.
14310     *
14311     * @see #setOutlineProvider(ViewOutlineProvider)
14312     * @see #getClipToOutline()
14313     */
14314    public void setClipToOutline(boolean clipToOutline) {
14315        damageInParent();
14316        if (getClipToOutline() != clipToOutline) {
14317            mRenderNode.setClipToOutline(clipToOutline);
14318        }
14319    }
14320
14321    // correspond to the enum values of View_outlineProvider
14322    private static final int PROVIDER_BACKGROUND = 0;
14323    private static final int PROVIDER_NONE = 1;
14324    private static final int PROVIDER_BOUNDS = 2;
14325    private static final int PROVIDER_PADDED_BOUNDS = 3;
14326    private void setOutlineProviderFromAttribute(int providerInt) {
14327        switch (providerInt) {
14328            case PROVIDER_BACKGROUND:
14329                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14330                break;
14331            case PROVIDER_NONE:
14332                setOutlineProvider(null);
14333                break;
14334            case PROVIDER_BOUNDS:
14335                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14336                break;
14337            case PROVIDER_PADDED_BOUNDS:
14338                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14339                break;
14340        }
14341    }
14342
14343    /**
14344     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14345     * the shape of the shadow it casts, and enables outline clipping.
14346     * <p>
14347     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14348     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14349     * outline provider with this method allows this behavior to be overridden.
14350     * <p>
14351     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14352     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14353     * <p>
14354     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14355     *
14356     * @see #setClipToOutline(boolean)
14357     * @see #getClipToOutline()
14358     * @see #getOutlineProvider()
14359     */
14360    public void setOutlineProvider(ViewOutlineProvider provider) {
14361        mOutlineProvider = provider;
14362        invalidateOutline();
14363    }
14364
14365    /**
14366     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14367     * that defines the shape of the shadow it casts, and enables outline clipping.
14368     *
14369     * @see #setOutlineProvider(ViewOutlineProvider)
14370     */
14371    public ViewOutlineProvider getOutlineProvider() {
14372        return mOutlineProvider;
14373    }
14374
14375    /**
14376     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14377     *
14378     * @see #setOutlineProvider(ViewOutlineProvider)
14379     */
14380    public void invalidateOutline() {
14381        rebuildOutline();
14382
14383        notifySubtreeAccessibilityStateChangedIfNeeded();
14384        invalidateViewProperty(false, false);
14385    }
14386
14387    /**
14388     * Internal version of {@link #invalidateOutline()} which invalidates the
14389     * outline without invalidating the view itself. This is intended to be called from
14390     * within methods in the View class itself which are the result of the view being
14391     * invalidated already. For example, when we are drawing the background of a View,
14392     * we invalidate the outline in case it changed in the meantime, but we do not
14393     * need to invalidate the view because we're already drawing the background as part
14394     * of drawing the view in response to an earlier invalidation of the view.
14395     */
14396    private void rebuildOutline() {
14397        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14398        if (mAttachInfo == null) return;
14399
14400        if (mOutlineProvider == null) {
14401            // no provider, remove outline
14402            mRenderNode.setOutline(null);
14403        } else {
14404            final Outline outline = mAttachInfo.mTmpOutline;
14405            outline.setEmpty();
14406            outline.setAlpha(1.0f);
14407
14408            mOutlineProvider.getOutline(this, outline);
14409            mRenderNode.setOutline(outline);
14410        }
14411    }
14412
14413    /**
14414     * HierarchyViewer only
14415     *
14416     * @hide
14417     */
14418    @ViewDebug.ExportedProperty(category = "drawing")
14419    public boolean hasShadow() {
14420        return mRenderNode.hasShadow();
14421    }
14422
14423
14424    /** @hide */
14425    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14426        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14427        invalidateViewProperty(false, false);
14428    }
14429
14430    /**
14431     * Hit rectangle in parent's coordinates
14432     *
14433     * @param outRect The hit rectangle of the view.
14434     */
14435    public void getHitRect(Rect outRect) {
14436        if (hasIdentityMatrix() || mAttachInfo == null) {
14437            outRect.set(mLeft, mTop, mRight, mBottom);
14438        } else {
14439            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14440            tmpRect.set(0, 0, getWidth(), getHeight());
14441            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14442            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14443                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14444        }
14445    }
14446
14447    /**
14448     * Determines whether the given point, in local coordinates is inside the view.
14449     */
14450    /*package*/ final boolean pointInView(float localX, float localY) {
14451        return pointInView(localX, localY, 0);
14452    }
14453
14454    /**
14455     * Utility method to determine whether the given point, in local coordinates,
14456     * is inside the view, where the area of the view is expanded by the slop factor.
14457     * This method is called while processing touch-move events to determine if the event
14458     * is still within the view.
14459     *
14460     * @hide
14461     */
14462    public boolean pointInView(float localX, float localY, float slop) {
14463        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14464                localY < ((mBottom - mTop) + slop);
14465    }
14466
14467    /**
14468     * When a view has focus and the user navigates away from it, the next view is searched for
14469     * starting from the rectangle filled in by this method.
14470     *
14471     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14472     * of the view.  However, if your view maintains some idea of internal selection,
14473     * such as a cursor, or a selected row or column, you should override this method and
14474     * fill in a more specific rectangle.
14475     *
14476     * @param r The rectangle to fill in, in this view's coordinates.
14477     */
14478    public void getFocusedRect(Rect r) {
14479        getDrawingRect(r);
14480    }
14481
14482    /**
14483     * If some part of this view is not clipped by any of its parents, then
14484     * return that area in r in global (root) coordinates. To convert r to local
14485     * coordinates (without taking possible View rotations into account), offset
14486     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14487     * If the view is completely clipped or translated out, return false.
14488     *
14489     * @param r If true is returned, r holds the global coordinates of the
14490     *        visible portion of this view.
14491     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14492     *        between this view and its root. globalOffet may be null.
14493     * @return true if r is non-empty (i.e. part of the view is visible at the
14494     *         root level.
14495     */
14496    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14497        int width = mRight - mLeft;
14498        int height = mBottom - mTop;
14499        if (width > 0 && height > 0) {
14500            r.set(0, 0, width, height);
14501            if (globalOffset != null) {
14502                globalOffset.set(-mScrollX, -mScrollY);
14503            }
14504            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14505        }
14506        return false;
14507    }
14508
14509    public final boolean getGlobalVisibleRect(Rect r) {
14510        return getGlobalVisibleRect(r, null);
14511    }
14512
14513    public final boolean getLocalVisibleRect(Rect r) {
14514        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14515        if (getGlobalVisibleRect(r, offset)) {
14516            r.offset(-offset.x, -offset.y); // make r local
14517            return true;
14518        }
14519        return false;
14520    }
14521
14522    /**
14523     * Offset this view's vertical location by the specified number of pixels.
14524     *
14525     * @param offset the number of pixels to offset the view by
14526     */
14527    public void offsetTopAndBottom(int offset) {
14528        if (offset != 0) {
14529            final boolean matrixIsIdentity = hasIdentityMatrix();
14530            if (matrixIsIdentity) {
14531                if (isHardwareAccelerated()) {
14532                    invalidateViewProperty(false, false);
14533                } else {
14534                    final ViewParent p = mParent;
14535                    if (p != null && mAttachInfo != null) {
14536                        final Rect r = mAttachInfo.mTmpInvalRect;
14537                        int minTop;
14538                        int maxBottom;
14539                        int yLoc;
14540                        if (offset < 0) {
14541                            minTop = mTop + offset;
14542                            maxBottom = mBottom;
14543                            yLoc = offset;
14544                        } else {
14545                            minTop = mTop;
14546                            maxBottom = mBottom + offset;
14547                            yLoc = 0;
14548                        }
14549                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14550                        p.invalidateChild(this, r);
14551                    }
14552                }
14553            } else {
14554                invalidateViewProperty(false, false);
14555            }
14556
14557            mTop += offset;
14558            mBottom += offset;
14559            mRenderNode.offsetTopAndBottom(offset);
14560            if (isHardwareAccelerated()) {
14561                invalidateViewProperty(false, false);
14562                invalidateParentIfNeededAndWasQuickRejected();
14563            } else {
14564                if (!matrixIsIdentity) {
14565                    invalidateViewProperty(false, true);
14566                }
14567                invalidateParentIfNeeded();
14568            }
14569            notifySubtreeAccessibilityStateChangedIfNeeded();
14570        }
14571    }
14572
14573    /**
14574     * Offset this view's horizontal location by the specified amount of pixels.
14575     *
14576     * @param offset the number of pixels to offset the view by
14577     */
14578    public void offsetLeftAndRight(int offset) {
14579        if (offset != 0) {
14580            final boolean matrixIsIdentity = hasIdentityMatrix();
14581            if (matrixIsIdentity) {
14582                if (isHardwareAccelerated()) {
14583                    invalidateViewProperty(false, false);
14584                } else {
14585                    final ViewParent p = mParent;
14586                    if (p != null && mAttachInfo != null) {
14587                        final Rect r = mAttachInfo.mTmpInvalRect;
14588                        int minLeft;
14589                        int maxRight;
14590                        if (offset < 0) {
14591                            minLeft = mLeft + offset;
14592                            maxRight = mRight;
14593                        } else {
14594                            minLeft = mLeft;
14595                            maxRight = mRight + offset;
14596                        }
14597                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14598                        p.invalidateChild(this, r);
14599                    }
14600                }
14601            } else {
14602                invalidateViewProperty(false, false);
14603            }
14604
14605            mLeft += offset;
14606            mRight += offset;
14607            mRenderNode.offsetLeftAndRight(offset);
14608            if (isHardwareAccelerated()) {
14609                invalidateViewProperty(false, false);
14610                invalidateParentIfNeededAndWasQuickRejected();
14611            } else {
14612                if (!matrixIsIdentity) {
14613                    invalidateViewProperty(false, true);
14614                }
14615                invalidateParentIfNeeded();
14616            }
14617            notifySubtreeAccessibilityStateChangedIfNeeded();
14618        }
14619    }
14620
14621    /**
14622     * Get the LayoutParams associated with this view. All views should have
14623     * layout parameters. These supply parameters to the <i>parent</i> of this
14624     * view specifying how it should be arranged. There are many subclasses of
14625     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14626     * of ViewGroup that are responsible for arranging their children.
14627     *
14628     * This method may return null if this View is not attached to a parent
14629     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14630     * was not invoked successfully. When a View is attached to a parent
14631     * ViewGroup, this method must not return null.
14632     *
14633     * @return The LayoutParams associated with this view, or null if no
14634     *         parameters have been set yet
14635     */
14636    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14637    public ViewGroup.LayoutParams getLayoutParams() {
14638        return mLayoutParams;
14639    }
14640
14641    /**
14642     * Set the layout parameters associated with this view. These supply
14643     * parameters to the <i>parent</i> of this view specifying how it should be
14644     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14645     * correspond to the different subclasses of ViewGroup that are responsible
14646     * for arranging their children.
14647     *
14648     * @param params The layout parameters for this view, cannot be null
14649     */
14650    public void setLayoutParams(ViewGroup.LayoutParams params) {
14651        if (params == null) {
14652            throw new NullPointerException("Layout parameters cannot be null");
14653        }
14654        mLayoutParams = params;
14655        resolveLayoutParams();
14656        if (mParent instanceof ViewGroup) {
14657            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14658        }
14659        requestLayout();
14660    }
14661
14662    /**
14663     * Resolve the layout parameters depending on the resolved layout direction
14664     *
14665     * @hide
14666     */
14667    public void resolveLayoutParams() {
14668        if (mLayoutParams != null) {
14669            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14670        }
14671    }
14672
14673    /**
14674     * Set the scrolled position of your view. This will cause a call to
14675     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14676     * invalidated.
14677     * @param x the x position to scroll to
14678     * @param y the y position to scroll to
14679     */
14680    public void scrollTo(int x, int y) {
14681        if (mScrollX != x || mScrollY != y) {
14682            int oldX = mScrollX;
14683            int oldY = mScrollY;
14684            mScrollX = x;
14685            mScrollY = y;
14686            invalidateParentCaches();
14687            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14688            if (!awakenScrollBars()) {
14689                postInvalidateOnAnimation();
14690            }
14691        }
14692    }
14693
14694    /**
14695     * Move the scrolled position of your view. This will cause a call to
14696     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14697     * invalidated.
14698     * @param x the amount of pixels to scroll by horizontally
14699     * @param y the amount of pixels to scroll by vertically
14700     */
14701    public void scrollBy(int x, int y) {
14702        scrollTo(mScrollX + x, mScrollY + y);
14703    }
14704
14705    /**
14706     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14707     * animation to fade the scrollbars out after a default delay. If a subclass
14708     * provides animated scrolling, the start delay should equal the duration
14709     * of the scrolling animation.</p>
14710     *
14711     * <p>The animation starts only if at least one of the scrollbars is
14712     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14713     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14714     * this method returns true, and false otherwise. If the animation is
14715     * started, this method calls {@link #invalidate()}; in that case the
14716     * caller should not call {@link #invalidate()}.</p>
14717     *
14718     * <p>This method should be invoked every time a subclass directly updates
14719     * the scroll parameters.</p>
14720     *
14721     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14722     * and {@link #scrollTo(int, int)}.</p>
14723     *
14724     * @return true if the animation is played, false otherwise
14725     *
14726     * @see #awakenScrollBars(int)
14727     * @see #scrollBy(int, int)
14728     * @see #scrollTo(int, int)
14729     * @see #isHorizontalScrollBarEnabled()
14730     * @see #isVerticalScrollBarEnabled()
14731     * @see #setHorizontalScrollBarEnabled(boolean)
14732     * @see #setVerticalScrollBarEnabled(boolean)
14733     */
14734    protected boolean awakenScrollBars() {
14735        return mScrollCache != null &&
14736                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14737    }
14738
14739    /**
14740     * Trigger the scrollbars to draw.
14741     * This method differs from awakenScrollBars() only in its default duration.
14742     * initialAwakenScrollBars() will show the scroll bars for longer than
14743     * usual to give the user more of a chance to notice them.
14744     *
14745     * @return true if the animation is played, false otherwise.
14746     */
14747    private boolean initialAwakenScrollBars() {
14748        return mScrollCache != null &&
14749                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14750    }
14751
14752    /**
14753     * <p>
14754     * Trigger the scrollbars to draw. When invoked this method starts an
14755     * animation to fade the scrollbars out after a fixed delay. If a subclass
14756     * provides animated scrolling, the start delay should equal the duration of
14757     * the scrolling animation.
14758     * </p>
14759     *
14760     * <p>
14761     * The animation starts only if at least one of the scrollbars is enabled,
14762     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14763     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14764     * this method returns true, and false otherwise. If the animation is
14765     * started, this method calls {@link #invalidate()}; in that case the caller
14766     * should not call {@link #invalidate()}.
14767     * </p>
14768     *
14769     * <p>
14770     * This method should be invoked every time a subclass directly updates the
14771     * scroll parameters.
14772     * </p>
14773     *
14774     * @param startDelay the delay, in milliseconds, after which the animation
14775     *        should start; when the delay is 0, the animation starts
14776     *        immediately
14777     * @return true if the animation is played, false otherwise
14778     *
14779     * @see #scrollBy(int, int)
14780     * @see #scrollTo(int, int)
14781     * @see #isHorizontalScrollBarEnabled()
14782     * @see #isVerticalScrollBarEnabled()
14783     * @see #setHorizontalScrollBarEnabled(boolean)
14784     * @see #setVerticalScrollBarEnabled(boolean)
14785     */
14786    protected boolean awakenScrollBars(int startDelay) {
14787        return awakenScrollBars(startDelay, true);
14788    }
14789
14790    /**
14791     * <p>
14792     * Trigger the scrollbars to draw. When invoked this method starts an
14793     * animation to fade the scrollbars out after a fixed delay. If a subclass
14794     * provides animated scrolling, the start delay should equal the duration of
14795     * the scrolling animation.
14796     * </p>
14797     *
14798     * <p>
14799     * The animation starts only if at least one of the scrollbars is enabled,
14800     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14801     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14802     * this method returns true, and false otherwise. If the animation is
14803     * started, this method calls {@link #invalidate()} if the invalidate parameter
14804     * is set to true; in that case the caller
14805     * should not call {@link #invalidate()}.
14806     * </p>
14807     *
14808     * <p>
14809     * This method should be invoked every time a subclass directly updates the
14810     * scroll parameters.
14811     * </p>
14812     *
14813     * @param startDelay the delay, in milliseconds, after which the animation
14814     *        should start; when the delay is 0, the animation starts
14815     *        immediately
14816     *
14817     * @param invalidate Whether this method should call invalidate
14818     *
14819     * @return true if the animation is played, false otherwise
14820     *
14821     * @see #scrollBy(int, int)
14822     * @see #scrollTo(int, int)
14823     * @see #isHorizontalScrollBarEnabled()
14824     * @see #isVerticalScrollBarEnabled()
14825     * @see #setHorizontalScrollBarEnabled(boolean)
14826     * @see #setVerticalScrollBarEnabled(boolean)
14827     */
14828    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14829        final ScrollabilityCache scrollCache = mScrollCache;
14830
14831        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14832            return false;
14833        }
14834
14835        if (scrollCache.scrollBar == null) {
14836            scrollCache.scrollBar = new ScrollBarDrawable();
14837            scrollCache.scrollBar.setState(getDrawableState());
14838            scrollCache.scrollBar.setCallback(this);
14839        }
14840
14841        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14842
14843            if (invalidate) {
14844                // Invalidate to show the scrollbars
14845                postInvalidateOnAnimation();
14846            }
14847
14848            if (scrollCache.state == ScrollabilityCache.OFF) {
14849                // FIXME: this is copied from WindowManagerService.
14850                // We should get this value from the system when it
14851                // is possible to do so.
14852                final int KEY_REPEAT_FIRST_DELAY = 750;
14853                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14854            }
14855
14856            // Tell mScrollCache when we should start fading. This may
14857            // extend the fade start time if one was already scheduled
14858            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14859            scrollCache.fadeStartTime = fadeStartTime;
14860            scrollCache.state = ScrollabilityCache.ON;
14861
14862            // Schedule our fader to run, unscheduling any old ones first
14863            if (mAttachInfo != null) {
14864                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14865                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14866            }
14867
14868            return true;
14869        }
14870
14871        return false;
14872    }
14873
14874    /**
14875     * Do not invalidate views which are not visible and which are not running an animation. They
14876     * will not get drawn and they should not set dirty flags as if they will be drawn
14877     */
14878    private boolean skipInvalidate() {
14879        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14880                (!(mParent instanceof ViewGroup) ||
14881                        !((ViewGroup) mParent).isViewTransitioning(this));
14882    }
14883
14884    /**
14885     * Mark the area defined by dirty as needing to be drawn. If the view is
14886     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14887     * point in the future.
14888     * <p>
14889     * This must be called from a UI thread. To call from a non-UI thread, call
14890     * {@link #postInvalidate()}.
14891     * <p>
14892     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14893     * {@code dirty}.
14894     *
14895     * @param dirty the rectangle representing the bounds of the dirty region
14896     */
14897    public void invalidate(Rect dirty) {
14898        final int scrollX = mScrollX;
14899        final int scrollY = mScrollY;
14900        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14901                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14902    }
14903
14904    /**
14905     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
14906     * coordinates of the dirty rect are relative to the view. If the view is
14907     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14908     * point in the future.
14909     * <p>
14910     * This must be called from a UI thread. To call from a non-UI thread, call
14911     * {@link #postInvalidate()}.
14912     *
14913     * @param l the left position of the dirty region
14914     * @param t the top position of the dirty region
14915     * @param r the right position of the dirty region
14916     * @param b the bottom position of the dirty region
14917     */
14918    public void invalidate(int l, int t, int r, int b) {
14919        final int scrollX = mScrollX;
14920        final int scrollY = mScrollY;
14921        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14922    }
14923
14924    /**
14925     * Invalidate the whole view. If the view is visible,
14926     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
14927     * the future.
14928     * <p>
14929     * This must be called from a UI thread. To call from a non-UI thread, call
14930     * {@link #postInvalidate()}.
14931     */
14932    public void invalidate() {
14933        invalidate(true);
14934    }
14935
14936    /**
14937     * This is where the invalidate() work actually happens. A full invalidate()
14938     * causes the drawing cache to be invalidated, but this function can be
14939     * called with invalidateCache set to false to skip that invalidation step
14940     * for cases that do not need it (for example, a component that remains at
14941     * the same dimensions with the same content).
14942     *
14943     * @param invalidateCache Whether the drawing cache for this view should be
14944     *            invalidated as well. This is usually true for a full
14945     *            invalidate, but may be set to false if the View's contents or
14946     *            dimensions have not changed.
14947     * @hide
14948     */
14949    public void invalidate(boolean invalidateCache) {
14950        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
14951    }
14952
14953    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
14954            boolean fullInvalidate) {
14955        if (mGhostView != null) {
14956            mGhostView.invalidate(true);
14957            return;
14958        }
14959
14960        if (skipInvalidate()) {
14961            return;
14962        }
14963
14964        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
14965                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
14966                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
14967                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
14968            if (fullInvalidate) {
14969                mLastIsOpaque = isOpaque();
14970                mPrivateFlags &= ~PFLAG_DRAWN;
14971            }
14972
14973            mPrivateFlags |= PFLAG_DIRTY;
14974
14975            if (invalidateCache) {
14976                mPrivateFlags |= PFLAG_INVALIDATED;
14977                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14978            }
14979
14980            // Propagate the damage rectangle to the parent view.
14981            final AttachInfo ai = mAttachInfo;
14982            final ViewParent p = mParent;
14983            if (p != null && ai != null && l < r && t < b) {
14984                final Rect damage = ai.mTmpInvalRect;
14985                damage.set(l, t, r, b);
14986                p.invalidateChild(this, damage);
14987            }
14988
14989            // Damage the entire projection receiver, if necessary.
14990            if (mBackground != null && mBackground.isProjected()) {
14991                final View receiver = getProjectionReceiver();
14992                if (receiver != null) {
14993                    receiver.damageInParent();
14994                }
14995            }
14996        }
14997    }
14998
14999    /**
15000     * @return this view's projection receiver, or {@code null} if none exists
15001     */
15002    private View getProjectionReceiver() {
15003        ViewParent p = getParent();
15004        while (p != null && p instanceof View) {
15005            final View v = (View) p;
15006            if (v.isProjectionReceiver()) {
15007                return v;
15008            }
15009            p = p.getParent();
15010        }
15011
15012        return null;
15013    }
15014
15015    /**
15016     * @return whether the view is a projection receiver
15017     */
15018    private boolean isProjectionReceiver() {
15019        return mBackground != null;
15020    }
15021
15022    /**
15023     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15024     * set any flags or handle all of the cases handled by the default invalidation methods.
15025     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15026     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15027     * walk up the hierarchy, transforming the dirty rect as necessary.
15028     *
15029     * The method also handles normal invalidation logic if display list properties are not
15030     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15031     * backup approach, to handle these cases used in the various property-setting methods.
15032     *
15033     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15034     * are not being used in this view
15035     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15036     * list properties are not being used in this view
15037     */
15038    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15039        if (!isHardwareAccelerated()
15040                || !mRenderNode.isValid()
15041                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15042            if (invalidateParent) {
15043                invalidateParentCaches();
15044            }
15045            if (forceRedraw) {
15046                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15047            }
15048            invalidate(false);
15049        } else {
15050            damageInParent();
15051        }
15052    }
15053
15054    /**
15055     * Tells the parent view to damage this view's bounds.
15056     *
15057     * @hide
15058     */
15059    protected void damageInParent() {
15060        if (mParent != null && mAttachInfo != null) {
15061            mParent.onDescendantInvalidated(this, this);
15062        }
15063    }
15064
15065    /**
15066     * Utility method to transform a given Rect by the current matrix of this view.
15067     */
15068    void transformRect(final Rect rect) {
15069        if (!getMatrix().isIdentity()) {
15070            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15071            boundingRect.set(rect);
15072            getMatrix().mapRect(boundingRect);
15073            rect.set((int) Math.floor(boundingRect.left),
15074                    (int) Math.floor(boundingRect.top),
15075                    (int) Math.ceil(boundingRect.right),
15076                    (int) Math.ceil(boundingRect.bottom));
15077        }
15078    }
15079
15080    /**
15081     * Used to indicate that the parent of this view should clear its caches. This functionality
15082     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15083     * which is necessary when various parent-managed properties of the view change, such as
15084     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15085     * clears the parent caches and does not causes an invalidate event.
15086     *
15087     * @hide
15088     */
15089    protected void invalidateParentCaches() {
15090        if (mParent instanceof View) {
15091            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15092        }
15093    }
15094
15095    /**
15096     * Used to indicate that the parent of this view should be invalidated. This functionality
15097     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15098     * which is necessary when various parent-managed properties of the view change, such as
15099     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15100     * an invalidation event to the parent.
15101     *
15102     * @hide
15103     */
15104    protected void invalidateParentIfNeeded() {
15105        if (isHardwareAccelerated() && mParent instanceof View) {
15106            ((View) mParent).invalidate(true);
15107        }
15108    }
15109
15110    /**
15111     * @hide
15112     */
15113    protected void invalidateParentIfNeededAndWasQuickRejected() {
15114        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15115            // View was rejected last time it was drawn by its parent; this may have changed
15116            invalidateParentIfNeeded();
15117        }
15118    }
15119
15120    /**
15121     * Indicates whether this View is opaque. An opaque View guarantees that it will
15122     * draw all the pixels overlapping its bounds using a fully opaque color.
15123     *
15124     * Subclasses of View should override this method whenever possible to indicate
15125     * whether an instance is opaque. Opaque Views are treated in a special way by
15126     * the View hierarchy, possibly allowing it to perform optimizations during
15127     * invalidate/draw passes.
15128     *
15129     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15130     */
15131    @ViewDebug.ExportedProperty(category = "drawing")
15132    public boolean isOpaque() {
15133        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15134                getFinalAlpha() >= 1.0f;
15135    }
15136
15137    /**
15138     * @hide
15139     */
15140    protected void computeOpaqueFlags() {
15141        // Opaque if:
15142        //   - Has a background
15143        //   - Background is opaque
15144        //   - Doesn't have scrollbars or scrollbars overlay
15145
15146        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15147            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15148        } else {
15149            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15150        }
15151
15152        final int flags = mViewFlags;
15153        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15154                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15155                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15156            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15157        } else {
15158            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15159        }
15160    }
15161
15162    /**
15163     * @hide
15164     */
15165    protected boolean hasOpaqueScrollbars() {
15166        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15167    }
15168
15169    /**
15170     * @return A handler associated with the thread running the View. This
15171     * handler can be used to pump events in the UI events queue.
15172     */
15173    public Handler getHandler() {
15174        final AttachInfo attachInfo = mAttachInfo;
15175        if (attachInfo != null) {
15176            return attachInfo.mHandler;
15177        }
15178        return null;
15179    }
15180
15181    /**
15182     * Returns the queue of runnable for this view.
15183     *
15184     * @return the queue of runnables for this view
15185     */
15186    private HandlerActionQueue getRunQueue() {
15187        if (mRunQueue == null) {
15188            mRunQueue = new HandlerActionQueue();
15189        }
15190        return mRunQueue;
15191    }
15192
15193    /**
15194     * Gets the view root associated with the View.
15195     * @return The view root, or null if none.
15196     * @hide
15197     */
15198    public ViewRootImpl getViewRootImpl() {
15199        if (mAttachInfo != null) {
15200            return mAttachInfo.mViewRootImpl;
15201        }
15202        return null;
15203    }
15204
15205    /**
15206     * @hide
15207     */
15208    public ThreadedRenderer getThreadedRenderer() {
15209        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15210    }
15211
15212    /**
15213     * <p>Causes the Runnable to be added to the message queue.
15214     * The runnable will be run on the user interface thread.</p>
15215     *
15216     * @param action The Runnable that will be executed.
15217     *
15218     * @return Returns true if the Runnable was successfully placed in to the
15219     *         message queue.  Returns false on failure, usually because the
15220     *         looper processing the message queue is exiting.
15221     *
15222     * @see #postDelayed
15223     * @see #removeCallbacks
15224     */
15225    public boolean post(Runnable action) {
15226        final AttachInfo attachInfo = mAttachInfo;
15227        if (attachInfo != null) {
15228            return attachInfo.mHandler.post(action);
15229        }
15230
15231        // Postpone the runnable until we know on which thread it needs to run.
15232        // Assume that the runnable will be successfully placed after attach.
15233        getRunQueue().post(action);
15234        return true;
15235    }
15236
15237    /**
15238     * <p>Causes the Runnable to be added to the message queue, to be run
15239     * after the specified amount of time elapses.
15240     * The runnable will be run on the user interface thread.</p>
15241     *
15242     * @param action The Runnable that will be executed.
15243     * @param delayMillis The delay (in milliseconds) until the Runnable
15244     *        will be executed.
15245     *
15246     * @return true if the Runnable was successfully placed in to the
15247     *         message queue.  Returns false on failure, usually because the
15248     *         looper processing the message queue is exiting.  Note that a
15249     *         result of true does not mean the Runnable will be processed --
15250     *         if the looper is quit before the delivery time of the message
15251     *         occurs then the message will be dropped.
15252     *
15253     * @see #post
15254     * @see #removeCallbacks
15255     */
15256    public boolean postDelayed(Runnable action, long delayMillis) {
15257        final AttachInfo attachInfo = mAttachInfo;
15258        if (attachInfo != null) {
15259            return attachInfo.mHandler.postDelayed(action, delayMillis);
15260        }
15261
15262        // Postpone the runnable until we know on which thread it needs to run.
15263        // Assume that the runnable will be successfully placed after attach.
15264        getRunQueue().postDelayed(action, delayMillis);
15265        return true;
15266    }
15267
15268    /**
15269     * <p>Causes the Runnable to execute on the next animation time step.
15270     * The runnable will be run on the user interface thread.</p>
15271     *
15272     * @param action The Runnable that will be executed.
15273     *
15274     * @see #postOnAnimationDelayed
15275     * @see #removeCallbacks
15276     */
15277    public void postOnAnimation(Runnable action) {
15278        final AttachInfo attachInfo = mAttachInfo;
15279        if (attachInfo != null) {
15280            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15281                    Choreographer.CALLBACK_ANIMATION, action, null);
15282        } else {
15283            // Postpone the runnable until we know
15284            // on which thread it needs to run.
15285            getRunQueue().post(action);
15286        }
15287    }
15288
15289    /**
15290     * <p>Causes the Runnable to execute on the next animation time step,
15291     * after the specified amount of time elapses.
15292     * The runnable will be run on the user interface thread.</p>
15293     *
15294     * @param action The Runnable that will be executed.
15295     * @param delayMillis The delay (in milliseconds) until the Runnable
15296     *        will be executed.
15297     *
15298     * @see #postOnAnimation
15299     * @see #removeCallbacks
15300     */
15301    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15302        final AttachInfo attachInfo = mAttachInfo;
15303        if (attachInfo != null) {
15304            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15305                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15306        } else {
15307            // Postpone the runnable until we know
15308            // on which thread it needs to run.
15309            getRunQueue().postDelayed(action, delayMillis);
15310        }
15311    }
15312
15313    /**
15314     * <p>Removes the specified Runnable from the message queue.</p>
15315     *
15316     * @param action The Runnable to remove from the message handling queue
15317     *
15318     * @return true if this view could ask the Handler to remove the Runnable,
15319     *         false otherwise. When the returned value is true, the Runnable
15320     *         may or may not have been actually removed from the message queue
15321     *         (for instance, if the Runnable was not in the queue already.)
15322     *
15323     * @see #post
15324     * @see #postDelayed
15325     * @see #postOnAnimation
15326     * @see #postOnAnimationDelayed
15327     */
15328    public boolean removeCallbacks(Runnable action) {
15329        if (action != null) {
15330            final AttachInfo attachInfo = mAttachInfo;
15331            if (attachInfo != null) {
15332                attachInfo.mHandler.removeCallbacks(action);
15333                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15334                        Choreographer.CALLBACK_ANIMATION, action, null);
15335            }
15336            getRunQueue().removeCallbacks(action);
15337        }
15338        return true;
15339    }
15340
15341    /**
15342     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15343     * Use this to invalidate the View from a non-UI thread.</p>
15344     *
15345     * <p>This method can be invoked from outside of the UI thread
15346     * only when this View is attached to a window.</p>
15347     *
15348     * @see #invalidate()
15349     * @see #postInvalidateDelayed(long)
15350     */
15351    public void postInvalidate() {
15352        postInvalidateDelayed(0);
15353    }
15354
15355    /**
15356     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15357     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15358     *
15359     * <p>This method can be invoked from outside of the UI thread
15360     * only when this View is attached to a window.</p>
15361     *
15362     * @param left The left coordinate of the rectangle to invalidate.
15363     * @param top The top coordinate of the rectangle to invalidate.
15364     * @param right The right coordinate of the rectangle to invalidate.
15365     * @param bottom The bottom coordinate of the rectangle to invalidate.
15366     *
15367     * @see #invalidate(int, int, int, int)
15368     * @see #invalidate(Rect)
15369     * @see #postInvalidateDelayed(long, int, int, int, int)
15370     */
15371    public void postInvalidate(int left, int top, int right, int bottom) {
15372        postInvalidateDelayed(0, left, top, right, bottom);
15373    }
15374
15375    /**
15376     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15377     * loop. Waits for the specified amount of time.</p>
15378     *
15379     * <p>This method can be invoked from outside of the UI thread
15380     * only when this View is attached to a window.</p>
15381     *
15382     * @param delayMilliseconds the duration in milliseconds to delay the
15383     *         invalidation by
15384     *
15385     * @see #invalidate()
15386     * @see #postInvalidate()
15387     */
15388    public void postInvalidateDelayed(long delayMilliseconds) {
15389        // We try only with the AttachInfo because there's no point in invalidating
15390        // if we are not attached to our window
15391        final AttachInfo attachInfo = mAttachInfo;
15392        if (attachInfo != null) {
15393            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15394        }
15395    }
15396
15397    /**
15398     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15399     * through the event loop. Waits for the specified amount of time.</p>
15400     *
15401     * <p>This method can be invoked from outside of the UI thread
15402     * only when this View is attached to a window.</p>
15403     *
15404     * @param delayMilliseconds the duration in milliseconds to delay the
15405     *         invalidation by
15406     * @param left The left coordinate of the rectangle to invalidate.
15407     * @param top The top coordinate of the rectangle to invalidate.
15408     * @param right The right coordinate of the rectangle to invalidate.
15409     * @param bottom The bottom coordinate of the rectangle to invalidate.
15410     *
15411     * @see #invalidate(int, int, int, int)
15412     * @see #invalidate(Rect)
15413     * @see #postInvalidate(int, int, int, int)
15414     */
15415    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15416            int right, int bottom) {
15417
15418        // We try only with the AttachInfo because there's no point in invalidating
15419        // if we are not attached to our window
15420        final AttachInfo attachInfo = mAttachInfo;
15421        if (attachInfo != null) {
15422            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15423            info.target = this;
15424            info.left = left;
15425            info.top = top;
15426            info.right = right;
15427            info.bottom = bottom;
15428
15429            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15430        }
15431    }
15432
15433    /**
15434     * <p>Cause an invalidate to happen on the next animation time step, typically the
15435     * next display frame.</p>
15436     *
15437     * <p>This method can be invoked from outside of the UI thread
15438     * only when this View is attached to a window.</p>
15439     *
15440     * @see #invalidate()
15441     */
15442    public void postInvalidateOnAnimation() {
15443        // We try only with the AttachInfo because there's no point in invalidating
15444        // if we are not attached to our window
15445        final AttachInfo attachInfo = mAttachInfo;
15446        if (attachInfo != null) {
15447            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15448        }
15449    }
15450
15451    /**
15452     * <p>Cause an invalidate of the specified area to happen on the next animation
15453     * time step, typically the next display frame.</p>
15454     *
15455     * <p>This method can be invoked from outside of the UI thread
15456     * only when this View is attached to a window.</p>
15457     *
15458     * @param left The left coordinate of the rectangle to invalidate.
15459     * @param top The top coordinate of the rectangle to invalidate.
15460     * @param right The right coordinate of the rectangle to invalidate.
15461     * @param bottom The bottom coordinate of the rectangle to invalidate.
15462     *
15463     * @see #invalidate(int, int, int, int)
15464     * @see #invalidate(Rect)
15465     */
15466    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15467        // We try only with the AttachInfo because there's no point in invalidating
15468        // if we are not attached to our window
15469        final AttachInfo attachInfo = mAttachInfo;
15470        if (attachInfo != null) {
15471            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15472            info.target = this;
15473            info.left = left;
15474            info.top = top;
15475            info.right = right;
15476            info.bottom = bottom;
15477
15478            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15479        }
15480    }
15481
15482    /**
15483     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15484     * This event is sent at most once every
15485     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15486     */
15487    private void postSendViewScrolledAccessibilityEventCallback() {
15488        if (mSendViewScrolledAccessibilityEvent == null) {
15489            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15490        }
15491        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15492            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15493            postDelayed(mSendViewScrolledAccessibilityEvent,
15494                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15495        }
15496    }
15497
15498    /**
15499     * Called by a parent to request that a child update its values for mScrollX
15500     * and mScrollY if necessary. This will typically be done if the child is
15501     * animating a scroll using a {@link android.widget.Scroller Scroller}
15502     * object.
15503     */
15504    public void computeScroll() {
15505    }
15506
15507    /**
15508     * <p>Indicate whether the horizontal edges are faded when the view is
15509     * scrolled horizontally.</p>
15510     *
15511     * @return true if the horizontal edges should are faded on scroll, false
15512     *         otherwise
15513     *
15514     * @see #setHorizontalFadingEdgeEnabled(boolean)
15515     *
15516     * @attr ref android.R.styleable#View_requiresFadingEdge
15517     */
15518    public boolean isHorizontalFadingEdgeEnabled() {
15519        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15520    }
15521
15522    /**
15523     * <p>Define whether the horizontal edges should be faded when this view
15524     * is scrolled horizontally.</p>
15525     *
15526     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15527     *                                    be faded when the view is scrolled
15528     *                                    horizontally
15529     *
15530     * @see #isHorizontalFadingEdgeEnabled()
15531     *
15532     * @attr ref android.R.styleable#View_requiresFadingEdge
15533     */
15534    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15535        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15536            if (horizontalFadingEdgeEnabled) {
15537                initScrollCache();
15538            }
15539
15540            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15541        }
15542    }
15543
15544    /**
15545     * <p>Indicate whether the vertical edges are faded when the view is
15546     * scrolled horizontally.</p>
15547     *
15548     * @return true if the vertical edges should are faded on scroll, false
15549     *         otherwise
15550     *
15551     * @see #setVerticalFadingEdgeEnabled(boolean)
15552     *
15553     * @attr ref android.R.styleable#View_requiresFadingEdge
15554     */
15555    public boolean isVerticalFadingEdgeEnabled() {
15556        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15557    }
15558
15559    /**
15560     * <p>Define whether the vertical edges should be faded when this view
15561     * is scrolled vertically.</p>
15562     *
15563     * @param verticalFadingEdgeEnabled true if the vertical edges should
15564     *                                  be faded when the view is scrolled
15565     *                                  vertically
15566     *
15567     * @see #isVerticalFadingEdgeEnabled()
15568     *
15569     * @attr ref android.R.styleable#View_requiresFadingEdge
15570     */
15571    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15572        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15573            if (verticalFadingEdgeEnabled) {
15574                initScrollCache();
15575            }
15576
15577            mViewFlags ^= FADING_EDGE_VERTICAL;
15578        }
15579    }
15580
15581    /**
15582     * Returns the strength, or intensity, of the top faded edge. The strength is
15583     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15584     * returns 0.0 or 1.0 but no value in between.
15585     *
15586     * Subclasses should override this method to provide a smoother fade transition
15587     * when scrolling occurs.
15588     *
15589     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15590     */
15591    protected float getTopFadingEdgeStrength() {
15592        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15593    }
15594
15595    /**
15596     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15597     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15598     * returns 0.0 or 1.0 but no value in between.
15599     *
15600     * Subclasses should override this method to provide a smoother fade transition
15601     * when scrolling occurs.
15602     *
15603     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15604     */
15605    protected float getBottomFadingEdgeStrength() {
15606        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15607                computeVerticalScrollRange() ? 1.0f : 0.0f;
15608    }
15609
15610    /**
15611     * Returns the strength, or intensity, of the left faded edge. The strength is
15612     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15613     * returns 0.0 or 1.0 but no value in between.
15614     *
15615     * Subclasses should override this method to provide a smoother fade transition
15616     * when scrolling occurs.
15617     *
15618     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15619     */
15620    protected float getLeftFadingEdgeStrength() {
15621        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15622    }
15623
15624    /**
15625     * Returns the strength, or intensity, of the right faded edge. The strength is
15626     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15627     * returns 0.0 or 1.0 but no value in between.
15628     *
15629     * Subclasses should override this method to provide a smoother fade transition
15630     * when scrolling occurs.
15631     *
15632     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15633     */
15634    protected float getRightFadingEdgeStrength() {
15635        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15636                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15637    }
15638
15639    /**
15640     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15641     * scrollbar is not drawn by default.</p>
15642     *
15643     * @return true if the horizontal scrollbar should be painted, false
15644     *         otherwise
15645     *
15646     * @see #setHorizontalScrollBarEnabled(boolean)
15647     */
15648    public boolean isHorizontalScrollBarEnabled() {
15649        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15650    }
15651
15652    /**
15653     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15654     * scrollbar is not drawn by default.</p>
15655     *
15656     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15657     *                                   be painted
15658     *
15659     * @see #isHorizontalScrollBarEnabled()
15660     */
15661    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15662        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15663            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15664            computeOpaqueFlags();
15665            resolvePadding();
15666        }
15667    }
15668
15669    /**
15670     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15671     * scrollbar is not drawn by default.</p>
15672     *
15673     * @return true if the vertical scrollbar should be painted, false
15674     *         otherwise
15675     *
15676     * @see #setVerticalScrollBarEnabled(boolean)
15677     */
15678    public boolean isVerticalScrollBarEnabled() {
15679        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15680    }
15681
15682    /**
15683     * <p>Define whether the vertical scrollbar should be drawn or not. The
15684     * scrollbar is not drawn by default.</p>
15685     *
15686     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15687     *                                 be painted
15688     *
15689     * @see #isVerticalScrollBarEnabled()
15690     */
15691    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15692        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15693            mViewFlags ^= SCROLLBARS_VERTICAL;
15694            computeOpaqueFlags();
15695            resolvePadding();
15696        }
15697    }
15698
15699    /**
15700     * @hide
15701     */
15702    protected void recomputePadding() {
15703        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15704    }
15705
15706    /**
15707     * Define whether scrollbars will fade when the view is not scrolling.
15708     *
15709     * @param fadeScrollbars whether to enable fading
15710     *
15711     * @attr ref android.R.styleable#View_fadeScrollbars
15712     */
15713    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15714        initScrollCache();
15715        final ScrollabilityCache scrollabilityCache = mScrollCache;
15716        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15717        if (fadeScrollbars) {
15718            scrollabilityCache.state = ScrollabilityCache.OFF;
15719        } else {
15720            scrollabilityCache.state = ScrollabilityCache.ON;
15721        }
15722    }
15723
15724    /**
15725     *
15726     * Returns true if scrollbars will fade when this view is not scrolling
15727     *
15728     * @return true if scrollbar fading is enabled
15729     *
15730     * @attr ref android.R.styleable#View_fadeScrollbars
15731     */
15732    public boolean isScrollbarFadingEnabled() {
15733        return mScrollCache != null && mScrollCache.fadeScrollBars;
15734    }
15735
15736    /**
15737     *
15738     * Returns the delay before scrollbars fade.
15739     *
15740     * @return the delay before scrollbars fade
15741     *
15742     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15743     */
15744    public int getScrollBarDefaultDelayBeforeFade() {
15745        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15746                mScrollCache.scrollBarDefaultDelayBeforeFade;
15747    }
15748
15749    /**
15750     * Define the delay before scrollbars fade.
15751     *
15752     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15753     *
15754     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15755     */
15756    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15757        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15758    }
15759
15760    /**
15761     *
15762     * Returns the scrollbar fade duration.
15763     *
15764     * @return the scrollbar fade duration, in milliseconds
15765     *
15766     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15767     */
15768    public int getScrollBarFadeDuration() {
15769        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15770                mScrollCache.scrollBarFadeDuration;
15771    }
15772
15773    /**
15774     * Define the scrollbar fade duration.
15775     *
15776     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15777     *
15778     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15779     */
15780    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15781        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15782    }
15783
15784    /**
15785     *
15786     * Returns the scrollbar size.
15787     *
15788     * @return the scrollbar size
15789     *
15790     * @attr ref android.R.styleable#View_scrollbarSize
15791     */
15792    public int getScrollBarSize() {
15793        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15794                mScrollCache.scrollBarSize;
15795    }
15796
15797    /**
15798     * Define the scrollbar size.
15799     *
15800     * @param scrollBarSize - the scrollbar size
15801     *
15802     * @attr ref android.R.styleable#View_scrollbarSize
15803     */
15804    public void setScrollBarSize(int scrollBarSize) {
15805        getScrollCache().scrollBarSize = scrollBarSize;
15806    }
15807
15808    /**
15809     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15810     * inset. When inset, they add to the padding of the view. And the scrollbars
15811     * can be drawn inside the padding area or on the edge of the view. For example,
15812     * if a view has a background drawable and you want to draw the scrollbars
15813     * inside the padding specified by the drawable, you can use
15814     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15815     * appear at the edge of the view, ignoring the padding, then you can use
15816     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15817     * @param style the style of the scrollbars. Should be one of
15818     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15819     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15820     * @see #SCROLLBARS_INSIDE_OVERLAY
15821     * @see #SCROLLBARS_INSIDE_INSET
15822     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15823     * @see #SCROLLBARS_OUTSIDE_INSET
15824     *
15825     * @attr ref android.R.styleable#View_scrollbarStyle
15826     */
15827    public void setScrollBarStyle(@ScrollBarStyle int style) {
15828        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15829            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15830            computeOpaqueFlags();
15831            resolvePadding();
15832        }
15833    }
15834
15835    /**
15836     * <p>Returns the current scrollbar style.</p>
15837     * @return the current scrollbar style
15838     * @see #SCROLLBARS_INSIDE_OVERLAY
15839     * @see #SCROLLBARS_INSIDE_INSET
15840     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15841     * @see #SCROLLBARS_OUTSIDE_INSET
15842     *
15843     * @attr ref android.R.styleable#View_scrollbarStyle
15844     */
15845    @ViewDebug.ExportedProperty(mapping = {
15846            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15847            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15848            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15849            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15850    })
15851    @ScrollBarStyle
15852    public int getScrollBarStyle() {
15853        return mViewFlags & SCROLLBARS_STYLE_MASK;
15854    }
15855
15856    /**
15857     * <p>Compute the horizontal range that the horizontal scrollbar
15858     * represents.</p>
15859     *
15860     * <p>The range is expressed in arbitrary units that must be the same as the
15861     * units used by {@link #computeHorizontalScrollExtent()} and
15862     * {@link #computeHorizontalScrollOffset()}.</p>
15863     *
15864     * <p>The default range is the drawing width of this view.</p>
15865     *
15866     * @return the total horizontal range represented by the horizontal
15867     *         scrollbar
15868     *
15869     * @see #computeHorizontalScrollExtent()
15870     * @see #computeHorizontalScrollOffset()
15871     * @see android.widget.ScrollBarDrawable
15872     */
15873    protected int computeHorizontalScrollRange() {
15874        return getWidth();
15875    }
15876
15877    /**
15878     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15879     * within the horizontal range. This value is used to compute the position
15880     * of the thumb within the scrollbar's track.</p>
15881     *
15882     * <p>The range is expressed in arbitrary units that must be the same as the
15883     * units used by {@link #computeHorizontalScrollRange()} and
15884     * {@link #computeHorizontalScrollExtent()}.</p>
15885     *
15886     * <p>The default offset is the scroll offset of this view.</p>
15887     *
15888     * @return the horizontal offset of the scrollbar's thumb
15889     *
15890     * @see #computeHorizontalScrollRange()
15891     * @see #computeHorizontalScrollExtent()
15892     * @see android.widget.ScrollBarDrawable
15893     */
15894    protected int computeHorizontalScrollOffset() {
15895        return mScrollX;
15896    }
15897
15898    /**
15899     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15900     * within the horizontal range. This value is used to compute the length
15901     * of the thumb within the scrollbar's track.</p>
15902     *
15903     * <p>The range is expressed in arbitrary units that must be the same as the
15904     * units used by {@link #computeHorizontalScrollRange()} and
15905     * {@link #computeHorizontalScrollOffset()}.</p>
15906     *
15907     * <p>The default extent is the drawing width of this view.</p>
15908     *
15909     * @return the horizontal extent of the scrollbar's thumb
15910     *
15911     * @see #computeHorizontalScrollRange()
15912     * @see #computeHorizontalScrollOffset()
15913     * @see android.widget.ScrollBarDrawable
15914     */
15915    protected int computeHorizontalScrollExtent() {
15916        return getWidth();
15917    }
15918
15919    /**
15920     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15921     *
15922     * <p>The range is expressed in arbitrary units that must be the same as the
15923     * units used by {@link #computeVerticalScrollExtent()} and
15924     * {@link #computeVerticalScrollOffset()}.</p>
15925     *
15926     * @return the total vertical range represented by the vertical scrollbar
15927     *
15928     * <p>The default range is the drawing height of this view.</p>
15929     *
15930     * @see #computeVerticalScrollExtent()
15931     * @see #computeVerticalScrollOffset()
15932     * @see android.widget.ScrollBarDrawable
15933     */
15934    protected int computeVerticalScrollRange() {
15935        return getHeight();
15936    }
15937
15938    /**
15939     * <p>Compute the vertical offset of the vertical scrollbar's thumb
15940     * within the horizontal range. This value is used to compute the position
15941     * of the thumb within the scrollbar's track.</p>
15942     *
15943     * <p>The range is expressed in arbitrary units that must be the same as the
15944     * units used by {@link #computeVerticalScrollRange()} and
15945     * {@link #computeVerticalScrollExtent()}.</p>
15946     *
15947     * <p>The default offset is the scroll offset of this view.</p>
15948     *
15949     * @return the vertical offset of the scrollbar's thumb
15950     *
15951     * @see #computeVerticalScrollRange()
15952     * @see #computeVerticalScrollExtent()
15953     * @see android.widget.ScrollBarDrawable
15954     */
15955    protected int computeVerticalScrollOffset() {
15956        return mScrollY;
15957    }
15958
15959    /**
15960     * <p>Compute the vertical extent of the vertical scrollbar's thumb
15961     * within the vertical range. This value is used to compute the length
15962     * of the thumb within the scrollbar's track.</p>
15963     *
15964     * <p>The range is expressed in arbitrary units that must be the same as the
15965     * units used by {@link #computeVerticalScrollRange()} and
15966     * {@link #computeVerticalScrollOffset()}.</p>
15967     *
15968     * <p>The default extent is the drawing height of this view.</p>
15969     *
15970     * @return the vertical extent of the scrollbar's thumb
15971     *
15972     * @see #computeVerticalScrollRange()
15973     * @see #computeVerticalScrollOffset()
15974     * @see android.widget.ScrollBarDrawable
15975     */
15976    protected int computeVerticalScrollExtent() {
15977        return getHeight();
15978    }
15979
15980    /**
15981     * Check if this view can be scrolled horizontally in a certain direction.
15982     *
15983     * @param direction Negative to check scrolling left, positive to check scrolling right.
15984     * @return true if this view can be scrolled in the specified direction, false otherwise.
15985     */
15986    public boolean canScrollHorizontally(int direction) {
15987        final int offset = computeHorizontalScrollOffset();
15988        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
15989        if (range == 0) return false;
15990        if (direction < 0) {
15991            return offset > 0;
15992        } else {
15993            return offset < range - 1;
15994        }
15995    }
15996
15997    /**
15998     * Check if this view can be scrolled vertically in a certain direction.
15999     *
16000     * @param direction Negative to check scrolling up, positive to check scrolling down.
16001     * @return true if this view can be scrolled in the specified direction, false otherwise.
16002     */
16003    public boolean canScrollVertically(int direction) {
16004        final int offset = computeVerticalScrollOffset();
16005        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16006        if (range == 0) return false;
16007        if (direction < 0) {
16008            return offset > 0;
16009        } else {
16010            return offset < range - 1;
16011        }
16012    }
16013
16014    void getScrollIndicatorBounds(@NonNull Rect out) {
16015        out.left = mScrollX;
16016        out.right = mScrollX + mRight - mLeft;
16017        out.top = mScrollY;
16018        out.bottom = mScrollY + mBottom - mTop;
16019    }
16020
16021    private void onDrawScrollIndicators(Canvas c) {
16022        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16023            // No scroll indicators enabled.
16024            return;
16025        }
16026
16027        final Drawable dr = mScrollIndicatorDrawable;
16028        if (dr == null) {
16029            // Scroll indicators aren't supported here.
16030            return;
16031        }
16032
16033        final int h = dr.getIntrinsicHeight();
16034        final int w = dr.getIntrinsicWidth();
16035        final Rect rect = mAttachInfo.mTmpInvalRect;
16036        getScrollIndicatorBounds(rect);
16037
16038        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16039            final boolean canScrollUp = canScrollVertically(-1);
16040            if (canScrollUp) {
16041                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16042                dr.draw(c);
16043            }
16044        }
16045
16046        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16047            final boolean canScrollDown = canScrollVertically(1);
16048            if (canScrollDown) {
16049                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16050                dr.draw(c);
16051            }
16052        }
16053
16054        final int leftRtl;
16055        final int rightRtl;
16056        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16057            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16058            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16059        } else {
16060            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16061            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16062        }
16063
16064        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16065        if ((mPrivateFlags3 & leftMask) != 0) {
16066            final boolean canScrollLeft = canScrollHorizontally(-1);
16067            if (canScrollLeft) {
16068                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16069                dr.draw(c);
16070            }
16071        }
16072
16073        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16074        if ((mPrivateFlags3 & rightMask) != 0) {
16075            final boolean canScrollRight = canScrollHorizontally(1);
16076            if (canScrollRight) {
16077                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16078                dr.draw(c);
16079            }
16080        }
16081    }
16082
16083    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16084            @Nullable Rect touchBounds) {
16085        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16086        if (bounds == null) {
16087            return;
16088        }
16089        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16090        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16091                && !isVerticalScrollBarHidden();
16092        final int size = getHorizontalScrollbarHeight();
16093        final int verticalScrollBarGap = drawVerticalScrollBar ?
16094                getVerticalScrollbarWidth() : 0;
16095        final int width = mRight - mLeft;
16096        final int height = mBottom - mTop;
16097        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16098        bounds.left = mScrollX + (mPaddingLeft & inside);
16099        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16100        bounds.bottom = bounds.top + size;
16101
16102        if (touchBounds == null) {
16103            return;
16104        }
16105        if (touchBounds != bounds) {
16106            touchBounds.set(bounds);
16107        }
16108        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16109        if (touchBounds.height() < minTouchTarget) {
16110            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16111            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16112            touchBounds.top = touchBounds.bottom - minTouchTarget;
16113        }
16114        if (touchBounds.width() < minTouchTarget) {
16115            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16116            touchBounds.left -= adjust;
16117            touchBounds.right = touchBounds.left + minTouchTarget;
16118        }
16119    }
16120
16121    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16122        if (mRoundScrollbarRenderer == null) {
16123            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16124        } else {
16125            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16126        }
16127    }
16128
16129    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16130        final int width = mRight - mLeft;
16131        final int height = mBottom - mTop;
16132        // Do not take padding into account as we always want the scrollbars
16133        // to hug the screen for round wearable devices.
16134        bounds.left = mScrollX;
16135        bounds.top = mScrollY;
16136        bounds.right = bounds.left + width;
16137        bounds.bottom = mScrollY + height;
16138    }
16139
16140    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16141            @Nullable Rect touchBounds) {
16142        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16143        if (bounds == null) {
16144            return;
16145        }
16146        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16147        final int size = getVerticalScrollbarWidth();
16148        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16149        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16150            verticalScrollbarPosition = isLayoutRtl() ?
16151                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16152        }
16153        final int width = mRight - mLeft;
16154        final int height = mBottom - mTop;
16155        switch (verticalScrollbarPosition) {
16156            default:
16157            case SCROLLBAR_POSITION_RIGHT:
16158                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16159                break;
16160            case SCROLLBAR_POSITION_LEFT:
16161                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16162                break;
16163        }
16164        bounds.top = mScrollY + (mPaddingTop & inside);
16165        bounds.right = bounds.left + size;
16166        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16167
16168        if (touchBounds == null) {
16169            return;
16170        }
16171        if (touchBounds != bounds) {
16172            touchBounds.set(bounds);
16173        }
16174        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16175        if (touchBounds.width() < minTouchTarget) {
16176            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16177            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16178                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16179                touchBounds.left = touchBounds.right - minTouchTarget;
16180            } else {
16181                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16182                touchBounds.right = touchBounds.left + minTouchTarget;
16183            }
16184        }
16185        if (touchBounds.height() < minTouchTarget) {
16186            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16187            touchBounds.top -= adjust;
16188            touchBounds.bottom = touchBounds.top + minTouchTarget;
16189        }
16190    }
16191
16192    /**
16193     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16194     * scrollbars are painted only if they have been awakened first.</p>
16195     *
16196     * @param canvas the canvas on which to draw the scrollbars
16197     *
16198     * @see #awakenScrollBars(int)
16199     */
16200    protected final void onDrawScrollBars(Canvas canvas) {
16201        // scrollbars are drawn only when the animation is running
16202        final ScrollabilityCache cache = mScrollCache;
16203
16204        if (cache != null) {
16205
16206            int state = cache.state;
16207
16208            if (state == ScrollabilityCache.OFF) {
16209                return;
16210            }
16211
16212            boolean invalidate = false;
16213
16214            if (state == ScrollabilityCache.FADING) {
16215                // We're fading -- get our fade interpolation
16216                if (cache.interpolatorValues == null) {
16217                    cache.interpolatorValues = new float[1];
16218                }
16219
16220                float[] values = cache.interpolatorValues;
16221
16222                // Stops the animation if we're done
16223                if (cache.scrollBarInterpolator.timeToValues(values) ==
16224                        Interpolator.Result.FREEZE_END) {
16225                    cache.state = ScrollabilityCache.OFF;
16226                } else {
16227                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16228                }
16229
16230                // This will make the scroll bars inval themselves after
16231                // drawing. We only want this when we're fading so that
16232                // we prevent excessive redraws
16233                invalidate = true;
16234            } else {
16235                // We're just on -- but we may have been fading before so
16236                // reset alpha
16237                cache.scrollBar.mutate().setAlpha(255);
16238            }
16239
16240            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16241            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16242                    && !isVerticalScrollBarHidden();
16243
16244            // Fork out the scroll bar drawing for round wearable devices.
16245            if (mRoundScrollbarRenderer != null) {
16246                if (drawVerticalScrollBar) {
16247                    final Rect bounds = cache.mScrollBarBounds;
16248                    getVerticalScrollBarBounds(bounds, null);
16249                    mRoundScrollbarRenderer.drawRoundScrollbars(
16250                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16251                    if (invalidate) {
16252                        invalidate();
16253                    }
16254                }
16255                // Do not draw horizontal scroll bars for round wearable devices.
16256            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16257                final ScrollBarDrawable scrollBar = cache.scrollBar;
16258
16259                if (drawHorizontalScrollBar) {
16260                    scrollBar.setParameters(computeHorizontalScrollRange(),
16261                            computeHorizontalScrollOffset(),
16262                            computeHorizontalScrollExtent(), false);
16263                    final Rect bounds = cache.mScrollBarBounds;
16264                    getHorizontalScrollBarBounds(bounds, null);
16265                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16266                            bounds.right, bounds.bottom);
16267                    if (invalidate) {
16268                        invalidate(bounds);
16269                    }
16270                }
16271
16272                if (drawVerticalScrollBar) {
16273                    scrollBar.setParameters(computeVerticalScrollRange(),
16274                            computeVerticalScrollOffset(),
16275                            computeVerticalScrollExtent(), true);
16276                    final Rect bounds = cache.mScrollBarBounds;
16277                    getVerticalScrollBarBounds(bounds, null);
16278                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16279                            bounds.right, bounds.bottom);
16280                    if (invalidate) {
16281                        invalidate(bounds);
16282                    }
16283                }
16284            }
16285        }
16286    }
16287
16288    /**
16289     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16290     * FastScroller is visible.
16291     * @return whether to temporarily hide the vertical scrollbar
16292     * @hide
16293     */
16294    protected boolean isVerticalScrollBarHidden() {
16295        return false;
16296    }
16297
16298    /**
16299     * <p>Draw the horizontal scrollbar if
16300     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16301     *
16302     * @param canvas the canvas on which to draw the scrollbar
16303     * @param scrollBar the scrollbar's drawable
16304     *
16305     * @see #isHorizontalScrollBarEnabled()
16306     * @see #computeHorizontalScrollRange()
16307     * @see #computeHorizontalScrollExtent()
16308     * @see #computeHorizontalScrollOffset()
16309     * @see android.widget.ScrollBarDrawable
16310     * @hide
16311     */
16312    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16313            int l, int t, int r, int b) {
16314        scrollBar.setBounds(l, t, r, b);
16315        scrollBar.draw(canvas);
16316    }
16317
16318    /**
16319     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16320     * returns true.</p>
16321     *
16322     * @param canvas the canvas on which to draw the scrollbar
16323     * @param scrollBar the scrollbar's drawable
16324     *
16325     * @see #isVerticalScrollBarEnabled()
16326     * @see #computeVerticalScrollRange()
16327     * @see #computeVerticalScrollExtent()
16328     * @see #computeVerticalScrollOffset()
16329     * @see android.widget.ScrollBarDrawable
16330     * @hide
16331     */
16332    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16333            int l, int t, int r, int b) {
16334        scrollBar.setBounds(l, t, r, b);
16335        scrollBar.draw(canvas);
16336    }
16337
16338    /**
16339     * Implement this to do your drawing.
16340     *
16341     * @param canvas the canvas on which the background will be drawn
16342     */
16343    protected void onDraw(Canvas canvas) {
16344    }
16345
16346    /*
16347     * Caller is responsible for calling requestLayout if necessary.
16348     * (This allows addViewInLayout to not request a new layout.)
16349     */
16350    void assignParent(ViewParent parent) {
16351        if (mParent == null) {
16352            mParent = parent;
16353        } else if (parent == null) {
16354            mParent = null;
16355        } else {
16356            throw new RuntimeException("view " + this + " being added, but"
16357                    + " it already has a parent");
16358        }
16359    }
16360
16361    /**
16362     * This is called when the view is attached to a window.  At this point it
16363     * has a Surface and will start drawing.  Note that this function is
16364     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16365     * however it may be called any time before the first onDraw -- including
16366     * before or after {@link #onMeasure(int, int)}.
16367     *
16368     * @see #onDetachedFromWindow()
16369     */
16370    @CallSuper
16371    protected void onAttachedToWindow() {
16372        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16373            mParent.requestTransparentRegion(this);
16374        }
16375
16376        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16377
16378        jumpDrawablesToCurrentState();
16379
16380        resetSubtreeAccessibilityStateChanged();
16381
16382        // rebuild, since Outline not maintained while View is detached
16383        rebuildOutline();
16384
16385        if (isFocused()) {
16386            InputMethodManager imm = InputMethodManager.peekInstance();
16387            if (imm != null) {
16388                imm.focusIn(this);
16389            }
16390        }
16391    }
16392
16393    /**
16394     * Resolve all RTL related properties.
16395     *
16396     * @return true if resolution of RTL properties has been done
16397     *
16398     * @hide
16399     */
16400    public boolean resolveRtlPropertiesIfNeeded() {
16401        if (!needRtlPropertiesResolution()) return false;
16402
16403        // Order is important here: LayoutDirection MUST be resolved first
16404        if (!isLayoutDirectionResolved()) {
16405            resolveLayoutDirection();
16406            resolveLayoutParams();
16407        }
16408        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16409        if (!isTextDirectionResolved()) {
16410            resolveTextDirection();
16411        }
16412        if (!isTextAlignmentResolved()) {
16413            resolveTextAlignment();
16414        }
16415        // Should resolve Drawables before Padding because we need the layout direction of the
16416        // Drawable to correctly resolve Padding.
16417        if (!areDrawablesResolved()) {
16418            resolveDrawables();
16419        }
16420        if (!isPaddingResolved()) {
16421            resolvePadding();
16422        }
16423        onRtlPropertiesChanged(getLayoutDirection());
16424        return true;
16425    }
16426
16427    /**
16428     * Reset resolution of all RTL related properties.
16429     *
16430     * @hide
16431     */
16432    public void resetRtlProperties() {
16433        resetResolvedLayoutDirection();
16434        resetResolvedTextDirection();
16435        resetResolvedTextAlignment();
16436        resetResolvedPadding();
16437        resetResolvedDrawables();
16438    }
16439
16440    /**
16441     * @see #onScreenStateChanged(int)
16442     */
16443    void dispatchScreenStateChanged(int screenState) {
16444        onScreenStateChanged(screenState);
16445    }
16446
16447    /**
16448     * This method is called whenever the state of the screen this view is
16449     * attached to changes. A state change will usually occurs when the screen
16450     * turns on or off (whether it happens automatically or the user does it
16451     * manually.)
16452     *
16453     * @param screenState The new state of the screen. Can be either
16454     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16455     */
16456    public void onScreenStateChanged(int screenState) {
16457    }
16458
16459    /**
16460     * @see #onMovedToDisplay(int)
16461     */
16462    void dispatchMovedToDisplay(Display display) {
16463        mAttachInfo.mDisplay = display;
16464        mAttachInfo.mDisplayState = display.getState();
16465        onMovedToDisplay(display.getDisplayId());
16466    }
16467
16468    /**
16469     * Called by the system when the hosting activity is moved from one display to another without
16470     * recreation. This means that the activity is declared to handle all changes to configuration
16471     * that happened when it was switched to another display, so it wasn't destroyed and created
16472     * again. This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16473     * applied configuration actually changed.
16474     *
16475     * <p>Use this callback to track changes to the displays if some functionality relies on an
16476     * association with some display properties.
16477     *
16478     * @param displayId The id of the display to which the view was moved.
16479     *
16480     * @see #onConfigurationChanged(Configuration)
16481     */
16482    public void onMovedToDisplay(int displayId) {
16483    }
16484
16485    /**
16486     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16487     */
16488    private boolean hasRtlSupport() {
16489        return mContext.getApplicationInfo().hasRtlSupport();
16490    }
16491
16492    /**
16493     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16494     * RTL not supported)
16495     */
16496    private boolean isRtlCompatibilityMode() {
16497        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16498        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16499    }
16500
16501    /**
16502     * @return true if RTL properties need resolution.
16503     *
16504     */
16505    private boolean needRtlPropertiesResolution() {
16506        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16507    }
16508
16509    /**
16510     * Called when any RTL property (layout direction or text direction or text alignment) has
16511     * been changed.
16512     *
16513     * Subclasses need to override this method to take care of cached information that depends on the
16514     * resolved layout direction, or to inform child views that inherit their layout direction.
16515     *
16516     * The default implementation does nothing.
16517     *
16518     * @param layoutDirection the direction of the layout
16519     *
16520     * @see #LAYOUT_DIRECTION_LTR
16521     * @see #LAYOUT_DIRECTION_RTL
16522     */
16523    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16524    }
16525
16526    /**
16527     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16528     * that the parent directionality can and will be resolved before its children.
16529     *
16530     * @return true if resolution has been done, false otherwise.
16531     *
16532     * @hide
16533     */
16534    public boolean resolveLayoutDirection() {
16535        // Clear any previous layout direction resolution
16536        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16537
16538        if (hasRtlSupport()) {
16539            // Set resolved depending on layout direction
16540            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16541                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16542                case LAYOUT_DIRECTION_INHERIT:
16543                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16544                    // later to get the correct resolved value
16545                    if (!canResolveLayoutDirection()) return false;
16546
16547                    // Parent has not yet resolved, LTR is still the default
16548                    try {
16549                        if (!mParent.isLayoutDirectionResolved()) return false;
16550
16551                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16552                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16553                        }
16554                    } catch (AbstractMethodError e) {
16555                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16556                                " does not fully implement ViewParent", e);
16557                    }
16558                    break;
16559                case LAYOUT_DIRECTION_RTL:
16560                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16561                    break;
16562                case LAYOUT_DIRECTION_LOCALE:
16563                    if((LAYOUT_DIRECTION_RTL ==
16564                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16565                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16566                    }
16567                    break;
16568                default:
16569                    // Nothing to do, LTR by default
16570            }
16571        }
16572
16573        // Set to resolved
16574        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16575        return true;
16576    }
16577
16578    /**
16579     * Check if layout direction resolution can be done.
16580     *
16581     * @return true if layout direction resolution can be done otherwise return false.
16582     */
16583    public boolean canResolveLayoutDirection() {
16584        switch (getRawLayoutDirection()) {
16585            case LAYOUT_DIRECTION_INHERIT:
16586                if (mParent != null) {
16587                    try {
16588                        return mParent.canResolveLayoutDirection();
16589                    } catch (AbstractMethodError e) {
16590                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16591                                " does not fully implement ViewParent", e);
16592                    }
16593                }
16594                return false;
16595
16596            default:
16597                return true;
16598        }
16599    }
16600
16601    /**
16602     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16603     * {@link #onMeasure(int, int)}.
16604     *
16605     * @hide
16606     */
16607    public void resetResolvedLayoutDirection() {
16608        // Reset the current resolved bits
16609        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16610    }
16611
16612    /**
16613     * @return true if the layout direction is inherited.
16614     *
16615     * @hide
16616     */
16617    public boolean isLayoutDirectionInherited() {
16618        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16619    }
16620
16621    /**
16622     * @return true if layout direction has been resolved.
16623     */
16624    public boolean isLayoutDirectionResolved() {
16625        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16626    }
16627
16628    /**
16629     * Return if padding has been resolved
16630     *
16631     * @hide
16632     */
16633    boolean isPaddingResolved() {
16634        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16635    }
16636
16637    /**
16638     * Resolves padding depending on layout direction, if applicable, and
16639     * recomputes internal padding values to adjust for scroll bars.
16640     *
16641     * @hide
16642     */
16643    public void resolvePadding() {
16644        final int resolvedLayoutDirection = getLayoutDirection();
16645
16646        if (!isRtlCompatibilityMode()) {
16647            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16648            // If start / end padding are defined, they will be resolved (hence overriding) to
16649            // left / right or right / left depending on the resolved layout direction.
16650            // If start / end padding are not defined, use the left / right ones.
16651            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16652                Rect padding = sThreadLocal.get();
16653                if (padding == null) {
16654                    padding = new Rect();
16655                    sThreadLocal.set(padding);
16656                }
16657                mBackground.getPadding(padding);
16658                if (!mLeftPaddingDefined) {
16659                    mUserPaddingLeftInitial = padding.left;
16660                }
16661                if (!mRightPaddingDefined) {
16662                    mUserPaddingRightInitial = padding.right;
16663                }
16664            }
16665            switch (resolvedLayoutDirection) {
16666                case LAYOUT_DIRECTION_RTL:
16667                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16668                        mUserPaddingRight = mUserPaddingStart;
16669                    } else {
16670                        mUserPaddingRight = mUserPaddingRightInitial;
16671                    }
16672                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16673                        mUserPaddingLeft = mUserPaddingEnd;
16674                    } else {
16675                        mUserPaddingLeft = mUserPaddingLeftInitial;
16676                    }
16677                    break;
16678                case LAYOUT_DIRECTION_LTR:
16679                default:
16680                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16681                        mUserPaddingLeft = mUserPaddingStart;
16682                    } else {
16683                        mUserPaddingLeft = mUserPaddingLeftInitial;
16684                    }
16685                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16686                        mUserPaddingRight = mUserPaddingEnd;
16687                    } else {
16688                        mUserPaddingRight = mUserPaddingRightInitial;
16689                    }
16690            }
16691
16692            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16693        }
16694
16695        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16696        onRtlPropertiesChanged(resolvedLayoutDirection);
16697
16698        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16699    }
16700
16701    /**
16702     * Reset the resolved layout direction.
16703     *
16704     * @hide
16705     */
16706    public void resetResolvedPadding() {
16707        resetResolvedPaddingInternal();
16708    }
16709
16710    /**
16711     * Used when we only want to reset *this* view's padding and not trigger overrides
16712     * in ViewGroup that reset children too.
16713     */
16714    void resetResolvedPaddingInternal() {
16715        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16716    }
16717
16718    /**
16719     * This is called when the view is detached from a window.  At this point it
16720     * no longer has a surface for drawing.
16721     *
16722     * @see #onAttachedToWindow()
16723     */
16724    @CallSuper
16725    protected void onDetachedFromWindow() {
16726    }
16727
16728    /**
16729     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16730     * after onDetachedFromWindow().
16731     *
16732     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16733     * The super method should be called at the end of the overridden method to ensure
16734     * subclasses are destroyed first
16735     *
16736     * @hide
16737     */
16738    @CallSuper
16739    protected void onDetachedFromWindowInternal() {
16740        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16741        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16742        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16743
16744        removeUnsetPressCallback();
16745        removeLongPressCallback();
16746        removePerformClickCallback();
16747        removeSendViewScrolledAccessibilityEventCallback();
16748        stopNestedScroll();
16749
16750        // Anything that started animating right before detach should already
16751        // be in its final state when re-attached.
16752        jumpDrawablesToCurrentState();
16753
16754        destroyDrawingCache();
16755
16756        cleanupDraw();
16757        mCurrentAnimation = null;
16758
16759        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16760            hideTooltip();
16761        }
16762    }
16763
16764    private void cleanupDraw() {
16765        resetDisplayList();
16766        if (mAttachInfo != null) {
16767            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16768        }
16769    }
16770
16771    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16772    }
16773
16774    /**
16775     * @return The number of times this view has been attached to a window
16776     */
16777    protected int getWindowAttachCount() {
16778        return mWindowAttachCount;
16779    }
16780
16781    /**
16782     * Retrieve a unique token identifying the window this view is attached to.
16783     * @return Return the window's token for use in
16784     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16785     */
16786    public IBinder getWindowToken() {
16787        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16788    }
16789
16790    /**
16791     * Retrieve the {@link WindowId} for the window this view is
16792     * currently attached to.
16793     */
16794    public WindowId getWindowId() {
16795        if (mAttachInfo == null) {
16796            return null;
16797        }
16798        if (mAttachInfo.mWindowId == null) {
16799            try {
16800                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16801                        mAttachInfo.mWindowToken);
16802                mAttachInfo.mWindowId = new WindowId(
16803                        mAttachInfo.mIWindowId);
16804            } catch (RemoteException e) {
16805            }
16806        }
16807        return mAttachInfo.mWindowId;
16808    }
16809
16810    /**
16811     * Retrieve a unique token identifying the top-level "real" window of
16812     * the window that this view is attached to.  That is, this is like
16813     * {@link #getWindowToken}, except if the window this view in is a panel
16814     * window (attached to another containing window), then the token of
16815     * the containing window is returned instead.
16816     *
16817     * @return Returns the associated window token, either
16818     * {@link #getWindowToken()} or the containing window's token.
16819     */
16820    public IBinder getApplicationWindowToken() {
16821        AttachInfo ai = mAttachInfo;
16822        if (ai != null) {
16823            IBinder appWindowToken = ai.mPanelParentWindowToken;
16824            if (appWindowToken == null) {
16825                appWindowToken = ai.mWindowToken;
16826            }
16827            return appWindowToken;
16828        }
16829        return null;
16830    }
16831
16832    /**
16833     * Gets the logical display to which the view's window has been attached.
16834     *
16835     * @return The logical display, or null if the view is not currently attached to a window.
16836     */
16837    public Display getDisplay() {
16838        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16839    }
16840
16841    /**
16842     * Retrieve private session object this view hierarchy is using to
16843     * communicate with the window manager.
16844     * @return the session object to communicate with the window manager
16845     */
16846    /*package*/ IWindowSession getWindowSession() {
16847        return mAttachInfo != null ? mAttachInfo.mSession : null;
16848    }
16849
16850    /**
16851     * Return the visibility value of the least visible component passed.
16852     */
16853    int combineVisibility(int vis1, int vis2) {
16854        // This works because VISIBLE < INVISIBLE < GONE.
16855        return Math.max(vis1, vis2);
16856    }
16857
16858    /**
16859     * @param info the {@link android.view.View.AttachInfo} to associated with
16860     *        this view
16861     */
16862    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16863        mAttachInfo = info;
16864        if (mOverlay != null) {
16865            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16866        }
16867        mWindowAttachCount++;
16868        // We will need to evaluate the drawable state at least once.
16869        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16870        if (mFloatingTreeObserver != null) {
16871            info.mTreeObserver.merge(mFloatingTreeObserver);
16872            mFloatingTreeObserver = null;
16873        }
16874
16875        registerPendingFrameMetricsObservers();
16876
16877        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16878            mAttachInfo.mScrollContainers.add(this);
16879            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16880        }
16881        // Transfer all pending runnables.
16882        if (mRunQueue != null) {
16883            mRunQueue.executeActions(info.mHandler);
16884            mRunQueue = null;
16885        }
16886        performCollectViewAttributes(mAttachInfo, visibility);
16887        onAttachedToWindow();
16888
16889        ListenerInfo li = mListenerInfo;
16890        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16891                li != null ? li.mOnAttachStateChangeListeners : null;
16892        if (listeners != null && listeners.size() > 0) {
16893            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16894            // perform the dispatching. The iterator is a safe guard against listeners that
16895            // could mutate the list by calling the various add/remove methods. This prevents
16896            // the array from being modified while we iterate it.
16897            for (OnAttachStateChangeListener listener : listeners) {
16898                listener.onViewAttachedToWindow(this);
16899            }
16900        }
16901
16902        int vis = info.mWindowVisibility;
16903        if (vis != GONE) {
16904            onWindowVisibilityChanged(vis);
16905            if (isShown()) {
16906                // Calling onVisibilityAggregated directly here since the subtree will also
16907                // receive dispatchAttachedToWindow and this same call
16908                onVisibilityAggregated(vis == VISIBLE);
16909            }
16910        }
16911
16912        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
16913        // As all views in the subtree will already receive dispatchAttachedToWindow
16914        // traversing the subtree again here is not desired.
16915        onVisibilityChanged(this, visibility);
16916
16917        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
16918            // If nobody has evaluated the drawable state yet, then do it now.
16919            refreshDrawableState();
16920        }
16921        needGlobalAttributesUpdate(false);
16922
16923        notifyEnterOrExitForAutoFillIfNeeded(true);
16924    }
16925
16926    void dispatchDetachedFromWindow() {
16927        AttachInfo info = mAttachInfo;
16928        if (info != null) {
16929            int vis = info.mWindowVisibility;
16930            if (vis != GONE) {
16931                onWindowVisibilityChanged(GONE);
16932                if (isShown()) {
16933                    // Invoking onVisibilityAggregated directly here since the subtree
16934                    // will also receive detached from window
16935                    onVisibilityAggregated(false);
16936                }
16937            }
16938        }
16939
16940        onDetachedFromWindow();
16941        onDetachedFromWindowInternal();
16942
16943        InputMethodManager imm = InputMethodManager.peekInstance();
16944        if (imm != null) {
16945            imm.onViewDetachedFromWindow(this);
16946        }
16947
16948        ListenerInfo li = mListenerInfo;
16949        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16950                li != null ? li.mOnAttachStateChangeListeners : null;
16951        if (listeners != null && listeners.size() > 0) {
16952            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16953            // perform the dispatching. The iterator is a safe guard against listeners that
16954            // could mutate the list by calling the various add/remove methods. This prevents
16955            // the array from being modified while we iterate it.
16956            for (OnAttachStateChangeListener listener : listeners) {
16957                listener.onViewDetachedFromWindow(this);
16958            }
16959        }
16960
16961        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
16962            mAttachInfo.mScrollContainers.remove(this);
16963            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
16964        }
16965
16966        mAttachInfo = null;
16967        if (mOverlay != null) {
16968            mOverlay.getOverlayView().dispatchDetachedFromWindow();
16969        }
16970
16971        notifyEnterOrExitForAutoFillIfNeeded(false);
16972    }
16973
16974    /**
16975     * Cancel any deferred high-level input events that were previously posted to the event queue.
16976     *
16977     * <p>Many views post high-level events such as click handlers to the event queue
16978     * to run deferred in order to preserve a desired user experience - clearing visible
16979     * pressed states before executing, etc. This method will abort any events of this nature
16980     * that are currently in flight.</p>
16981     *
16982     * <p>Custom views that generate their own high-level deferred input events should override
16983     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
16984     *
16985     * <p>This will also cancel pending input events for any child views.</p>
16986     *
16987     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
16988     * This will not impact newer events posted after this call that may occur as a result of
16989     * lower-level input events still waiting in the queue. If you are trying to prevent
16990     * double-submitted  events for the duration of some sort of asynchronous transaction
16991     * you should also take other steps to protect against unexpected double inputs e.g. calling
16992     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
16993     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
16994     */
16995    public final void cancelPendingInputEvents() {
16996        dispatchCancelPendingInputEvents();
16997    }
16998
16999    /**
17000     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17001     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17002     */
17003    void dispatchCancelPendingInputEvents() {
17004        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17005        onCancelPendingInputEvents();
17006        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17007            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17008                    " did not call through to super.onCancelPendingInputEvents()");
17009        }
17010    }
17011
17012    /**
17013     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17014     * a parent view.
17015     *
17016     * <p>This method is responsible for removing any pending high-level input events that were
17017     * posted to the event queue to run later. Custom view classes that post their own deferred
17018     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17019     * {@link android.os.Handler} should override this method, call
17020     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17021     * </p>
17022     */
17023    public void onCancelPendingInputEvents() {
17024        removePerformClickCallback();
17025        cancelLongPress();
17026        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17027    }
17028
17029    /**
17030     * Store this view hierarchy's frozen state into the given container.
17031     *
17032     * @param container The SparseArray in which to save the view's state.
17033     *
17034     * @see #restoreHierarchyState(android.util.SparseArray)
17035     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17036     * @see #onSaveInstanceState()
17037     */
17038    public void saveHierarchyState(SparseArray<Parcelable> container) {
17039        dispatchSaveInstanceState(container);
17040    }
17041
17042    /**
17043     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17044     * this view and its children. May be overridden to modify how freezing happens to a
17045     * view's children; for example, some views may want to not store state for their children.
17046     *
17047     * @param container The SparseArray in which to save the view's state.
17048     *
17049     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17050     * @see #saveHierarchyState(android.util.SparseArray)
17051     * @see #onSaveInstanceState()
17052     */
17053    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17054        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17055            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17056            Parcelable state = onSaveInstanceState();
17057            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17058                throw new IllegalStateException(
17059                        "Derived class did not call super.onSaveInstanceState()");
17060            }
17061            if (state != null) {
17062                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17063                // + ": " + state);
17064                container.put(mID, state);
17065            }
17066        }
17067    }
17068
17069    /**
17070     * Hook allowing a view to generate a representation of its internal state
17071     * that can later be used to create a new instance with that same state.
17072     * This state should only contain information that is not persistent or can
17073     * not be reconstructed later. For example, you will never store your
17074     * current position on screen because that will be computed again when a
17075     * new instance of the view is placed in its view hierarchy.
17076     * <p>
17077     * Some examples of things you may store here: the current cursor position
17078     * in a text view (but usually not the text itself since that is stored in a
17079     * content provider or other persistent storage), the currently selected
17080     * item in a list view.
17081     *
17082     * @return Returns a Parcelable object containing the view's current dynamic
17083     *         state, or null if there is nothing interesting to save. The
17084     *         default implementation returns null.
17085     * @see #onRestoreInstanceState(android.os.Parcelable)
17086     * @see #saveHierarchyState(android.util.SparseArray)
17087     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17088     * @see #setSaveEnabled(boolean)
17089     */
17090    @CallSuper
17091    protected Parcelable onSaveInstanceState() {
17092        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17093        if (mStartActivityRequestWho != null) {
17094            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17095            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17096            return state;
17097        }
17098        return BaseSavedState.EMPTY_STATE;
17099    }
17100
17101    /**
17102     * Restore this view hierarchy's frozen state from the given container.
17103     *
17104     * @param container The SparseArray which holds previously frozen states.
17105     *
17106     * @see #saveHierarchyState(android.util.SparseArray)
17107     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17108     * @see #onRestoreInstanceState(android.os.Parcelable)
17109     */
17110    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17111        dispatchRestoreInstanceState(container);
17112    }
17113
17114    /**
17115     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17116     * state for this view and its children. May be overridden to modify how restoring
17117     * happens to a view's children; for example, some views may want to not store state
17118     * for their children.
17119     *
17120     * @param container The SparseArray which holds previously saved state.
17121     *
17122     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17123     * @see #restoreHierarchyState(android.util.SparseArray)
17124     * @see #onRestoreInstanceState(android.os.Parcelable)
17125     */
17126    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17127        if (mID != NO_ID) {
17128            Parcelable state = container.get(mID);
17129            if (state != null) {
17130                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17131                // + ": " + state);
17132                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17133                onRestoreInstanceState(state);
17134                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17135                    throw new IllegalStateException(
17136                            "Derived class did not call super.onRestoreInstanceState()");
17137                }
17138            }
17139        }
17140    }
17141
17142    /**
17143     * Hook allowing a view to re-apply a representation of its internal state that had previously
17144     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17145     * null state.
17146     *
17147     * @param state The frozen state that had previously been returned by
17148     *        {@link #onSaveInstanceState}.
17149     *
17150     * @see #onSaveInstanceState()
17151     * @see #restoreHierarchyState(android.util.SparseArray)
17152     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17153     */
17154    @CallSuper
17155    protected void onRestoreInstanceState(Parcelable state) {
17156        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17157        if (state != null && !(state instanceof AbsSavedState)) {
17158            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17159                    + "received " + state.getClass().toString() + " instead. This usually happens "
17160                    + "when two views of different type have the same id in the same hierarchy. "
17161                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17162                    + "other views do not use the same id.");
17163        }
17164        if (state != null && state instanceof BaseSavedState) {
17165            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
17166        }
17167    }
17168
17169    /**
17170     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17171     *
17172     * @return the drawing start time in milliseconds
17173     */
17174    public long getDrawingTime() {
17175        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17176    }
17177
17178    /**
17179     * <p>Enables or disables the duplication of the parent's state into this view. When
17180     * duplication is enabled, this view gets its drawable state from its parent rather
17181     * than from its own internal properties.</p>
17182     *
17183     * <p>Note: in the current implementation, setting this property to true after the
17184     * view was added to a ViewGroup might have no effect at all. This property should
17185     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17186     *
17187     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17188     * property is enabled, an exception will be thrown.</p>
17189     *
17190     * <p>Note: if the child view uses and updates additional states which are unknown to the
17191     * parent, these states should not be affected by this method.</p>
17192     *
17193     * @param enabled True to enable duplication of the parent's drawable state, false
17194     *                to disable it.
17195     *
17196     * @see #getDrawableState()
17197     * @see #isDuplicateParentStateEnabled()
17198     */
17199    public void setDuplicateParentStateEnabled(boolean enabled) {
17200        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17201    }
17202
17203    /**
17204     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17205     *
17206     * @return True if this view's drawable state is duplicated from the parent,
17207     *         false otherwise
17208     *
17209     * @see #getDrawableState()
17210     * @see #setDuplicateParentStateEnabled(boolean)
17211     */
17212    public boolean isDuplicateParentStateEnabled() {
17213        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17214    }
17215
17216    /**
17217     * <p>Specifies the type of layer backing this view. The layer can be
17218     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17219     * {@link #LAYER_TYPE_HARDWARE}.</p>
17220     *
17221     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17222     * instance that controls how the layer is composed on screen. The following
17223     * properties of the paint are taken into account when composing the layer:</p>
17224     * <ul>
17225     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17226     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17227     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17228     * </ul>
17229     *
17230     * <p>If this view has an alpha value set to < 1.0 by calling
17231     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17232     * by this view's alpha value.</p>
17233     *
17234     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17235     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17236     * for more information on when and how to use layers.</p>
17237     *
17238     * @param layerType The type of layer to use with this view, must be one of
17239     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17240     *        {@link #LAYER_TYPE_HARDWARE}
17241     * @param paint The paint used to compose the layer. This argument is optional
17242     *        and can be null. It is ignored when the layer type is
17243     *        {@link #LAYER_TYPE_NONE}
17244     *
17245     * @see #getLayerType()
17246     * @see #LAYER_TYPE_NONE
17247     * @see #LAYER_TYPE_SOFTWARE
17248     * @see #LAYER_TYPE_HARDWARE
17249     * @see #setAlpha(float)
17250     *
17251     * @attr ref android.R.styleable#View_layerType
17252     */
17253    public void setLayerType(int layerType, @Nullable Paint paint) {
17254        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17255            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17256                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17257        }
17258
17259        boolean typeChanged = mRenderNode.setLayerType(layerType);
17260
17261        if (!typeChanged) {
17262            setLayerPaint(paint);
17263            return;
17264        }
17265
17266        if (layerType != LAYER_TYPE_SOFTWARE) {
17267            // Destroy any previous software drawing cache if present
17268            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17269            // drawing cache created in View#draw when drawing to a SW canvas.
17270            destroyDrawingCache();
17271        }
17272
17273        mLayerType = layerType;
17274        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17275        mRenderNode.setLayerPaint(mLayerPaint);
17276
17277        // draw() behaves differently if we are on a layer, so we need to
17278        // invalidate() here
17279        invalidateParentCaches();
17280        invalidate(true);
17281    }
17282
17283    /**
17284     * Updates the {@link Paint} object used with the current layer (used only if the current
17285     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17286     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17287     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17288     * ensure that the view gets redrawn immediately.
17289     *
17290     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17291     * instance that controls how the layer is composed on screen. The following
17292     * properties of the paint are taken into account when composing the layer:</p>
17293     * <ul>
17294     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17295     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17296     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17297     * </ul>
17298     *
17299     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17300     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17301     *
17302     * @param paint The paint used to compose the layer. This argument is optional
17303     *        and can be null. It is ignored when the layer type is
17304     *        {@link #LAYER_TYPE_NONE}
17305     *
17306     * @see #setLayerType(int, android.graphics.Paint)
17307     */
17308    public void setLayerPaint(@Nullable Paint paint) {
17309        int layerType = getLayerType();
17310        if (layerType != LAYER_TYPE_NONE) {
17311            mLayerPaint = paint;
17312            if (layerType == LAYER_TYPE_HARDWARE) {
17313                if (mRenderNode.setLayerPaint(paint)) {
17314                    invalidateViewProperty(false, false);
17315                }
17316            } else {
17317                invalidate();
17318            }
17319        }
17320    }
17321
17322    /**
17323     * Indicates what type of layer is currently associated with this view. By default
17324     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17325     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17326     * for more information on the different types of layers.
17327     *
17328     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17329     *         {@link #LAYER_TYPE_HARDWARE}
17330     *
17331     * @see #setLayerType(int, android.graphics.Paint)
17332     * @see #buildLayer()
17333     * @see #LAYER_TYPE_NONE
17334     * @see #LAYER_TYPE_SOFTWARE
17335     * @see #LAYER_TYPE_HARDWARE
17336     */
17337    public int getLayerType() {
17338        return mLayerType;
17339    }
17340
17341    /**
17342     * Forces this view's layer to be created and this view to be rendered
17343     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17344     * invoking this method will have no effect.
17345     *
17346     * This method can for instance be used to render a view into its layer before
17347     * starting an animation. If this view is complex, rendering into the layer
17348     * before starting the animation will avoid skipping frames.
17349     *
17350     * @throws IllegalStateException If this view is not attached to a window
17351     *
17352     * @see #setLayerType(int, android.graphics.Paint)
17353     */
17354    public void buildLayer() {
17355        if (mLayerType == LAYER_TYPE_NONE) return;
17356
17357        final AttachInfo attachInfo = mAttachInfo;
17358        if (attachInfo == null) {
17359            throw new IllegalStateException("This view must be attached to a window first");
17360        }
17361
17362        if (getWidth() == 0 || getHeight() == 0) {
17363            return;
17364        }
17365
17366        switch (mLayerType) {
17367            case LAYER_TYPE_HARDWARE:
17368                updateDisplayListIfDirty();
17369                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17370                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17371                }
17372                break;
17373            case LAYER_TYPE_SOFTWARE:
17374                buildDrawingCache(true);
17375                break;
17376        }
17377    }
17378
17379    /**
17380     * Destroys all hardware rendering resources. This method is invoked
17381     * when the system needs to reclaim resources. Upon execution of this
17382     * method, you should free any OpenGL resources created by the view.
17383     *
17384     * Note: you <strong>must</strong> call
17385     * <code>super.destroyHardwareResources()</code> when overriding
17386     * this method.
17387     *
17388     * @hide
17389     */
17390    @CallSuper
17391    protected void destroyHardwareResources() {
17392        if (mOverlay != null) {
17393            mOverlay.getOverlayView().destroyHardwareResources();
17394        }
17395        if (mGhostView != null) {
17396            mGhostView.destroyHardwareResources();
17397        }
17398    }
17399
17400    /**
17401     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17402     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17403     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17404     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17405     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17406     * null.</p>
17407     *
17408     * <p>Enabling the drawing cache is similar to
17409     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17410     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17411     * drawing cache has no effect on rendering because the system uses a different mechanism
17412     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17413     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17414     * for information on how to enable software and hardware layers.</p>
17415     *
17416     * <p>This API can be used to manually generate
17417     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17418     * {@link #getDrawingCache()}.</p>
17419     *
17420     * @param enabled true to enable the drawing cache, false otherwise
17421     *
17422     * @see #isDrawingCacheEnabled()
17423     * @see #getDrawingCache()
17424     * @see #buildDrawingCache()
17425     * @see #setLayerType(int, android.graphics.Paint)
17426     */
17427    public void setDrawingCacheEnabled(boolean enabled) {
17428        mCachingFailed = false;
17429        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17430    }
17431
17432    /**
17433     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17434     *
17435     * @return true if the drawing cache is enabled
17436     *
17437     * @see #setDrawingCacheEnabled(boolean)
17438     * @see #getDrawingCache()
17439     */
17440    @ViewDebug.ExportedProperty(category = "drawing")
17441    public boolean isDrawingCacheEnabled() {
17442        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17443    }
17444
17445    /**
17446     * Debugging utility which recursively outputs the dirty state of a view and its
17447     * descendants.
17448     *
17449     * @hide
17450     */
17451    @SuppressWarnings({"UnusedDeclaration"})
17452    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17453        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17454                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17455                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17456                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17457        if (clear) {
17458            mPrivateFlags &= clearMask;
17459        }
17460        if (this instanceof ViewGroup) {
17461            ViewGroup parent = (ViewGroup) this;
17462            final int count = parent.getChildCount();
17463            for (int i = 0; i < count; i++) {
17464                final View child = parent.getChildAt(i);
17465                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17466            }
17467        }
17468    }
17469
17470    /**
17471     * This method is used by ViewGroup to cause its children to restore or recreate their
17472     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17473     * to recreate its own display list, which would happen if it went through the normal
17474     * draw/dispatchDraw mechanisms.
17475     *
17476     * @hide
17477     */
17478    protected void dispatchGetDisplayList() {}
17479
17480    /**
17481     * A view that is not attached or hardware accelerated cannot create a display list.
17482     * This method checks these conditions and returns the appropriate result.
17483     *
17484     * @return true if view has the ability to create a display list, false otherwise.
17485     *
17486     * @hide
17487     */
17488    public boolean canHaveDisplayList() {
17489        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17490    }
17491
17492    /**
17493     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17494     * @hide
17495     */
17496    @NonNull
17497    public RenderNode updateDisplayListIfDirty() {
17498        final RenderNode renderNode = mRenderNode;
17499        if (!canHaveDisplayList()) {
17500            // can't populate RenderNode, don't try
17501            return renderNode;
17502        }
17503
17504        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17505                || !renderNode.isValid()
17506                || (mRecreateDisplayList)) {
17507            // Don't need to recreate the display list, just need to tell our
17508            // children to restore/recreate theirs
17509            if (renderNode.isValid()
17510                    && !mRecreateDisplayList) {
17511                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17512                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17513                dispatchGetDisplayList();
17514
17515                return renderNode; // no work needed
17516            }
17517
17518            // If we got here, we're recreating it. Mark it as such to ensure that
17519            // we copy in child display lists into ours in drawChild()
17520            mRecreateDisplayList = true;
17521
17522            int width = mRight - mLeft;
17523            int height = mBottom - mTop;
17524            int layerType = getLayerType();
17525
17526            final DisplayListCanvas canvas = renderNode.start(width, height);
17527            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17528
17529            try {
17530                if (layerType == LAYER_TYPE_SOFTWARE) {
17531                    buildDrawingCache(true);
17532                    Bitmap cache = getDrawingCache(true);
17533                    if (cache != null) {
17534                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17535                    }
17536                } else {
17537                    computeScroll();
17538
17539                    canvas.translate(-mScrollX, -mScrollY);
17540                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17541                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17542
17543                    // Fast path for layouts with no backgrounds
17544                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17545                        dispatchDraw(canvas);
17546                        if (mOverlay != null && !mOverlay.isEmpty()) {
17547                            mOverlay.getOverlayView().draw(canvas);
17548                        }
17549                        if (debugDraw()) {
17550                            debugDrawFocus(canvas);
17551                        }
17552                    } else {
17553                        draw(canvas);
17554                    }
17555                }
17556            } finally {
17557                renderNode.end(canvas);
17558                setDisplayListProperties(renderNode);
17559            }
17560        } else {
17561            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17562            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17563        }
17564        return renderNode;
17565    }
17566
17567    private void resetDisplayList() {
17568        mRenderNode.discardDisplayList();
17569        if (mBackgroundRenderNode != null) {
17570            mBackgroundRenderNode.discardDisplayList();
17571        }
17572    }
17573
17574    /**
17575     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17576     *
17577     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17578     *
17579     * @see #getDrawingCache(boolean)
17580     */
17581    public Bitmap getDrawingCache() {
17582        return getDrawingCache(false);
17583    }
17584
17585    /**
17586     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17587     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17588     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17589     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17590     * request the drawing cache by calling this method and draw it on screen if the
17591     * returned bitmap is not null.</p>
17592     *
17593     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17594     * this method will create a bitmap of the same size as this view. Because this bitmap
17595     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17596     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17597     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17598     * size than the view. This implies that your application must be able to handle this
17599     * size.</p>
17600     *
17601     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17602     *        the current density of the screen when the application is in compatibility
17603     *        mode.
17604     *
17605     * @return A bitmap representing this view or null if cache is disabled.
17606     *
17607     * @see #setDrawingCacheEnabled(boolean)
17608     * @see #isDrawingCacheEnabled()
17609     * @see #buildDrawingCache(boolean)
17610     * @see #destroyDrawingCache()
17611     */
17612    public Bitmap getDrawingCache(boolean autoScale) {
17613        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17614            return null;
17615        }
17616        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17617            buildDrawingCache(autoScale);
17618        }
17619        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17620    }
17621
17622    /**
17623     * <p>Frees the resources used by the drawing cache. If you call
17624     * {@link #buildDrawingCache()} manually without calling
17625     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17626     * should cleanup the cache with this method afterwards.</p>
17627     *
17628     * @see #setDrawingCacheEnabled(boolean)
17629     * @see #buildDrawingCache()
17630     * @see #getDrawingCache()
17631     */
17632    public void destroyDrawingCache() {
17633        if (mDrawingCache != null) {
17634            mDrawingCache.recycle();
17635            mDrawingCache = null;
17636        }
17637        if (mUnscaledDrawingCache != null) {
17638            mUnscaledDrawingCache.recycle();
17639            mUnscaledDrawingCache = null;
17640        }
17641    }
17642
17643    /**
17644     * Setting a solid background color for the drawing cache's bitmaps will improve
17645     * performance and memory usage. Note, though that this should only be used if this
17646     * view will always be drawn on top of a solid color.
17647     *
17648     * @param color The background color to use for the drawing cache's bitmap
17649     *
17650     * @see #setDrawingCacheEnabled(boolean)
17651     * @see #buildDrawingCache()
17652     * @see #getDrawingCache()
17653     */
17654    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17655        if (color != mDrawingCacheBackgroundColor) {
17656            mDrawingCacheBackgroundColor = color;
17657            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17658        }
17659    }
17660
17661    /**
17662     * @see #setDrawingCacheBackgroundColor(int)
17663     *
17664     * @return The background color to used for the drawing cache's bitmap
17665     */
17666    @ColorInt
17667    public int getDrawingCacheBackgroundColor() {
17668        return mDrawingCacheBackgroundColor;
17669    }
17670
17671    /**
17672     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17673     *
17674     * @see #buildDrawingCache(boolean)
17675     */
17676    public void buildDrawingCache() {
17677        buildDrawingCache(false);
17678    }
17679
17680    /**
17681     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17682     *
17683     * <p>If you call {@link #buildDrawingCache()} manually without calling
17684     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17685     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17686     *
17687     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17688     * this method will create a bitmap of the same size as this view. Because this bitmap
17689     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17690     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17691     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17692     * size than the view. This implies that your application must be able to handle this
17693     * size.</p>
17694     *
17695     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17696     * you do not need the drawing cache bitmap, calling this method will increase memory
17697     * usage and cause the view to be rendered in software once, thus negatively impacting
17698     * performance.</p>
17699     *
17700     * @see #getDrawingCache()
17701     * @see #destroyDrawingCache()
17702     */
17703    public void buildDrawingCache(boolean autoScale) {
17704        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17705                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17706            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17707                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17708                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17709            }
17710            try {
17711                buildDrawingCacheImpl(autoScale);
17712            } finally {
17713                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17714            }
17715        }
17716    }
17717
17718    /**
17719     * private, internal implementation of buildDrawingCache, used to enable tracing
17720     */
17721    private void buildDrawingCacheImpl(boolean autoScale) {
17722        mCachingFailed = false;
17723
17724        int width = mRight - mLeft;
17725        int height = mBottom - mTop;
17726
17727        final AttachInfo attachInfo = mAttachInfo;
17728        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17729
17730        if (autoScale && scalingRequired) {
17731            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17732            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17733        }
17734
17735        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17736        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17737        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17738
17739        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17740        final long drawingCacheSize =
17741                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17742        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17743            if (width > 0 && height > 0) {
17744                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17745                        + " too large to fit into a software layer (or drawing cache), needs "
17746                        + projectedBitmapSize + " bytes, only "
17747                        + drawingCacheSize + " available");
17748            }
17749            destroyDrawingCache();
17750            mCachingFailed = true;
17751            return;
17752        }
17753
17754        boolean clear = true;
17755        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17756
17757        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17758            Bitmap.Config quality;
17759            if (!opaque) {
17760                // Never pick ARGB_4444 because it looks awful
17761                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17762                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17763                    case DRAWING_CACHE_QUALITY_AUTO:
17764                    case DRAWING_CACHE_QUALITY_LOW:
17765                    case DRAWING_CACHE_QUALITY_HIGH:
17766                    default:
17767                        quality = Bitmap.Config.ARGB_8888;
17768                        break;
17769                }
17770            } else {
17771                // Optimization for translucent windows
17772                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17773                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17774            }
17775
17776            // Try to cleanup memory
17777            if (bitmap != null) bitmap.recycle();
17778
17779            try {
17780                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17781                        width, height, quality);
17782                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17783                if (autoScale) {
17784                    mDrawingCache = bitmap;
17785                } else {
17786                    mUnscaledDrawingCache = bitmap;
17787                }
17788                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17789            } catch (OutOfMemoryError e) {
17790                // If there is not enough memory to create the bitmap cache, just
17791                // ignore the issue as bitmap caches are not required to draw the
17792                // view hierarchy
17793                if (autoScale) {
17794                    mDrawingCache = null;
17795                } else {
17796                    mUnscaledDrawingCache = null;
17797                }
17798                mCachingFailed = true;
17799                return;
17800            }
17801
17802            clear = drawingCacheBackgroundColor != 0;
17803        }
17804
17805        Canvas canvas;
17806        if (attachInfo != null) {
17807            canvas = attachInfo.mCanvas;
17808            if (canvas == null) {
17809                canvas = new Canvas();
17810            }
17811            canvas.setBitmap(bitmap);
17812            // Temporarily clobber the cached Canvas in case one of our children
17813            // is also using a drawing cache. Without this, the children would
17814            // steal the canvas by attaching their own bitmap to it and bad, bad
17815            // thing would happen (invisible views, corrupted drawings, etc.)
17816            attachInfo.mCanvas = null;
17817        } else {
17818            // This case should hopefully never or seldom happen
17819            canvas = new Canvas(bitmap);
17820        }
17821
17822        if (clear) {
17823            bitmap.eraseColor(drawingCacheBackgroundColor);
17824        }
17825
17826        computeScroll();
17827        final int restoreCount = canvas.save();
17828
17829        if (autoScale && scalingRequired) {
17830            final float scale = attachInfo.mApplicationScale;
17831            canvas.scale(scale, scale);
17832        }
17833
17834        canvas.translate(-mScrollX, -mScrollY);
17835
17836        mPrivateFlags |= PFLAG_DRAWN;
17837        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17838                mLayerType != LAYER_TYPE_NONE) {
17839            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17840        }
17841
17842        // Fast path for layouts with no backgrounds
17843        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17844            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17845            dispatchDraw(canvas);
17846            if (mOverlay != null && !mOverlay.isEmpty()) {
17847                mOverlay.getOverlayView().draw(canvas);
17848            }
17849        } else {
17850            draw(canvas);
17851        }
17852
17853        canvas.restoreToCount(restoreCount);
17854        canvas.setBitmap(null);
17855
17856        if (attachInfo != null) {
17857            // Restore the cached Canvas for our siblings
17858            attachInfo.mCanvas = canvas;
17859        }
17860    }
17861
17862    /**
17863     * Create a snapshot of the view into a bitmap.  We should probably make
17864     * some form of this public, but should think about the API.
17865     *
17866     * @hide
17867     */
17868    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17869        int width = mRight - mLeft;
17870        int height = mBottom - mTop;
17871
17872        final AttachInfo attachInfo = mAttachInfo;
17873        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
17874        width = (int) ((width * scale) + 0.5f);
17875        height = (int) ((height * scale) + 0.5f);
17876
17877        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17878                width > 0 ? width : 1, height > 0 ? height : 1, quality);
17879        if (bitmap == null) {
17880            throw new OutOfMemoryError();
17881        }
17882
17883        Resources resources = getResources();
17884        if (resources != null) {
17885            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
17886        }
17887
17888        Canvas canvas;
17889        if (attachInfo != null) {
17890            canvas = attachInfo.mCanvas;
17891            if (canvas == null) {
17892                canvas = new Canvas();
17893            }
17894            canvas.setBitmap(bitmap);
17895            // Temporarily clobber the cached Canvas in case one of our children
17896            // is also using a drawing cache. Without this, the children would
17897            // steal the canvas by attaching their own bitmap to it and bad, bad
17898            // things would happen (invisible views, corrupted drawings, etc.)
17899            attachInfo.mCanvas = null;
17900        } else {
17901            // This case should hopefully never or seldom happen
17902            canvas = new Canvas(bitmap);
17903        }
17904        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
17905        canvas.setHwBitmapsInSwModeEnabled(true);
17906        if ((backgroundColor & 0xff000000) != 0) {
17907            bitmap.eraseColor(backgroundColor);
17908        }
17909
17910        computeScroll();
17911        final int restoreCount = canvas.save();
17912        canvas.scale(scale, scale);
17913        canvas.translate(-mScrollX, -mScrollY);
17914
17915        // Temporarily remove the dirty mask
17916        int flags = mPrivateFlags;
17917        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17918
17919        // Fast path for layouts with no backgrounds
17920        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17921            dispatchDraw(canvas);
17922            if (mOverlay != null && !mOverlay.isEmpty()) {
17923                mOverlay.getOverlayView().draw(canvas);
17924            }
17925        } else {
17926            draw(canvas);
17927        }
17928
17929        mPrivateFlags = flags;
17930
17931        canvas.restoreToCount(restoreCount);
17932        canvas.setBitmap(null);
17933        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
17934
17935        if (attachInfo != null) {
17936            // Restore the cached Canvas for our siblings
17937            attachInfo.mCanvas = canvas;
17938        }
17939
17940        return bitmap;
17941    }
17942
17943    /**
17944     * Indicates whether this View is currently in edit mode. A View is usually
17945     * in edit mode when displayed within a developer tool. For instance, if
17946     * this View is being drawn by a visual user interface builder, this method
17947     * should return true.
17948     *
17949     * Subclasses should check the return value of this method to provide
17950     * different behaviors if their normal behavior might interfere with the
17951     * host environment. For instance: the class spawns a thread in its
17952     * constructor, the drawing code relies on device-specific features, etc.
17953     *
17954     * This method is usually checked in the drawing code of custom widgets.
17955     *
17956     * @return True if this View is in edit mode, false otherwise.
17957     */
17958    public boolean isInEditMode() {
17959        return false;
17960    }
17961
17962    /**
17963     * If the View draws content inside its padding and enables fading edges,
17964     * it needs to support padding offsets. Padding offsets are added to the
17965     * fading edges to extend the length of the fade so that it covers pixels
17966     * drawn inside the padding.
17967     *
17968     * Subclasses of this class should override this method if they need
17969     * to draw content inside the padding.
17970     *
17971     * @return True if padding offset must be applied, false otherwise.
17972     *
17973     * @see #getLeftPaddingOffset()
17974     * @see #getRightPaddingOffset()
17975     * @see #getTopPaddingOffset()
17976     * @see #getBottomPaddingOffset()
17977     *
17978     * @since CURRENT
17979     */
17980    protected boolean isPaddingOffsetRequired() {
17981        return false;
17982    }
17983
17984    /**
17985     * Amount by which to extend the left fading region. Called only when
17986     * {@link #isPaddingOffsetRequired()} returns true.
17987     *
17988     * @return The left padding offset in pixels.
17989     *
17990     * @see #isPaddingOffsetRequired()
17991     *
17992     * @since CURRENT
17993     */
17994    protected int getLeftPaddingOffset() {
17995        return 0;
17996    }
17997
17998    /**
17999     * Amount by which to extend the right fading region. Called only when
18000     * {@link #isPaddingOffsetRequired()} returns true.
18001     *
18002     * @return The right padding offset in pixels.
18003     *
18004     * @see #isPaddingOffsetRequired()
18005     *
18006     * @since CURRENT
18007     */
18008    protected int getRightPaddingOffset() {
18009        return 0;
18010    }
18011
18012    /**
18013     * Amount by which to extend the top fading region. Called only when
18014     * {@link #isPaddingOffsetRequired()} returns true.
18015     *
18016     * @return The top padding offset in pixels.
18017     *
18018     * @see #isPaddingOffsetRequired()
18019     *
18020     * @since CURRENT
18021     */
18022    protected int getTopPaddingOffset() {
18023        return 0;
18024    }
18025
18026    /**
18027     * Amount by which to extend the bottom fading region. Called only when
18028     * {@link #isPaddingOffsetRequired()} returns true.
18029     *
18030     * @return The bottom padding offset in pixels.
18031     *
18032     * @see #isPaddingOffsetRequired()
18033     *
18034     * @since CURRENT
18035     */
18036    protected int getBottomPaddingOffset() {
18037        return 0;
18038    }
18039
18040    /**
18041     * @hide
18042     * @param offsetRequired
18043     */
18044    protected int getFadeTop(boolean offsetRequired) {
18045        int top = mPaddingTop;
18046        if (offsetRequired) top += getTopPaddingOffset();
18047        return top;
18048    }
18049
18050    /**
18051     * @hide
18052     * @param offsetRequired
18053     */
18054    protected int getFadeHeight(boolean offsetRequired) {
18055        int padding = mPaddingTop;
18056        if (offsetRequired) padding += getTopPaddingOffset();
18057        return mBottom - mTop - mPaddingBottom - padding;
18058    }
18059
18060    /**
18061     * <p>Indicates whether this view is attached to a hardware accelerated
18062     * window or not.</p>
18063     *
18064     * <p>Even if this method returns true, it does not mean that every call
18065     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18066     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18067     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18068     * window is hardware accelerated,
18069     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18070     * return false, and this method will return true.</p>
18071     *
18072     * @return True if the view is attached to a window and the window is
18073     *         hardware accelerated; false in any other case.
18074     */
18075    @ViewDebug.ExportedProperty(category = "drawing")
18076    public boolean isHardwareAccelerated() {
18077        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18078    }
18079
18080    /**
18081     * Sets a rectangular area on this view to which the view will be clipped
18082     * when it is drawn. Setting the value to null will remove the clip bounds
18083     * and the view will draw normally, using its full bounds.
18084     *
18085     * @param clipBounds The rectangular area, in the local coordinates of
18086     * this view, to which future drawing operations will be clipped.
18087     */
18088    public void setClipBounds(Rect clipBounds) {
18089        if (clipBounds == mClipBounds
18090                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18091            return;
18092        }
18093        if (clipBounds != null) {
18094            if (mClipBounds == null) {
18095                mClipBounds = new Rect(clipBounds);
18096            } else {
18097                mClipBounds.set(clipBounds);
18098            }
18099        } else {
18100            mClipBounds = null;
18101        }
18102        mRenderNode.setClipBounds(mClipBounds);
18103        invalidateViewProperty(false, false);
18104    }
18105
18106    /**
18107     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18108     *
18109     * @return A copy of the current clip bounds if clip bounds are set,
18110     * otherwise null.
18111     */
18112    public Rect getClipBounds() {
18113        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18114    }
18115
18116
18117    /**
18118     * Populates an output rectangle with the clip bounds of the view,
18119     * returning {@code true} if successful or {@code false} if the view's
18120     * clip bounds are {@code null}.
18121     *
18122     * @param outRect rectangle in which to place the clip bounds of the view
18123     * @return {@code true} if successful or {@code false} if the view's
18124     *         clip bounds are {@code null}
18125     */
18126    public boolean getClipBounds(Rect outRect) {
18127        if (mClipBounds != null) {
18128            outRect.set(mClipBounds);
18129            return true;
18130        }
18131        return false;
18132    }
18133
18134    /**
18135     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18136     * case of an active Animation being run on the view.
18137     */
18138    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18139            Animation a, boolean scalingRequired) {
18140        Transformation invalidationTransform;
18141        final int flags = parent.mGroupFlags;
18142        final boolean initialized = a.isInitialized();
18143        if (!initialized) {
18144            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18145            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18146            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18147            onAnimationStart();
18148        }
18149
18150        final Transformation t = parent.getChildTransformation();
18151        boolean more = a.getTransformation(drawingTime, t, 1f);
18152        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18153            if (parent.mInvalidationTransformation == null) {
18154                parent.mInvalidationTransformation = new Transformation();
18155            }
18156            invalidationTransform = parent.mInvalidationTransformation;
18157            a.getTransformation(drawingTime, invalidationTransform, 1f);
18158        } else {
18159            invalidationTransform = t;
18160        }
18161
18162        if (more) {
18163            if (!a.willChangeBounds()) {
18164                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18165                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18166                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18167                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18168                    // The child need to draw an animation, potentially offscreen, so
18169                    // make sure we do not cancel invalidate requests
18170                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18171                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18172                }
18173            } else {
18174                if (parent.mInvalidateRegion == null) {
18175                    parent.mInvalidateRegion = new RectF();
18176                }
18177                final RectF region = parent.mInvalidateRegion;
18178                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18179                        invalidationTransform);
18180
18181                // The child need to draw an animation, potentially offscreen, so
18182                // make sure we do not cancel invalidate requests
18183                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18184
18185                final int left = mLeft + (int) region.left;
18186                final int top = mTop + (int) region.top;
18187                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18188                        top + (int) (region.height() + .5f));
18189            }
18190        }
18191        return more;
18192    }
18193
18194    /**
18195     * This method is called by getDisplayList() when a display list is recorded for a View.
18196     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18197     */
18198    void setDisplayListProperties(RenderNode renderNode) {
18199        if (renderNode != null) {
18200            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18201            renderNode.setClipToBounds(mParent instanceof ViewGroup
18202                    && ((ViewGroup) mParent).getClipChildren());
18203
18204            float alpha = 1;
18205            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18206                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18207                ViewGroup parentVG = (ViewGroup) mParent;
18208                final Transformation t = parentVG.getChildTransformation();
18209                if (parentVG.getChildStaticTransformation(this, t)) {
18210                    final int transformType = t.getTransformationType();
18211                    if (transformType != Transformation.TYPE_IDENTITY) {
18212                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18213                            alpha = t.getAlpha();
18214                        }
18215                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18216                            renderNode.setStaticMatrix(t.getMatrix());
18217                        }
18218                    }
18219                }
18220            }
18221            if (mTransformationInfo != null) {
18222                alpha *= getFinalAlpha();
18223                if (alpha < 1) {
18224                    final int multipliedAlpha = (int) (255 * alpha);
18225                    if (onSetAlpha(multipliedAlpha)) {
18226                        alpha = 1;
18227                    }
18228                }
18229                renderNode.setAlpha(alpha);
18230            } else if (alpha < 1) {
18231                renderNode.setAlpha(alpha);
18232            }
18233        }
18234    }
18235
18236    /**
18237     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18238     *
18239     * This is where the View specializes rendering behavior based on layer type,
18240     * and hardware acceleration.
18241     */
18242    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18243        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18244        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18245         *
18246         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18247         * HW accelerated, it can't handle drawing RenderNodes.
18248         */
18249        boolean drawingWithRenderNode = mAttachInfo != null
18250                && mAttachInfo.mHardwareAccelerated
18251                && hardwareAcceleratedCanvas;
18252
18253        boolean more = false;
18254        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18255        final int parentFlags = parent.mGroupFlags;
18256
18257        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18258            parent.getChildTransformation().clear();
18259            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18260        }
18261
18262        Transformation transformToApply = null;
18263        boolean concatMatrix = false;
18264        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18265        final Animation a = getAnimation();
18266        if (a != null) {
18267            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18268            concatMatrix = a.willChangeTransformationMatrix();
18269            if (concatMatrix) {
18270                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18271            }
18272            transformToApply = parent.getChildTransformation();
18273        } else {
18274            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18275                // No longer animating: clear out old animation matrix
18276                mRenderNode.setAnimationMatrix(null);
18277                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18278            }
18279            if (!drawingWithRenderNode
18280                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18281                final Transformation t = parent.getChildTransformation();
18282                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18283                if (hasTransform) {
18284                    final int transformType = t.getTransformationType();
18285                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18286                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18287                }
18288            }
18289        }
18290
18291        concatMatrix |= !childHasIdentityMatrix;
18292
18293        // Sets the flag as early as possible to allow draw() implementations
18294        // to call invalidate() successfully when doing animations
18295        mPrivateFlags |= PFLAG_DRAWN;
18296
18297        if (!concatMatrix &&
18298                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18299                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18300                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18301                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18302            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18303            return more;
18304        }
18305        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18306
18307        if (hardwareAcceleratedCanvas) {
18308            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18309            // retain the flag's value temporarily in the mRecreateDisplayList flag
18310            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18311            mPrivateFlags &= ~PFLAG_INVALIDATED;
18312        }
18313
18314        RenderNode renderNode = null;
18315        Bitmap cache = null;
18316        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18317        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18318             if (layerType != LAYER_TYPE_NONE) {
18319                 // If not drawing with RenderNode, treat HW layers as SW
18320                 layerType = LAYER_TYPE_SOFTWARE;
18321                 buildDrawingCache(true);
18322            }
18323            cache = getDrawingCache(true);
18324        }
18325
18326        if (drawingWithRenderNode) {
18327            // Delay getting the display list until animation-driven alpha values are
18328            // set up and possibly passed on to the view
18329            renderNode = updateDisplayListIfDirty();
18330            if (!renderNode.isValid()) {
18331                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18332                // to getDisplayList(), the display list will be marked invalid and we should not
18333                // try to use it again.
18334                renderNode = null;
18335                drawingWithRenderNode = false;
18336            }
18337        }
18338
18339        int sx = 0;
18340        int sy = 0;
18341        if (!drawingWithRenderNode) {
18342            computeScroll();
18343            sx = mScrollX;
18344            sy = mScrollY;
18345        }
18346
18347        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18348        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18349
18350        int restoreTo = -1;
18351        if (!drawingWithRenderNode || transformToApply != null) {
18352            restoreTo = canvas.save();
18353        }
18354        if (offsetForScroll) {
18355            canvas.translate(mLeft - sx, mTop - sy);
18356        } else {
18357            if (!drawingWithRenderNode) {
18358                canvas.translate(mLeft, mTop);
18359            }
18360            if (scalingRequired) {
18361                if (drawingWithRenderNode) {
18362                    // TODO: Might not need this if we put everything inside the DL
18363                    restoreTo = canvas.save();
18364                }
18365                // mAttachInfo cannot be null, otherwise scalingRequired == false
18366                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18367                canvas.scale(scale, scale);
18368            }
18369        }
18370
18371        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18372        if (transformToApply != null
18373                || alpha < 1
18374                || !hasIdentityMatrix()
18375                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18376            if (transformToApply != null || !childHasIdentityMatrix) {
18377                int transX = 0;
18378                int transY = 0;
18379
18380                if (offsetForScroll) {
18381                    transX = -sx;
18382                    transY = -sy;
18383                }
18384
18385                if (transformToApply != null) {
18386                    if (concatMatrix) {
18387                        if (drawingWithRenderNode) {
18388                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18389                        } else {
18390                            // Undo the scroll translation, apply the transformation matrix,
18391                            // then redo the scroll translate to get the correct result.
18392                            canvas.translate(-transX, -transY);
18393                            canvas.concat(transformToApply.getMatrix());
18394                            canvas.translate(transX, transY);
18395                        }
18396                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18397                    }
18398
18399                    float transformAlpha = transformToApply.getAlpha();
18400                    if (transformAlpha < 1) {
18401                        alpha *= transformAlpha;
18402                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18403                    }
18404                }
18405
18406                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18407                    canvas.translate(-transX, -transY);
18408                    canvas.concat(getMatrix());
18409                    canvas.translate(transX, transY);
18410                }
18411            }
18412
18413            // Deal with alpha if it is or used to be <1
18414            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18415                if (alpha < 1) {
18416                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18417                } else {
18418                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18419                }
18420                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18421                if (!drawingWithDrawingCache) {
18422                    final int multipliedAlpha = (int) (255 * alpha);
18423                    if (!onSetAlpha(multipliedAlpha)) {
18424                        if (drawingWithRenderNode) {
18425                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18426                        } else if (layerType == LAYER_TYPE_NONE) {
18427                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18428                                    multipliedAlpha);
18429                        }
18430                    } else {
18431                        // Alpha is handled by the child directly, clobber the layer's alpha
18432                        mPrivateFlags |= PFLAG_ALPHA_SET;
18433                    }
18434                }
18435            }
18436        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18437            onSetAlpha(255);
18438            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18439        }
18440
18441        if (!drawingWithRenderNode) {
18442            // apply clips directly, since RenderNode won't do it for this draw
18443            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18444                if (offsetForScroll) {
18445                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18446                } else {
18447                    if (!scalingRequired || cache == null) {
18448                        canvas.clipRect(0, 0, getWidth(), getHeight());
18449                    } else {
18450                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18451                    }
18452                }
18453            }
18454
18455            if (mClipBounds != null) {
18456                // clip bounds ignore scroll
18457                canvas.clipRect(mClipBounds);
18458            }
18459        }
18460
18461        if (!drawingWithDrawingCache) {
18462            if (drawingWithRenderNode) {
18463                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18464                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18465            } else {
18466                // Fast path for layouts with no backgrounds
18467                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18468                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18469                    dispatchDraw(canvas);
18470                } else {
18471                    draw(canvas);
18472                }
18473            }
18474        } else if (cache != null) {
18475            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18476            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18477                // no layer paint, use temporary paint to draw bitmap
18478                Paint cachePaint = parent.mCachePaint;
18479                if (cachePaint == null) {
18480                    cachePaint = new Paint();
18481                    cachePaint.setDither(false);
18482                    parent.mCachePaint = cachePaint;
18483                }
18484                cachePaint.setAlpha((int) (alpha * 255));
18485                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18486            } else {
18487                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18488                int layerPaintAlpha = mLayerPaint.getAlpha();
18489                if (alpha < 1) {
18490                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18491                }
18492                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18493                if (alpha < 1) {
18494                    mLayerPaint.setAlpha(layerPaintAlpha);
18495                }
18496            }
18497        }
18498
18499        if (restoreTo >= 0) {
18500            canvas.restoreToCount(restoreTo);
18501        }
18502
18503        if (a != null && !more) {
18504            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18505                onSetAlpha(255);
18506            }
18507            parent.finishAnimatingView(this, a);
18508        }
18509
18510        if (more && hardwareAcceleratedCanvas) {
18511            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18512                // alpha animations should cause the child to recreate its display list
18513                invalidate(true);
18514            }
18515        }
18516
18517        mRecreateDisplayList = false;
18518
18519        return more;
18520    }
18521
18522    static Paint getDebugPaint() {
18523        if (sDebugPaint == null) {
18524            sDebugPaint = new Paint();
18525            sDebugPaint.setAntiAlias(false);
18526        }
18527        return sDebugPaint;
18528    }
18529
18530    final int dipsToPixels(int dips) {
18531        float scale = getContext().getResources().getDisplayMetrics().density;
18532        return (int) (dips * scale + 0.5f);
18533    }
18534
18535    final private void debugDrawFocus(Canvas canvas) {
18536        if (isFocused()) {
18537            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18538            final int l = mScrollX;
18539            final int r = l + mRight - mLeft;
18540            final int t = mScrollY;
18541            final int b = t + mBottom - mTop;
18542
18543            final Paint paint = getDebugPaint();
18544            paint.setColor(DEBUG_CORNERS_COLOR);
18545
18546            // Draw squares in corners.
18547            paint.setStyle(Paint.Style.FILL);
18548            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18549            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18550            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18551            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18552
18553            // Draw big X across the view.
18554            paint.setStyle(Paint.Style.STROKE);
18555            canvas.drawLine(l, t, r, b, paint);
18556            canvas.drawLine(l, b, r, t, paint);
18557        }
18558    }
18559
18560    /**
18561     * Manually render this view (and all of its children) to the given Canvas.
18562     * The view must have already done a full layout before this function is
18563     * called.  When implementing a view, implement
18564     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18565     * If you do need to override this method, call the superclass version.
18566     *
18567     * @param canvas The Canvas to which the View is rendered.
18568     */
18569    @CallSuper
18570    public void draw(Canvas canvas) {
18571        final int privateFlags = mPrivateFlags;
18572        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18573                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18574        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18575
18576        /*
18577         * Draw traversal performs several drawing steps which must be executed
18578         * in the appropriate order:
18579         *
18580         *      1. Draw the background
18581         *      2. If necessary, save the canvas' layers to prepare for fading
18582         *      3. Draw view's content
18583         *      4. Draw children
18584         *      5. If necessary, draw the fading edges and restore layers
18585         *      6. Draw decorations (scrollbars for instance)
18586         */
18587
18588        // Step 1, draw the background, if needed
18589        int saveCount;
18590
18591        if (!dirtyOpaque) {
18592            drawBackground(canvas);
18593        }
18594
18595        // skip step 2 & 5 if possible (common case)
18596        final int viewFlags = mViewFlags;
18597        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18598        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18599        if (!verticalEdges && !horizontalEdges) {
18600            // Step 3, draw the content
18601            if (!dirtyOpaque) onDraw(canvas);
18602
18603            // Step 4, draw the children
18604            dispatchDraw(canvas);
18605
18606            // Overlay is part of the content and draws beneath Foreground
18607            if (mOverlay != null && !mOverlay.isEmpty()) {
18608                mOverlay.getOverlayView().dispatchDraw(canvas);
18609            }
18610
18611            // Step 6, draw decorations (foreground, scrollbars)
18612            onDrawForeground(canvas);
18613
18614            if (debugDraw()) {
18615                debugDrawFocus(canvas);
18616            }
18617
18618            // we're done...
18619            return;
18620        }
18621
18622        /*
18623         * Here we do the full fledged routine...
18624         * (this is an uncommon case where speed matters less,
18625         * this is why we repeat some of the tests that have been
18626         * done above)
18627         */
18628
18629        boolean drawTop = false;
18630        boolean drawBottom = false;
18631        boolean drawLeft = false;
18632        boolean drawRight = false;
18633
18634        float topFadeStrength = 0.0f;
18635        float bottomFadeStrength = 0.0f;
18636        float leftFadeStrength = 0.0f;
18637        float rightFadeStrength = 0.0f;
18638
18639        // Step 2, save the canvas' layers
18640        int paddingLeft = mPaddingLeft;
18641
18642        final boolean offsetRequired = isPaddingOffsetRequired();
18643        if (offsetRequired) {
18644            paddingLeft += getLeftPaddingOffset();
18645        }
18646
18647        int left = mScrollX + paddingLeft;
18648        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18649        int top = mScrollY + getFadeTop(offsetRequired);
18650        int bottom = top + getFadeHeight(offsetRequired);
18651
18652        if (offsetRequired) {
18653            right += getRightPaddingOffset();
18654            bottom += getBottomPaddingOffset();
18655        }
18656
18657        final ScrollabilityCache scrollabilityCache = mScrollCache;
18658        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18659        int length = (int) fadeHeight;
18660
18661        // clip the fade length if top and bottom fades overlap
18662        // overlapping fades produce odd-looking artifacts
18663        if (verticalEdges && (top + length > bottom - length)) {
18664            length = (bottom - top) / 2;
18665        }
18666
18667        // also clip horizontal fades if necessary
18668        if (horizontalEdges && (left + length > right - length)) {
18669            length = (right - left) / 2;
18670        }
18671
18672        if (verticalEdges) {
18673            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18674            drawTop = topFadeStrength * fadeHeight > 1.0f;
18675            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18676            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18677        }
18678
18679        if (horizontalEdges) {
18680            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18681            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18682            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18683            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18684        }
18685
18686        saveCount = canvas.getSaveCount();
18687
18688        int solidColor = getSolidColor();
18689        if (solidColor == 0) {
18690            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18691
18692            if (drawTop) {
18693                canvas.saveLayer(left, top, right, top + length, null, flags);
18694            }
18695
18696            if (drawBottom) {
18697                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18698            }
18699
18700            if (drawLeft) {
18701                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18702            }
18703
18704            if (drawRight) {
18705                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18706            }
18707        } else {
18708            scrollabilityCache.setFadeColor(solidColor);
18709        }
18710
18711        // Step 3, draw the content
18712        if (!dirtyOpaque) onDraw(canvas);
18713
18714        // Step 4, draw the children
18715        dispatchDraw(canvas);
18716
18717        // Step 5, draw the fade effect and restore layers
18718        final Paint p = scrollabilityCache.paint;
18719        final Matrix matrix = scrollabilityCache.matrix;
18720        final Shader fade = scrollabilityCache.shader;
18721
18722        if (drawTop) {
18723            matrix.setScale(1, fadeHeight * topFadeStrength);
18724            matrix.postTranslate(left, top);
18725            fade.setLocalMatrix(matrix);
18726            p.setShader(fade);
18727            canvas.drawRect(left, top, right, top + length, p);
18728        }
18729
18730        if (drawBottom) {
18731            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18732            matrix.postRotate(180);
18733            matrix.postTranslate(left, bottom);
18734            fade.setLocalMatrix(matrix);
18735            p.setShader(fade);
18736            canvas.drawRect(left, bottom - length, right, bottom, p);
18737        }
18738
18739        if (drawLeft) {
18740            matrix.setScale(1, fadeHeight * leftFadeStrength);
18741            matrix.postRotate(-90);
18742            matrix.postTranslate(left, top);
18743            fade.setLocalMatrix(matrix);
18744            p.setShader(fade);
18745            canvas.drawRect(left, top, left + length, bottom, p);
18746        }
18747
18748        if (drawRight) {
18749            matrix.setScale(1, fadeHeight * rightFadeStrength);
18750            matrix.postRotate(90);
18751            matrix.postTranslate(right, top);
18752            fade.setLocalMatrix(matrix);
18753            p.setShader(fade);
18754            canvas.drawRect(right - length, top, right, bottom, p);
18755        }
18756
18757        canvas.restoreToCount(saveCount);
18758
18759        // Overlay is part of the content and draws beneath Foreground
18760        if (mOverlay != null && !mOverlay.isEmpty()) {
18761            mOverlay.getOverlayView().dispatchDraw(canvas);
18762        }
18763
18764        // Step 6, draw decorations (foreground, scrollbars)
18765        onDrawForeground(canvas);
18766
18767        if (debugDraw()) {
18768            debugDrawFocus(canvas);
18769        }
18770    }
18771
18772    /**
18773     * Draws the background onto the specified canvas.
18774     *
18775     * @param canvas Canvas on which to draw the background
18776     */
18777    private void drawBackground(Canvas canvas) {
18778        final Drawable background = mBackground;
18779        if (background == null) {
18780            return;
18781        }
18782
18783        setBackgroundBounds();
18784
18785        // Attempt to use a display list if requested.
18786        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18787                && mAttachInfo.mThreadedRenderer != null) {
18788            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18789
18790            final RenderNode renderNode = mBackgroundRenderNode;
18791            if (renderNode != null && renderNode.isValid()) {
18792                setBackgroundRenderNodeProperties(renderNode);
18793                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18794                return;
18795            }
18796        }
18797
18798        final int scrollX = mScrollX;
18799        final int scrollY = mScrollY;
18800        if ((scrollX | scrollY) == 0) {
18801            background.draw(canvas);
18802        } else {
18803            canvas.translate(scrollX, scrollY);
18804            background.draw(canvas);
18805            canvas.translate(-scrollX, -scrollY);
18806        }
18807    }
18808
18809    /**
18810     * Sets the correct background bounds and rebuilds the outline, if needed.
18811     * <p/>
18812     * This is called by LayoutLib.
18813     */
18814    void setBackgroundBounds() {
18815        if (mBackgroundSizeChanged && mBackground != null) {
18816            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18817            mBackgroundSizeChanged = false;
18818            rebuildOutline();
18819        }
18820    }
18821
18822    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18823        renderNode.setTranslationX(mScrollX);
18824        renderNode.setTranslationY(mScrollY);
18825    }
18826
18827    /**
18828     * Creates a new display list or updates the existing display list for the
18829     * specified Drawable.
18830     *
18831     * @param drawable Drawable for which to create a display list
18832     * @param renderNode Existing RenderNode, or {@code null}
18833     * @return A valid display list for the specified drawable
18834     */
18835    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18836        if (renderNode == null) {
18837            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18838        }
18839
18840        final Rect bounds = drawable.getBounds();
18841        final int width = bounds.width();
18842        final int height = bounds.height();
18843        final DisplayListCanvas canvas = renderNode.start(width, height);
18844
18845        // Reverse left/top translation done by drawable canvas, which will
18846        // instead be applied by rendernode's LTRB bounds below. This way, the
18847        // drawable's bounds match with its rendernode bounds and its content
18848        // will lie within those bounds in the rendernode tree.
18849        canvas.translate(-bounds.left, -bounds.top);
18850
18851        try {
18852            drawable.draw(canvas);
18853        } finally {
18854            renderNode.end(canvas);
18855        }
18856
18857        // Set up drawable properties that are view-independent.
18858        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18859        renderNode.setProjectBackwards(drawable.isProjected());
18860        renderNode.setProjectionReceiver(true);
18861        renderNode.setClipToBounds(false);
18862        return renderNode;
18863    }
18864
18865    /**
18866     * Returns the overlay for this view, creating it if it does not yet exist.
18867     * Adding drawables to the overlay will cause them to be displayed whenever
18868     * the view itself is redrawn. Objects in the overlay should be actively
18869     * managed: remove them when they should not be displayed anymore. The
18870     * overlay will always have the same size as its host view.
18871     *
18872     * <p>Note: Overlays do not currently work correctly with {@link
18873     * SurfaceView} or {@link TextureView}; contents in overlays for these
18874     * types of views may not display correctly.</p>
18875     *
18876     * @return The ViewOverlay object for this view.
18877     * @see ViewOverlay
18878     */
18879    public ViewOverlay getOverlay() {
18880        if (mOverlay == null) {
18881            mOverlay = new ViewOverlay(mContext, this);
18882        }
18883        return mOverlay;
18884    }
18885
18886    /**
18887     * Override this if your view is known to always be drawn on top of a solid color background,
18888     * and needs to draw fading edges. Returning a non-zero color enables the view system to
18889     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
18890     * should be set to 0xFF.
18891     *
18892     * @see #setVerticalFadingEdgeEnabled(boolean)
18893     * @see #setHorizontalFadingEdgeEnabled(boolean)
18894     *
18895     * @return The known solid color background for this view, or 0 if the color may vary
18896     */
18897    @ViewDebug.ExportedProperty(category = "drawing")
18898    @ColorInt
18899    public int getSolidColor() {
18900        return 0;
18901    }
18902
18903    /**
18904     * Build a human readable string representation of the specified view flags.
18905     *
18906     * @param flags the view flags to convert to a string
18907     * @return a String representing the supplied flags
18908     */
18909    private static String printFlags(int flags) {
18910        String output = "";
18911        int numFlags = 0;
18912        if ((flags & FOCUSABLE) == FOCUSABLE) {
18913            output += "TAKES_FOCUS";
18914            numFlags++;
18915        }
18916
18917        switch (flags & VISIBILITY_MASK) {
18918        case INVISIBLE:
18919            if (numFlags > 0) {
18920                output += " ";
18921            }
18922            output += "INVISIBLE";
18923            // USELESS HERE numFlags++;
18924            break;
18925        case GONE:
18926            if (numFlags > 0) {
18927                output += " ";
18928            }
18929            output += "GONE";
18930            // USELESS HERE numFlags++;
18931            break;
18932        default:
18933            break;
18934        }
18935        return output;
18936    }
18937
18938    /**
18939     * Build a human readable string representation of the specified private
18940     * view flags.
18941     *
18942     * @param privateFlags the private view flags to convert to a string
18943     * @return a String representing the supplied flags
18944     */
18945    private static String printPrivateFlags(int privateFlags) {
18946        String output = "";
18947        int numFlags = 0;
18948
18949        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
18950            output += "WANTS_FOCUS";
18951            numFlags++;
18952        }
18953
18954        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
18955            if (numFlags > 0) {
18956                output += " ";
18957            }
18958            output += "FOCUSED";
18959            numFlags++;
18960        }
18961
18962        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
18963            if (numFlags > 0) {
18964                output += " ";
18965            }
18966            output += "SELECTED";
18967            numFlags++;
18968        }
18969
18970        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
18971            if (numFlags > 0) {
18972                output += " ";
18973            }
18974            output += "IS_ROOT_NAMESPACE";
18975            numFlags++;
18976        }
18977
18978        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
18979            if (numFlags > 0) {
18980                output += " ";
18981            }
18982            output += "HAS_BOUNDS";
18983            numFlags++;
18984        }
18985
18986        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
18987            if (numFlags > 0) {
18988                output += " ";
18989            }
18990            output += "DRAWN";
18991            // USELESS HERE numFlags++;
18992        }
18993        return output;
18994    }
18995
18996    /**
18997     * <p>Indicates whether or not this view's layout will be requested during
18998     * the next hierarchy layout pass.</p>
18999     *
19000     * @return true if the layout will be forced during next layout pass
19001     */
19002    public boolean isLayoutRequested() {
19003        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19004    }
19005
19006    /**
19007     * Return true if o is a ViewGroup that is laying out using optical bounds.
19008     * @hide
19009     */
19010    public static boolean isLayoutModeOptical(Object o) {
19011        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19012    }
19013
19014    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19015        Insets parentInsets = mParent instanceof View ?
19016                ((View) mParent).getOpticalInsets() : Insets.NONE;
19017        Insets childInsets = getOpticalInsets();
19018        return setFrame(
19019                left   + parentInsets.left - childInsets.left,
19020                top    + parentInsets.top  - childInsets.top,
19021                right  + parentInsets.left + childInsets.right,
19022                bottom + parentInsets.top  + childInsets.bottom);
19023    }
19024
19025    /**
19026     * Assign a size and position to a view and all of its
19027     * descendants
19028     *
19029     * <p>This is the second phase of the layout mechanism.
19030     * (The first is measuring). In this phase, each parent calls
19031     * layout on all of its children to position them.
19032     * This is typically done using the child measurements
19033     * that were stored in the measure pass().</p>
19034     *
19035     * <p>Derived classes should not override this method.
19036     * Derived classes with children should override
19037     * onLayout. In that method, they should
19038     * call layout on each of their children.</p>
19039     *
19040     * @param l Left position, relative to parent
19041     * @param t Top position, relative to parent
19042     * @param r Right position, relative to parent
19043     * @param b Bottom position, relative to parent
19044     */
19045    @SuppressWarnings({"unchecked"})
19046    public void layout(int l, int t, int r, int b) {
19047        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19048            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19049            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19050        }
19051
19052        int oldL = mLeft;
19053        int oldT = mTop;
19054        int oldB = mBottom;
19055        int oldR = mRight;
19056
19057        boolean changed = isLayoutModeOptical(mParent) ?
19058                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19059
19060        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19061            onLayout(changed, l, t, r, b);
19062
19063            if (shouldDrawRoundScrollbar()) {
19064                if(mRoundScrollbarRenderer == null) {
19065                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19066                }
19067            } else {
19068                mRoundScrollbarRenderer = null;
19069            }
19070
19071            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19072
19073            ListenerInfo li = mListenerInfo;
19074            if (li != null && li.mOnLayoutChangeListeners != null) {
19075                ArrayList<OnLayoutChangeListener> listenersCopy =
19076                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19077                int numListeners = listenersCopy.size();
19078                for (int i = 0; i < numListeners; ++i) {
19079                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19080                }
19081            }
19082        }
19083
19084        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19085        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19086    }
19087
19088    /**
19089     * Called from layout when this view should
19090     * assign a size and position to each of its children.
19091     *
19092     * Derived classes with children should override
19093     * this method and call layout on each of
19094     * their children.
19095     * @param changed This is a new size or position for this view
19096     * @param left Left position, relative to parent
19097     * @param top Top position, relative to parent
19098     * @param right Right position, relative to parent
19099     * @param bottom Bottom position, relative to parent
19100     */
19101    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19102    }
19103
19104    /**
19105     * Assign a size and position to this view.
19106     *
19107     * This is called from layout.
19108     *
19109     * @param left Left position, relative to parent
19110     * @param top Top position, relative to parent
19111     * @param right Right position, relative to parent
19112     * @param bottom Bottom position, relative to parent
19113     * @return true if the new size and position are different than the
19114     *         previous ones
19115     * {@hide}
19116     */
19117    protected boolean setFrame(int left, int top, int right, int bottom) {
19118        boolean changed = false;
19119
19120        if (DBG) {
19121            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19122                    + right + "," + bottom + ")");
19123        }
19124
19125        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19126            changed = true;
19127
19128            // Remember our drawn bit
19129            int drawn = mPrivateFlags & PFLAG_DRAWN;
19130
19131            int oldWidth = mRight - mLeft;
19132            int oldHeight = mBottom - mTop;
19133            int newWidth = right - left;
19134            int newHeight = bottom - top;
19135            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19136
19137            // Invalidate our old position
19138            invalidate(sizeChanged);
19139
19140            mLeft = left;
19141            mTop = top;
19142            mRight = right;
19143            mBottom = bottom;
19144            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19145
19146            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19147
19148
19149            if (sizeChanged) {
19150                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19151            }
19152
19153            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19154                // If we are visible, force the DRAWN bit to on so that
19155                // this invalidate will go through (at least to our parent).
19156                // This is because someone may have invalidated this view
19157                // before this call to setFrame came in, thereby clearing
19158                // the DRAWN bit.
19159                mPrivateFlags |= PFLAG_DRAWN;
19160                invalidate(sizeChanged);
19161                // parent display list may need to be recreated based on a change in the bounds
19162                // of any child
19163                invalidateParentCaches();
19164            }
19165
19166            // Reset drawn bit to original value (invalidate turns it off)
19167            mPrivateFlags |= drawn;
19168
19169            mBackgroundSizeChanged = true;
19170            if (mForegroundInfo != null) {
19171                mForegroundInfo.mBoundsChanged = true;
19172            }
19173
19174            notifySubtreeAccessibilityStateChangedIfNeeded();
19175        }
19176        return changed;
19177    }
19178
19179    /**
19180     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19181     * @hide
19182     */
19183    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19184        setFrame(left, top, right, bottom);
19185    }
19186
19187    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19188        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19189        if (mOverlay != null) {
19190            mOverlay.getOverlayView().setRight(newWidth);
19191            mOverlay.getOverlayView().setBottom(newHeight);
19192        }
19193        rebuildOutline();
19194    }
19195
19196    /**
19197     * Finalize inflating a view from XML.  This is called as the last phase
19198     * of inflation, after all child views have been added.
19199     *
19200     * <p>Even if the subclass overrides onFinishInflate, they should always be
19201     * sure to call the super method, so that we get called.
19202     */
19203    @CallSuper
19204    protected void onFinishInflate() {
19205    }
19206
19207    /**
19208     * Returns the resources associated with this view.
19209     *
19210     * @return Resources object.
19211     */
19212    public Resources getResources() {
19213        return mResources;
19214    }
19215
19216    /**
19217     * Invalidates the specified Drawable.
19218     *
19219     * @param drawable the drawable to invalidate
19220     */
19221    @Override
19222    public void invalidateDrawable(@NonNull Drawable drawable) {
19223        if (verifyDrawable(drawable)) {
19224            final Rect dirty = drawable.getDirtyBounds();
19225            final int scrollX = mScrollX;
19226            final int scrollY = mScrollY;
19227
19228            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19229                    dirty.right + scrollX, dirty.bottom + scrollY);
19230            rebuildOutline();
19231        }
19232    }
19233
19234    /**
19235     * Schedules an action on a drawable to occur at a specified time.
19236     *
19237     * @param who the recipient of the action
19238     * @param what the action to run on the drawable
19239     * @param when the time at which the action must occur. Uses the
19240     *        {@link SystemClock#uptimeMillis} timebase.
19241     */
19242    @Override
19243    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19244        if (verifyDrawable(who) && what != null) {
19245            final long delay = when - SystemClock.uptimeMillis();
19246            if (mAttachInfo != null) {
19247                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19248                        Choreographer.CALLBACK_ANIMATION, what, who,
19249                        Choreographer.subtractFrameDelay(delay));
19250            } else {
19251                // Postpone the runnable until we know
19252                // on which thread it needs to run.
19253                getRunQueue().postDelayed(what, delay);
19254            }
19255        }
19256    }
19257
19258    /**
19259     * Cancels a scheduled action on a drawable.
19260     *
19261     * @param who the recipient of the action
19262     * @param what the action to cancel
19263     */
19264    @Override
19265    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19266        if (verifyDrawable(who) && what != null) {
19267            if (mAttachInfo != null) {
19268                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19269                        Choreographer.CALLBACK_ANIMATION, what, who);
19270            }
19271            getRunQueue().removeCallbacks(what);
19272        }
19273    }
19274
19275    /**
19276     * Unschedule any events associated with the given Drawable.  This can be
19277     * used when selecting a new Drawable into a view, so that the previous
19278     * one is completely unscheduled.
19279     *
19280     * @param who The Drawable to unschedule.
19281     *
19282     * @see #drawableStateChanged
19283     */
19284    public void unscheduleDrawable(Drawable who) {
19285        if (mAttachInfo != null && who != null) {
19286            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19287                    Choreographer.CALLBACK_ANIMATION, null, who);
19288        }
19289    }
19290
19291    /**
19292     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19293     * that the View directionality can and will be resolved before its Drawables.
19294     *
19295     * Will call {@link View#onResolveDrawables} when resolution is done.
19296     *
19297     * @hide
19298     */
19299    protected void resolveDrawables() {
19300        // Drawables resolution may need to happen before resolving the layout direction (which is
19301        // done only during the measure() call).
19302        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19303        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19304        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19305        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19306        // direction to be resolved as its resolved value will be the same as its raw value.
19307        if (!isLayoutDirectionResolved() &&
19308                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19309            return;
19310        }
19311
19312        final int layoutDirection = isLayoutDirectionResolved() ?
19313                getLayoutDirection() : getRawLayoutDirection();
19314
19315        if (mBackground != null) {
19316            mBackground.setLayoutDirection(layoutDirection);
19317        }
19318        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19319            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19320        }
19321        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19322        onResolveDrawables(layoutDirection);
19323    }
19324
19325    boolean areDrawablesResolved() {
19326        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19327    }
19328
19329    /**
19330     * Called when layout direction has been resolved.
19331     *
19332     * The default implementation does nothing.
19333     *
19334     * @param layoutDirection The resolved layout direction.
19335     *
19336     * @see #LAYOUT_DIRECTION_LTR
19337     * @see #LAYOUT_DIRECTION_RTL
19338     *
19339     * @hide
19340     */
19341    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19342    }
19343
19344    /**
19345     * @hide
19346     */
19347    protected void resetResolvedDrawables() {
19348        resetResolvedDrawablesInternal();
19349    }
19350
19351    void resetResolvedDrawablesInternal() {
19352        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19353    }
19354
19355    /**
19356     * If your view subclass is displaying its own Drawable objects, it should
19357     * override this function and return true for any Drawable it is
19358     * displaying.  This allows animations for those drawables to be
19359     * scheduled.
19360     *
19361     * <p>Be sure to call through to the super class when overriding this
19362     * function.
19363     *
19364     * @param who The Drawable to verify.  Return true if it is one you are
19365     *            displaying, else return the result of calling through to the
19366     *            super class.
19367     *
19368     * @return boolean If true than the Drawable is being displayed in the
19369     *         view; else false and it is not allowed to animate.
19370     *
19371     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19372     * @see #drawableStateChanged()
19373     */
19374    @CallSuper
19375    protected boolean verifyDrawable(@NonNull Drawable who) {
19376        // Avoid verifying the scroll bar drawable so that we don't end up in
19377        // an invalidation loop. This effectively prevents the scroll bar
19378        // drawable from triggering invalidations and scheduling runnables.
19379        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
19380    }
19381
19382    /**
19383     * This function is called whenever the state of the view changes in such
19384     * a way that it impacts the state of drawables being shown.
19385     * <p>
19386     * If the View has a StateListAnimator, it will also be called to run necessary state
19387     * change animations.
19388     * <p>
19389     * Be sure to call through to the superclass when overriding this function.
19390     *
19391     * @see Drawable#setState(int[])
19392     */
19393    @CallSuper
19394    protected void drawableStateChanged() {
19395        final int[] state = getDrawableState();
19396        boolean changed = false;
19397
19398        final Drawable bg = mBackground;
19399        if (bg != null && bg.isStateful()) {
19400            changed |= bg.setState(state);
19401        }
19402
19403        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19404        if (fg != null && fg.isStateful()) {
19405            changed |= fg.setState(state);
19406        }
19407
19408        if (mScrollCache != null) {
19409            final Drawable scrollBar = mScrollCache.scrollBar;
19410            if (scrollBar != null && scrollBar.isStateful()) {
19411                changed |= scrollBar.setState(state)
19412                        && mScrollCache.state != ScrollabilityCache.OFF;
19413            }
19414        }
19415
19416        if (mStateListAnimator != null) {
19417            mStateListAnimator.setState(state);
19418        }
19419
19420        if (changed) {
19421            invalidate();
19422        }
19423    }
19424
19425    /**
19426     * This function is called whenever the view hotspot changes and needs to
19427     * be propagated to drawables or child views managed by the view.
19428     * <p>
19429     * Dispatching to child views is handled by
19430     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19431     * <p>
19432     * Be sure to call through to the superclass when overriding this function.
19433     *
19434     * @param x hotspot x coordinate
19435     * @param y hotspot y coordinate
19436     */
19437    @CallSuper
19438    public void drawableHotspotChanged(float x, float y) {
19439        if (mBackground != null) {
19440            mBackground.setHotspot(x, y);
19441        }
19442        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19443            mForegroundInfo.mDrawable.setHotspot(x, y);
19444        }
19445
19446        dispatchDrawableHotspotChanged(x, y);
19447    }
19448
19449    /**
19450     * Dispatches drawableHotspotChanged to all of this View's children.
19451     *
19452     * @param x hotspot x coordinate
19453     * @param y hotspot y coordinate
19454     * @see #drawableHotspotChanged(float, float)
19455     */
19456    public void dispatchDrawableHotspotChanged(float x, float y) {
19457    }
19458
19459    /**
19460     * Call this to force a view to update its drawable state. This will cause
19461     * drawableStateChanged to be called on this view. Views that are interested
19462     * in the new state should call getDrawableState.
19463     *
19464     * @see #drawableStateChanged
19465     * @see #getDrawableState
19466     */
19467    public void refreshDrawableState() {
19468        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19469        drawableStateChanged();
19470
19471        ViewParent parent = mParent;
19472        if (parent != null) {
19473            parent.childDrawableStateChanged(this);
19474        }
19475    }
19476
19477    /**
19478     * Return an array of resource IDs of the drawable states representing the
19479     * current state of the view.
19480     *
19481     * @return The current drawable state
19482     *
19483     * @see Drawable#setState(int[])
19484     * @see #drawableStateChanged()
19485     * @see #onCreateDrawableState(int)
19486     */
19487    public final int[] getDrawableState() {
19488        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19489            return mDrawableState;
19490        } else {
19491            mDrawableState = onCreateDrawableState(0);
19492            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19493            return mDrawableState;
19494        }
19495    }
19496
19497    /**
19498     * Generate the new {@link android.graphics.drawable.Drawable} state for
19499     * this view. This is called by the view
19500     * system when the cached Drawable state is determined to be invalid.  To
19501     * retrieve the current state, you should use {@link #getDrawableState}.
19502     *
19503     * @param extraSpace if non-zero, this is the number of extra entries you
19504     * would like in the returned array in which you can place your own
19505     * states.
19506     *
19507     * @return Returns an array holding the current {@link Drawable} state of
19508     * the view.
19509     *
19510     * @see #mergeDrawableStates(int[], int[])
19511     */
19512    protected int[] onCreateDrawableState(int extraSpace) {
19513        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19514                mParent instanceof View) {
19515            return ((View) mParent).onCreateDrawableState(extraSpace);
19516        }
19517
19518        int[] drawableState;
19519
19520        int privateFlags = mPrivateFlags;
19521
19522        int viewStateIndex = 0;
19523        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19524        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19525        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19526        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19527        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19528        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19529        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19530                ThreadedRenderer.isAvailable()) {
19531            // This is set if HW acceleration is requested, even if the current
19532            // process doesn't allow it.  This is just to allow app preview
19533            // windows to better match their app.
19534            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19535        }
19536        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19537
19538        final int privateFlags2 = mPrivateFlags2;
19539        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19540            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19541        }
19542        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19543            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19544        }
19545
19546        drawableState = StateSet.get(viewStateIndex);
19547
19548        //noinspection ConstantIfStatement
19549        if (false) {
19550            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19551            Log.i("View", toString()
19552                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19553                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19554                    + " fo=" + hasFocus()
19555                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19556                    + " wf=" + hasWindowFocus()
19557                    + ": " + Arrays.toString(drawableState));
19558        }
19559
19560        if (extraSpace == 0) {
19561            return drawableState;
19562        }
19563
19564        final int[] fullState;
19565        if (drawableState != null) {
19566            fullState = new int[drawableState.length + extraSpace];
19567            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19568        } else {
19569            fullState = new int[extraSpace];
19570        }
19571
19572        return fullState;
19573    }
19574
19575    /**
19576     * Merge your own state values in <var>additionalState</var> into the base
19577     * state values <var>baseState</var> that were returned by
19578     * {@link #onCreateDrawableState(int)}.
19579     *
19580     * @param baseState The base state values returned by
19581     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19582     * own additional state values.
19583     *
19584     * @param additionalState The additional state values you would like
19585     * added to <var>baseState</var>; this array is not modified.
19586     *
19587     * @return As a convenience, the <var>baseState</var> array you originally
19588     * passed into the function is returned.
19589     *
19590     * @see #onCreateDrawableState(int)
19591     */
19592    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19593        final int N = baseState.length;
19594        int i = N - 1;
19595        while (i >= 0 && baseState[i] == 0) {
19596            i--;
19597        }
19598        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19599        return baseState;
19600    }
19601
19602    /**
19603     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19604     * on all Drawable objects associated with this view.
19605     * <p>
19606     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19607     * attached to this view.
19608     */
19609    @CallSuper
19610    public void jumpDrawablesToCurrentState() {
19611        if (mBackground != null) {
19612            mBackground.jumpToCurrentState();
19613        }
19614        if (mStateListAnimator != null) {
19615            mStateListAnimator.jumpToCurrentState();
19616        }
19617        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19618            mForegroundInfo.mDrawable.jumpToCurrentState();
19619        }
19620    }
19621
19622    /**
19623     * Sets the background color for this view.
19624     * @param color the color of the background
19625     */
19626    @RemotableViewMethod
19627    public void setBackgroundColor(@ColorInt int color) {
19628        if (mBackground instanceof ColorDrawable) {
19629            ((ColorDrawable) mBackground.mutate()).setColor(color);
19630            computeOpaqueFlags();
19631            mBackgroundResource = 0;
19632        } else {
19633            setBackground(new ColorDrawable(color));
19634        }
19635    }
19636
19637    /**
19638     * Set the background to a given resource. The resource should refer to
19639     * a Drawable object or 0 to remove the background.
19640     * @param resid The identifier of the resource.
19641     *
19642     * @attr ref android.R.styleable#View_background
19643     */
19644    @RemotableViewMethod
19645    public void setBackgroundResource(@DrawableRes int resid) {
19646        if (resid != 0 && resid == mBackgroundResource) {
19647            return;
19648        }
19649
19650        Drawable d = null;
19651        if (resid != 0) {
19652            d = mContext.getDrawable(resid);
19653        }
19654        setBackground(d);
19655
19656        mBackgroundResource = resid;
19657    }
19658
19659    /**
19660     * Set the background to a given Drawable, or remove the background. If the
19661     * background has padding, this View's padding is set to the background's
19662     * padding. However, when a background is removed, this View's padding isn't
19663     * touched. If setting the padding is desired, please use
19664     * {@link #setPadding(int, int, int, int)}.
19665     *
19666     * @param background The Drawable to use as the background, or null to remove the
19667     *        background
19668     */
19669    public void setBackground(Drawable background) {
19670        //noinspection deprecation
19671        setBackgroundDrawable(background);
19672    }
19673
19674    /**
19675     * @deprecated use {@link #setBackground(Drawable)} instead
19676     */
19677    @Deprecated
19678    public void setBackgroundDrawable(Drawable background) {
19679        computeOpaqueFlags();
19680
19681        if (background == mBackground) {
19682            return;
19683        }
19684
19685        boolean requestLayout = false;
19686
19687        mBackgroundResource = 0;
19688
19689        /*
19690         * Regardless of whether we're setting a new background or not, we want
19691         * to clear the previous drawable. setVisible first while we still have the callback set.
19692         */
19693        if (mBackground != null) {
19694            if (isAttachedToWindow()) {
19695                mBackground.setVisible(false, false);
19696            }
19697            mBackground.setCallback(null);
19698            unscheduleDrawable(mBackground);
19699        }
19700
19701        if (background != null) {
19702            Rect padding = sThreadLocal.get();
19703            if (padding == null) {
19704                padding = new Rect();
19705                sThreadLocal.set(padding);
19706            }
19707            resetResolvedDrawablesInternal();
19708            background.setLayoutDirection(getLayoutDirection());
19709            if (background.getPadding(padding)) {
19710                resetResolvedPaddingInternal();
19711                switch (background.getLayoutDirection()) {
19712                    case LAYOUT_DIRECTION_RTL:
19713                        mUserPaddingLeftInitial = padding.right;
19714                        mUserPaddingRightInitial = padding.left;
19715                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19716                        break;
19717                    case LAYOUT_DIRECTION_LTR:
19718                    default:
19719                        mUserPaddingLeftInitial = padding.left;
19720                        mUserPaddingRightInitial = padding.right;
19721                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19722                }
19723                mLeftPaddingDefined = false;
19724                mRightPaddingDefined = false;
19725            }
19726
19727            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19728            // if it has a different minimum size, we should layout again
19729            if (mBackground == null
19730                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19731                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19732                requestLayout = true;
19733            }
19734
19735            // Set mBackground before we set this as the callback and start making other
19736            // background drawable state change calls. In particular, the setVisible call below
19737            // can result in drawables attempting to start animations or otherwise invalidate,
19738            // which requires the view set as the callback (us) to recognize the drawable as
19739            // belonging to it as per verifyDrawable.
19740            mBackground = background;
19741            if (background.isStateful()) {
19742                background.setState(getDrawableState());
19743            }
19744            if (isAttachedToWindow()) {
19745                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19746            }
19747
19748            applyBackgroundTint();
19749
19750            // Set callback last, since the view may still be initializing.
19751            background.setCallback(this);
19752
19753            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19754                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19755                requestLayout = true;
19756            }
19757        } else {
19758            /* Remove the background */
19759            mBackground = null;
19760            if ((mViewFlags & WILL_NOT_DRAW) != 0
19761                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19762                mPrivateFlags |= PFLAG_SKIP_DRAW;
19763            }
19764
19765            /*
19766             * When the background is set, we try to apply its padding to this
19767             * View. When the background is removed, we don't touch this View's
19768             * padding. This is noted in the Javadocs. Hence, we don't need to
19769             * requestLayout(), the invalidate() below is sufficient.
19770             */
19771
19772            // The old background's minimum size could have affected this
19773            // View's layout, so let's requestLayout
19774            requestLayout = true;
19775        }
19776
19777        computeOpaqueFlags();
19778
19779        if (requestLayout) {
19780            requestLayout();
19781        }
19782
19783        mBackgroundSizeChanged = true;
19784        invalidate(true);
19785        invalidateOutline();
19786    }
19787
19788    /**
19789     * Gets the background drawable
19790     *
19791     * @return The drawable used as the background for this view, if any.
19792     *
19793     * @see #setBackground(Drawable)
19794     *
19795     * @attr ref android.R.styleable#View_background
19796     */
19797    public Drawable getBackground() {
19798        return mBackground;
19799    }
19800
19801    /**
19802     * Applies a tint to the background drawable. Does not modify the current tint
19803     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19804     * <p>
19805     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
19806     * mutate the drawable and apply the specified tint and tint mode using
19807     * {@link Drawable#setTintList(ColorStateList)}.
19808     *
19809     * @param tint the tint to apply, may be {@code null} to clear tint
19810     *
19811     * @attr ref android.R.styleable#View_backgroundTint
19812     * @see #getBackgroundTintList()
19813     * @see Drawable#setTintList(ColorStateList)
19814     */
19815    public void setBackgroundTintList(@Nullable ColorStateList tint) {
19816        if (mBackgroundTint == null) {
19817            mBackgroundTint = new TintInfo();
19818        }
19819        mBackgroundTint.mTintList = tint;
19820        mBackgroundTint.mHasTintList = true;
19821
19822        applyBackgroundTint();
19823    }
19824
19825    /**
19826     * Return the tint applied to the background drawable, if specified.
19827     *
19828     * @return the tint applied to the background drawable
19829     * @attr ref android.R.styleable#View_backgroundTint
19830     * @see #setBackgroundTintList(ColorStateList)
19831     */
19832    @Nullable
19833    public ColorStateList getBackgroundTintList() {
19834        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
19835    }
19836
19837    /**
19838     * Specifies the blending mode used to apply the tint specified by
19839     * {@link #setBackgroundTintList(ColorStateList)}} to the background
19840     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19841     *
19842     * @param tintMode the blending mode used to apply the tint, may be
19843     *                 {@code null} to clear tint
19844     * @attr ref android.R.styleable#View_backgroundTintMode
19845     * @see #getBackgroundTintMode()
19846     * @see Drawable#setTintMode(PorterDuff.Mode)
19847     */
19848    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19849        if (mBackgroundTint == null) {
19850            mBackgroundTint = new TintInfo();
19851        }
19852        mBackgroundTint.mTintMode = tintMode;
19853        mBackgroundTint.mHasTintMode = true;
19854
19855        applyBackgroundTint();
19856    }
19857
19858    /**
19859     * Return the blending mode used to apply the tint to the background
19860     * drawable, if specified.
19861     *
19862     * @return the blending mode used to apply the tint to the background
19863     *         drawable
19864     * @attr ref android.R.styleable#View_backgroundTintMode
19865     * @see #setBackgroundTintMode(PorterDuff.Mode)
19866     */
19867    @Nullable
19868    public PorterDuff.Mode getBackgroundTintMode() {
19869        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
19870    }
19871
19872    private void applyBackgroundTint() {
19873        if (mBackground != null && mBackgroundTint != null) {
19874            final TintInfo tintInfo = mBackgroundTint;
19875            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19876                mBackground = mBackground.mutate();
19877
19878                if (tintInfo.mHasTintList) {
19879                    mBackground.setTintList(tintInfo.mTintList);
19880                }
19881
19882                if (tintInfo.mHasTintMode) {
19883                    mBackground.setTintMode(tintInfo.mTintMode);
19884                }
19885
19886                // The drawable (or one of its children) may not have been
19887                // stateful before applying the tint, so let's try again.
19888                if (mBackground.isStateful()) {
19889                    mBackground.setState(getDrawableState());
19890                }
19891            }
19892        }
19893    }
19894
19895    /**
19896     * Returns the drawable used as the foreground of this View. The
19897     * foreground drawable, if non-null, is always drawn on top of the view's content.
19898     *
19899     * @return a Drawable or null if no foreground was set
19900     *
19901     * @see #onDrawForeground(Canvas)
19902     */
19903    public Drawable getForeground() {
19904        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19905    }
19906
19907    /**
19908     * Supply a Drawable that is to be rendered on top of all of the content in the view.
19909     *
19910     * @param foreground the Drawable to be drawn on top of the children
19911     *
19912     * @attr ref android.R.styleable#View_foreground
19913     */
19914    public void setForeground(Drawable foreground) {
19915        if (mForegroundInfo == null) {
19916            if (foreground == null) {
19917                // Nothing to do.
19918                return;
19919            }
19920            mForegroundInfo = new ForegroundInfo();
19921        }
19922
19923        if (foreground == mForegroundInfo.mDrawable) {
19924            // Nothing to do
19925            return;
19926        }
19927
19928        if (mForegroundInfo.mDrawable != null) {
19929            if (isAttachedToWindow()) {
19930                mForegroundInfo.mDrawable.setVisible(false, false);
19931            }
19932            mForegroundInfo.mDrawable.setCallback(null);
19933            unscheduleDrawable(mForegroundInfo.mDrawable);
19934        }
19935
19936        mForegroundInfo.mDrawable = foreground;
19937        mForegroundInfo.mBoundsChanged = true;
19938        if (foreground != null) {
19939            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19940                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19941            }
19942            foreground.setLayoutDirection(getLayoutDirection());
19943            if (foreground.isStateful()) {
19944                foreground.setState(getDrawableState());
19945            }
19946            applyForegroundTint();
19947            if (isAttachedToWindow()) {
19948                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19949            }
19950            // Set callback last, since the view may still be initializing.
19951            foreground.setCallback(this);
19952        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
19953            mPrivateFlags |= PFLAG_SKIP_DRAW;
19954        }
19955        requestLayout();
19956        invalidate();
19957    }
19958
19959    /**
19960     * Magic bit used to support features of framework-internal window decor implementation details.
19961     * This used to live exclusively in FrameLayout.
19962     *
19963     * @return true if the foreground should draw inside the padding region or false
19964     *         if it should draw inset by the view's padding
19965     * @hide internal use only; only used by FrameLayout and internal screen layouts.
19966     */
19967    public boolean isForegroundInsidePadding() {
19968        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
19969    }
19970
19971    /**
19972     * Describes how the foreground is positioned.
19973     *
19974     * @return foreground gravity.
19975     *
19976     * @see #setForegroundGravity(int)
19977     *
19978     * @attr ref android.R.styleable#View_foregroundGravity
19979     */
19980    public int getForegroundGravity() {
19981        return mForegroundInfo != null ? mForegroundInfo.mGravity
19982                : Gravity.START | Gravity.TOP;
19983    }
19984
19985    /**
19986     * Describes how the foreground is positioned. Defaults to START and TOP.
19987     *
19988     * @param gravity see {@link android.view.Gravity}
19989     *
19990     * @see #getForegroundGravity()
19991     *
19992     * @attr ref android.R.styleable#View_foregroundGravity
19993     */
19994    public void setForegroundGravity(int gravity) {
19995        if (mForegroundInfo == null) {
19996            mForegroundInfo = new ForegroundInfo();
19997        }
19998
19999        if (mForegroundInfo.mGravity != gravity) {
20000            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20001                gravity |= Gravity.START;
20002            }
20003
20004            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20005                gravity |= Gravity.TOP;
20006            }
20007
20008            mForegroundInfo.mGravity = gravity;
20009            requestLayout();
20010        }
20011    }
20012
20013    /**
20014     * Applies a tint to the foreground drawable. Does not modify the current tint
20015     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20016     * <p>
20017     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20018     * mutate the drawable and apply the specified tint and tint mode using
20019     * {@link Drawable#setTintList(ColorStateList)}.
20020     *
20021     * @param tint the tint to apply, may be {@code null} to clear tint
20022     *
20023     * @attr ref android.R.styleable#View_foregroundTint
20024     * @see #getForegroundTintList()
20025     * @see Drawable#setTintList(ColorStateList)
20026     */
20027    public void setForegroundTintList(@Nullable ColorStateList tint) {
20028        if (mForegroundInfo == null) {
20029            mForegroundInfo = new ForegroundInfo();
20030        }
20031        if (mForegroundInfo.mTintInfo == null) {
20032            mForegroundInfo.mTintInfo = new TintInfo();
20033        }
20034        mForegroundInfo.mTintInfo.mTintList = tint;
20035        mForegroundInfo.mTintInfo.mHasTintList = true;
20036
20037        applyForegroundTint();
20038    }
20039
20040    /**
20041     * Return the tint applied to the foreground drawable, if specified.
20042     *
20043     * @return the tint applied to the foreground drawable
20044     * @attr ref android.R.styleable#View_foregroundTint
20045     * @see #setForegroundTintList(ColorStateList)
20046     */
20047    @Nullable
20048    public ColorStateList getForegroundTintList() {
20049        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20050                ? mForegroundInfo.mTintInfo.mTintList : null;
20051    }
20052
20053    /**
20054     * Specifies the blending mode used to apply the tint specified by
20055     * {@link #setForegroundTintList(ColorStateList)}} to the background
20056     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20057     *
20058     * @param tintMode the blending mode used to apply the tint, may be
20059     *                 {@code null} to clear tint
20060     * @attr ref android.R.styleable#View_foregroundTintMode
20061     * @see #getForegroundTintMode()
20062     * @see Drawable#setTintMode(PorterDuff.Mode)
20063     */
20064    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20065        if (mForegroundInfo == null) {
20066            mForegroundInfo = new ForegroundInfo();
20067        }
20068        if (mForegroundInfo.mTintInfo == null) {
20069            mForegroundInfo.mTintInfo = new TintInfo();
20070        }
20071        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20072        mForegroundInfo.mTintInfo.mHasTintMode = true;
20073
20074        applyForegroundTint();
20075    }
20076
20077    /**
20078     * Return the blending mode used to apply the tint to the foreground
20079     * drawable, if specified.
20080     *
20081     * @return the blending mode used to apply the tint to the foreground
20082     *         drawable
20083     * @attr ref android.R.styleable#View_foregroundTintMode
20084     * @see #setForegroundTintMode(PorterDuff.Mode)
20085     */
20086    @Nullable
20087    public PorterDuff.Mode getForegroundTintMode() {
20088        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20089                ? mForegroundInfo.mTintInfo.mTintMode : null;
20090    }
20091
20092    private void applyForegroundTint() {
20093        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20094                && mForegroundInfo.mTintInfo != null) {
20095            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20096            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20097                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20098
20099                if (tintInfo.mHasTintList) {
20100                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20101                }
20102
20103                if (tintInfo.mHasTintMode) {
20104                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20105                }
20106
20107                // The drawable (or one of its children) may not have been
20108                // stateful before applying the tint, so let's try again.
20109                if (mForegroundInfo.mDrawable.isStateful()) {
20110                    mForegroundInfo.mDrawable.setState(getDrawableState());
20111                }
20112            }
20113        }
20114    }
20115
20116    /**
20117     * Draw any foreground content for this view.
20118     *
20119     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20120     * drawable or other view-specific decorations. The foreground is drawn on top of the
20121     * primary view content.</p>
20122     *
20123     * @param canvas canvas to draw into
20124     */
20125    public void onDrawForeground(Canvas canvas) {
20126        onDrawScrollIndicators(canvas);
20127        onDrawScrollBars(canvas);
20128
20129        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20130        if (foreground != null) {
20131            if (mForegroundInfo.mBoundsChanged) {
20132                mForegroundInfo.mBoundsChanged = false;
20133                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20134                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20135
20136                if (mForegroundInfo.mInsidePadding) {
20137                    selfBounds.set(0, 0, getWidth(), getHeight());
20138                } else {
20139                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20140                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20141                }
20142
20143                final int ld = getLayoutDirection();
20144                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20145                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20146                foreground.setBounds(overlayBounds);
20147            }
20148
20149            foreground.draw(canvas);
20150        }
20151    }
20152
20153    /**
20154     * Sets the padding. The view may add on the space required to display
20155     * the scrollbars, depending on the style and visibility of the scrollbars.
20156     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20157     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20158     * from the values set in this call.
20159     *
20160     * @attr ref android.R.styleable#View_padding
20161     * @attr ref android.R.styleable#View_paddingBottom
20162     * @attr ref android.R.styleable#View_paddingLeft
20163     * @attr ref android.R.styleable#View_paddingRight
20164     * @attr ref android.R.styleable#View_paddingTop
20165     * @param left the left padding in pixels
20166     * @param top the top padding in pixels
20167     * @param right the right padding in pixels
20168     * @param bottom the bottom padding in pixels
20169     */
20170    public void setPadding(int left, int top, int right, int bottom) {
20171        resetResolvedPaddingInternal();
20172
20173        mUserPaddingStart = UNDEFINED_PADDING;
20174        mUserPaddingEnd = UNDEFINED_PADDING;
20175
20176        mUserPaddingLeftInitial = left;
20177        mUserPaddingRightInitial = right;
20178
20179        mLeftPaddingDefined = true;
20180        mRightPaddingDefined = true;
20181
20182        internalSetPadding(left, top, right, bottom);
20183    }
20184
20185    /**
20186     * @hide
20187     */
20188    protected void internalSetPadding(int left, int top, int right, int bottom) {
20189        mUserPaddingLeft = left;
20190        mUserPaddingRight = right;
20191        mUserPaddingBottom = bottom;
20192
20193        final int viewFlags = mViewFlags;
20194        boolean changed = false;
20195
20196        // Common case is there are no scroll bars.
20197        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20198            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20199                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20200                        ? 0 : getVerticalScrollbarWidth();
20201                switch (mVerticalScrollbarPosition) {
20202                    case SCROLLBAR_POSITION_DEFAULT:
20203                        if (isLayoutRtl()) {
20204                            left += offset;
20205                        } else {
20206                            right += offset;
20207                        }
20208                        break;
20209                    case SCROLLBAR_POSITION_RIGHT:
20210                        right += offset;
20211                        break;
20212                    case SCROLLBAR_POSITION_LEFT:
20213                        left += offset;
20214                        break;
20215                }
20216            }
20217            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20218                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20219                        ? 0 : getHorizontalScrollbarHeight();
20220            }
20221        }
20222
20223        if (mPaddingLeft != left) {
20224            changed = true;
20225            mPaddingLeft = left;
20226        }
20227        if (mPaddingTop != top) {
20228            changed = true;
20229            mPaddingTop = top;
20230        }
20231        if (mPaddingRight != right) {
20232            changed = true;
20233            mPaddingRight = right;
20234        }
20235        if (mPaddingBottom != bottom) {
20236            changed = true;
20237            mPaddingBottom = bottom;
20238        }
20239
20240        if (changed) {
20241            requestLayout();
20242            invalidateOutline();
20243        }
20244    }
20245
20246    /**
20247     * Sets the relative padding. The view may add on the space required to display
20248     * the scrollbars, depending on the style and visibility of the scrollbars.
20249     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20250     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20251     * from the values set in this call.
20252     *
20253     * @attr ref android.R.styleable#View_padding
20254     * @attr ref android.R.styleable#View_paddingBottom
20255     * @attr ref android.R.styleable#View_paddingStart
20256     * @attr ref android.R.styleable#View_paddingEnd
20257     * @attr ref android.R.styleable#View_paddingTop
20258     * @param start the start padding in pixels
20259     * @param top the top padding in pixels
20260     * @param end the end padding in pixels
20261     * @param bottom the bottom padding in pixels
20262     */
20263    public void setPaddingRelative(int start, int top, int end, int bottom) {
20264        resetResolvedPaddingInternal();
20265
20266        mUserPaddingStart = start;
20267        mUserPaddingEnd = end;
20268        mLeftPaddingDefined = true;
20269        mRightPaddingDefined = true;
20270
20271        switch(getLayoutDirection()) {
20272            case LAYOUT_DIRECTION_RTL:
20273                mUserPaddingLeftInitial = end;
20274                mUserPaddingRightInitial = start;
20275                internalSetPadding(end, top, start, bottom);
20276                break;
20277            case LAYOUT_DIRECTION_LTR:
20278            default:
20279                mUserPaddingLeftInitial = start;
20280                mUserPaddingRightInitial = end;
20281                internalSetPadding(start, top, end, bottom);
20282        }
20283    }
20284
20285    /**
20286     * Returns the top padding of this view.
20287     *
20288     * @return the top padding in pixels
20289     */
20290    public int getPaddingTop() {
20291        return mPaddingTop;
20292    }
20293
20294    /**
20295     * Returns the bottom 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 bottom padding in pixels
20300     */
20301    public int getPaddingBottom() {
20302        return mPaddingBottom;
20303    }
20304
20305    /**
20306     * Returns the left padding of this view. If there are inset and enabled
20307     * scrollbars, this value may include the space required to display the
20308     * scrollbars as well.
20309     *
20310     * @return the left padding in pixels
20311     */
20312    public int getPaddingLeft() {
20313        if (!isPaddingResolved()) {
20314            resolvePadding();
20315        }
20316        return mPaddingLeft;
20317    }
20318
20319    /**
20320     * Returns the start padding of this view depending on its resolved layout direction.
20321     * If there are inset and enabled scrollbars, this value may include the space
20322     * required to display the scrollbars as well.
20323     *
20324     * @return the start padding in pixels
20325     */
20326    public int getPaddingStart() {
20327        if (!isPaddingResolved()) {
20328            resolvePadding();
20329        }
20330        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20331                mPaddingRight : mPaddingLeft;
20332    }
20333
20334    /**
20335     * Returns the right padding of this view. If there are inset and enabled
20336     * scrollbars, this value may include the space required to display the
20337     * scrollbars as well.
20338     *
20339     * @return the right padding in pixels
20340     */
20341    public int getPaddingRight() {
20342        if (!isPaddingResolved()) {
20343            resolvePadding();
20344        }
20345        return mPaddingRight;
20346    }
20347
20348    /**
20349     * Returns the end padding of this view depending on its resolved layout direction.
20350     * If there are inset and enabled scrollbars, this value may include the space
20351     * required to display the scrollbars as well.
20352     *
20353     * @return the end padding in pixels
20354     */
20355    public int getPaddingEnd() {
20356        if (!isPaddingResolved()) {
20357            resolvePadding();
20358        }
20359        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20360                mPaddingLeft : mPaddingRight;
20361    }
20362
20363    /**
20364     * Return if the padding has been set through relative values
20365     * {@link #setPaddingRelative(int, int, int, int)} or through
20366     * @attr ref android.R.styleable#View_paddingStart or
20367     * @attr ref android.R.styleable#View_paddingEnd
20368     *
20369     * @return true if the padding is relative or false if it is not.
20370     */
20371    public boolean isPaddingRelative() {
20372        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20373    }
20374
20375    Insets computeOpticalInsets() {
20376        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20377    }
20378
20379    /**
20380     * @hide
20381     */
20382    public void resetPaddingToInitialValues() {
20383        if (isRtlCompatibilityMode()) {
20384            mPaddingLeft = mUserPaddingLeftInitial;
20385            mPaddingRight = mUserPaddingRightInitial;
20386            return;
20387        }
20388        if (isLayoutRtl()) {
20389            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20390            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20391        } else {
20392            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20393            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20394        }
20395    }
20396
20397    /**
20398     * @hide
20399     */
20400    public Insets getOpticalInsets() {
20401        if (mLayoutInsets == null) {
20402            mLayoutInsets = computeOpticalInsets();
20403        }
20404        return mLayoutInsets;
20405    }
20406
20407    /**
20408     * Set this view's optical insets.
20409     *
20410     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20411     * property. Views that compute their own optical insets should call it as part of measurement.
20412     * This method does not request layout. If you are setting optical insets outside of
20413     * measure/layout itself you will want to call requestLayout() yourself.
20414     * </p>
20415     * @hide
20416     */
20417    public void setOpticalInsets(Insets insets) {
20418        mLayoutInsets = insets;
20419    }
20420
20421    /**
20422     * Changes the selection state of this view. A view can be selected or not.
20423     * Note that selection is not the same as focus. Views are typically
20424     * selected in the context of an AdapterView like ListView or GridView;
20425     * the selected view is the view that is highlighted.
20426     *
20427     * @param selected true if the view must be selected, false otherwise
20428     */
20429    public void setSelected(boolean selected) {
20430        //noinspection DoubleNegation
20431        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20432            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20433            if (!selected) resetPressedState();
20434            invalidate(true);
20435            refreshDrawableState();
20436            dispatchSetSelected(selected);
20437            if (selected) {
20438                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20439            } else {
20440                notifyViewAccessibilityStateChangedIfNeeded(
20441                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20442            }
20443        }
20444    }
20445
20446    /**
20447     * Dispatch setSelected to all of this View's children.
20448     *
20449     * @see #setSelected(boolean)
20450     *
20451     * @param selected The new selected state
20452     */
20453    protected void dispatchSetSelected(boolean selected) {
20454    }
20455
20456    /**
20457     * Indicates the selection state of this view.
20458     *
20459     * @return true if the view is selected, false otherwise
20460     */
20461    @ViewDebug.ExportedProperty
20462    public boolean isSelected() {
20463        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20464    }
20465
20466    /**
20467     * Changes the activated state of this view. A view can be activated or not.
20468     * Note that activation is not the same as selection.  Selection is
20469     * a transient property, representing the view (hierarchy) the user is
20470     * currently interacting with.  Activation is a longer-term state that the
20471     * user can move views in and out of.  For example, in a list view with
20472     * single or multiple selection enabled, the views in the current selection
20473     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20474     * here.)  The activated state is propagated down to children of the view it
20475     * is set on.
20476     *
20477     * @param activated true if the view must be activated, false otherwise
20478     */
20479    public void setActivated(boolean activated) {
20480        //noinspection DoubleNegation
20481        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20482            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20483            invalidate(true);
20484            refreshDrawableState();
20485            dispatchSetActivated(activated);
20486        }
20487    }
20488
20489    /**
20490     * Dispatch setActivated to all of this View's children.
20491     *
20492     * @see #setActivated(boolean)
20493     *
20494     * @param activated The new activated state
20495     */
20496    protected void dispatchSetActivated(boolean activated) {
20497    }
20498
20499    /**
20500     * Indicates the activation state of this view.
20501     *
20502     * @return true if the view is activated, false otherwise
20503     */
20504    @ViewDebug.ExportedProperty
20505    public boolean isActivated() {
20506        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20507    }
20508
20509    /**
20510     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20511     * observer can be used to get notifications when global events, like
20512     * layout, happen.
20513     *
20514     * The returned ViewTreeObserver observer is not guaranteed to remain
20515     * valid for the lifetime of this View. If the caller of this method keeps
20516     * a long-lived reference to ViewTreeObserver, it should always check for
20517     * the return value of {@link ViewTreeObserver#isAlive()}.
20518     *
20519     * @return The ViewTreeObserver for this view's hierarchy.
20520     */
20521    public ViewTreeObserver getViewTreeObserver() {
20522        if (mAttachInfo != null) {
20523            return mAttachInfo.mTreeObserver;
20524        }
20525        if (mFloatingTreeObserver == null) {
20526            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20527        }
20528        return mFloatingTreeObserver;
20529    }
20530
20531    /**
20532     * <p>Finds the topmost view in the current view hierarchy.</p>
20533     *
20534     * @return the topmost view containing this view
20535     */
20536    public View getRootView() {
20537        if (mAttachInfo != null) {
20538            final View v = mAttachInfo.mRootView;
20539            if (v != null) {
20540                return v;
20541            }
20542        }
20543
20544        View parent = this;
20545
20546        while (parent.mParent != null && parent.mParent instanceof View) {
20547            parent = (View) parent.mParent;
20548        }
20549
20550        return parent;
20551    }
20552
20553    /**
20554     * Transforms a motion event from view-local coordinates to on-screen
20555     * coordinates.
20556     *
20557     * @param ev the view-local motion event
20558     * @return false if the transformation could not be applied
20559     * @hide
20560     */
20561    public boolean toGlobalMotionEvent(MotionEvent ev) {
20562        final AttachInfo info = mAttachInfo;
20563        if (info == null) {
20564            return false;
20565        }
20566
20567        final Matrix m = info.mTmpMatrix;
20568        m.set(Matrix.IDENTITY_MATRIX);
20569        transformMatrixToGlobal(m);
20570        ev.transform(m);
20571        return true;
20572    }
20573
20574    /**
20575     * Transforms a motion event from on-screen coordinates to view-local
20576     * coordinates.
20577     *
20578     * @param ev the on-screen motion event
20579     * @return false if the transformation could not be applied
20580     * @hide
20581     */
20582    public boolean toLocalMotionEvent(MotionEvent ev) {
20583        final AttachInfo info = mAttachInfo;
20584        if (info == null) {
20585            return false;
20586        }
20587
20588        final Matrix m = info.mTmpMatrix;
20589        m.set(Matrix.IDENTITY_MATRIX);
20590        transformMatrixToLocal(m);
20591        ev.transform(m);
20592        return true;
20593    }
20594
20595    /**
20596     * Modifies the input matrix such that it maps view-local coordinates to
20597     * on-screen coordinates.
20598     *
20599     * @param m input matrix to modify
20600     * @hide
20601     */
20602    public void transformMatrixToGlobal(Matrix m) {
20603        final ViewParent parent = mParent;
20604        if (parent instanceof View) {
20605            final View vp = (View) parent;
20606            vp.transformMatrixToGlobal(m);
20607            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20608        } else if (parent instanceof ViewRootImpl) {
20609            final ViewRootImpl vr = (ViewRootImpl) parent;
20610            vr.transformMatrixToGlobal(m);
20611            m.preTranslate(0, -vr.mCurScrollY);
20612        }
20613
20614        m.preTranslate(mLeft, mTop);
20615
20616        if (!hasIdentityMatrix()) {
20617            m.preConcat(getMatrix());
20618        }
20619    }
20620
20621    /**
20622     * Modifies the input matrix such that it maps on-screen coordinates to
20623     * view-local coordinates.
20624     *
20625     * @param m input matrix to modify
20626     * @hide
20627     */
20628    public void transformMatrixToLocal(Matrix m) {
20629        final ViewParent parent = mParent;
20630        if (parent instanceof View) {
20631            final View vp = (View) parent;
20632            vp.transformMatrixToLocal(m);
20633            m.postTranslate(vp.mScrollX, vp.mScrollY);
20634        } else if (parent instanceof ViewRootImpl) {
20635            final ViewRootImpl vr = (ViewRootImpl) parent;
20636            vr.transformMatrixToLocal(m);
20637            m.postTranslate(0, vr.mCurScrollY);
20638        }
20639
20640        m.postTranslate(-mLeft, -mTop);
20641
20642        if (!hasIdentityMatrix()) {
20643            m.postConcat(getInverseMatrix());
20644        }
20645    }
20646
20647    /**
20648     * @hide
20649     */
20650    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20651            @ViewDebug.IntToString(from = 0, to = "x"),
20652            @ViewDebug.IntToString(from = 1, to = "y")
20653    })
20654    public int[] getLocationOnScreen() {
20655        int[] location = new int[2];
20656        getLocationOnScreen(location);
20657        return location;
20658    }
20659
20660    /**
20661     * <p>Computes the coordinates of this view on the screen. The argument
20662     * must be an array of two integers. After the method returns, the array
20663     * contains the x and y location in that order.</p>
20664     *
20665     * @param outLocation an array of two integers in which to hold the coordinates
20666     */
20667    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20668        getLocationInWindow(outLocation);
20669
20670        final AttachInfo info = mAttachInfo;
20671        if (info != null) {
20672            outLocation[0] += info.mWindowLeft;
20673            outLocation[1] += info.mWindowTop;
20674        }
20675    }
20676
20677    /**
20678     * <p>Computes the coordinates of this view in its window. The argument
20679     * must be an array of two integers. After the method returns, the array
20680     * contains the x and y location in that order.</p>
20681     *
20682     * @param outLocation an array of two integers in which to hold the coordinates
20683     */
20684    public void getLocationInWindow(@Size(2) int[] outLocation) {
20685        if (outLocation == null || outLocation.length < 2) {
20686            throw new IllegalArgumentException("outLocation must be an array of two integers");
20687        }
20688
20689        outLocation[0] = 0;
20690        outLocation[1] = 0;
20691
20692        transformFromViewToWindowSpace(outLocation);
20693    }
20694
20695    /** @hide */
20696    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20697        if (inOutLocation == null || inOutLocation.length < 2) {
20698            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20699        }
20700
20701        if (mAttachInfo == null) {
20702            // When the view is not attached to a window, this method does not make sense
20703            inOutLocation[0] = inOutLocation[1] = 0;
20704            return;
20705        }
20706
20707        float position[] = mAttachInfo.mTmpTransformLocation;
20708        position[0] = inOutLocation[0];
20709        position[1] = inOutLocation[1];
20710
20711        if (!hasIdentityMatrix()) {
20712            getMatrix().mapPoints(position);
20713        }
20714
20715        position[0] += mLeft;
20716        position[1] += mTop;
20717
20718        ViewParent viewParent = mParent;
20719        while (viewParent instanceof View) {
20720            final View view = (View) viewParent;
20721
20722            position[0] -= view.mScrollX;
20723            position[1] -= view.mScrollY;
20724
20725            if (!view.hasIdentityMatrix()) {
20726                view.getMatrix().mapPoints(position);
20727            }
20728
20729            position[0] += view.mLeft;
20730            position[1] += view.mTop;
20731
20732            viewParent = view.mParent;
20733         }
20734
20735        if (viewParent instanceof ViewRootImpl) {
20736            // *cough*
20737            final ViewRootImpl vr = (ViewRootImpl) viewParent;
20738            position[1] -= vr.mCurScrollY;
20739        }
20740
20741        inOutLocation[0] = Math.round(position[0]);
20742        inOutLocation[1] = Math.round(position[1]);
20743    }
20744
20745    /**
20746     * @param id the id of the view to be found
20747     * @return the view of the specified id, null if cannot be found
20748     * @hide
20749     */
20750    protected <T extends View> T findViewTraversal(@IdRes int id) {
20751        if (id == mID) {
20752            return (T) this;
20753        }
20754        return null;
20755    }
20756
20757    /**
20758     * @param tag the tag of the view to be found
20759     * @return the view of specified tag, null if cannot be found
20760     * @hide
20761     */
20762    protected <T extends View> T findViewWithTagTraversal(Object tag) {
20763        if (tag != null && tag.equals(mTag)) {
20764            return (T) this;
20765        }
20766        return null;
20767    }
20768
20769    /**
20770     * @param predicate The predicate to evaluate.
20771     * @param childToSkip If not null, ignores this child during the recursive traversal.
20772     * @return The first view that matches the predicate or null.
20773     * @hide
20774     */
20775    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
20776            View childToSkip) {
20777        if (predicate.test(this)) {
20778            return (T) this;
20779        }
20780        return null;
20781    }
20782
20783    /**
20784     * Look for a child view with the given id.  If this view has the given
20785     * id, return this view.
20786     *
20787     * @param id The id to search for.
20788     * @return The view that has the given id in the hierarchy or null
20789     */
20790    @Nullable
20791    public final <T extends View> T findViewById(@IdRes int id) {
20792        if (id < 0) {
20793            return null;
20794        }
20795        return findViewTraversal(id);
20796    }
20797
20798    /**
20799     * Finds a view by its unuque and stable accessibility id.
20800     *
20801     * @param accessibilityId The searched accessibility id.
20802     * @return The found view.
20803     */
20804    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
20805        if (accessibilityId < 0) {
20806            return null;
20807        }
20808        T view = findViewByAccessibilityIdTraversal(accessibilityId);
20809        if (view != null) {
20810            return view.includeForAccessibility() ? view : null;
20811        }
20812        return null;
20813    }
20814
20815    /**
20816     * Performs the traversal to find a view by its unuque and stable accessibility id.
20817     *
20818     * <strong>Note:</strong>This method does not stop at the root namespace
20819     * boundary since the user can touch the screen at an arbitrary location
20820     * potentially crossing the root namespace bounday which will send an
20821     * accessibility event to accessibility services and they should be able
20822     * to obtain the event source. Also accessibility ids are guaranteed to be
20823     * unique in the window.
20824     *
20825     * @param accessibilityId The accessibility id.
20826     * @return The found view.
20827     * @hide
20828     */
20829    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
20830        if (getAccessibilityViewId() == accessibilityId) {
20831            return (T) this;
20832        }
20833        return null;
20834    }
20835
20836    /**
20837     * Look for a child view with the given tag.  If this view has the given
20838     * tag, return this view.
20839     *
20840     * @param tag The tag to search for, using "tag.equals(getTag())".
20841     * @return The View that has the given tag in the hierarchy or null
20842     */
20843    public final <T extends View> T findViewWithTag(Object tag) {
20844        if (tag == null) {
20845            return null;
20846        }
20847        return findViewWithTagTraversal(tag);
20848    }
20849
20850    /**
20851     * Look for a child view that matches the specified predicate.
20852     * If this view matches the predicate, return this view.
20853     *
20854     * @param predicate The predicate to evaluate.
20855     * @return The first view that matches the predicate or null.
20856     * @hide
20857     */
20858    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
20859        return findViewByPredicateTraversal(predicate, null);
20860    }
20861
20862    /**
20863     * Look for a child view that matches the specified predicate,
20864     * starting with the specified view and its descendents and then
20865     * recusively searching the ancestors and siblings of that view
20866     * until this view is reached.
20867     *
20868     * This method is useful in cases where the predicate does not match
20869     * a single unique view (perhaps multiple views use the same id)
20870     * and we are trying to find the view that is "closest" in scope to the
20871     * starting view.
20872     *
20873     * @param start The view to start from.
20874     * @param predicate The predicate to evaluate.
20875     * @return The first view that matches the predicate or null.
20876     * @hide
20877     */
20878    public final <T extends View> T findViewByPredicateInsideOut(
20879            View start, Predicate<View> predicate) {
20880        View childToSkip = null;
20881        for (;;) {
20882            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
20883            if (view != null || start == this) {
20884                return view;
20885            }
20886
20887            ViewParent parent = start.getParent();
20888            if (parent == null || !(parent instanceof View)) {
20889                return null;
20890            }
20891
20892            childToSkip = start;
20893            start = (View) parent;
20894        }
20895    }
20896
20897    /**
20898     * Sets the identifier for this view. The identifier does not have to be
20899     * unique in this view's hierarchy. The identifier should be a positive
20900     * number.
20901     *
20902     * @see #NO_ID
20903     * @see #getId()
20904     * @see #findViewById(int)
20905     *
20906     * @param id a number used to identify the view
20907     *
20908     * @attr ref android.R.styleable#View_id
20909     */
20910    public void setId(@IdRes int id) {
20911        mID = id;
20912        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
20913            mID = generateViewId();
20914        }
20915    }
20916
20917    /**
20918     * {@hide}
20919     *
20920     * @param isRoot true if the view belongs to the root namespace, false
20921     *        otherwise
20922     */
20923    public void setIsRootNamespace(boolean isRoot) {
20924        if (isRoot) {
20925            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
20926        } else {
20927            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
20928        }
20929    }
20930
20931    /**
20932     * {@hide}
20933     *
20934     * @return true if the view belongs to the root namespace, false otherwise
20935     */
20936    public boolean isRootNamespace() {
20937        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
20938    }
20939
20940    /**
20941     * Returns this view's identifier.
20942     *
20943     * @return a positive integer used to identify the view or {@link #NO_ID}
20944     *         if the view has no ID
20945     *
20946     * @see #setId(int)
20947     * @see #findViewById(int)
20948     * @attr ref android.R.styleable#View_id
20949     */
20950    @IdRes
20951    @ViewDebug.CapturedViewProperty
20952    public int getId() {
20953        return mID;
20954    }
20955
20956    /**
20957     * Returns this view's tag.
20958     *
20959     * @return the Object stored in this view as a tag, or {@code null} if not
20960     *         set
20961     *
20962     * @see #setTag(Object)
20963     * @see #getTag(int)
20964     */
20965    @ViewDebug.ExportedProperty
20966    public Object getTag() {
20967        return mTag;
20968    }
20969
20970    /**
20971     * Sets the tag associated with this view. A tag can be used to mark
20972     * a view in its hierarchy and does not have to be unique within the
20973     * hierarchy. Tags can also be used to store data within a view without
20974     * resorting to another data structure.
20975     *
20976     * @param tag an Object to tag the view with
20977     *
20978     * @see #getTag()
20979     * @see #setTag(int, Object)
20980     */
20981    public void setTag(final Object tag) {
20982        mTag = tag;
20983    }
20984
20985    /**
20986     * Returns the tag associated with this view and the specified key.
20987     *
20988     * @param key The key identifying the tag
20989     *
20990     * @return the Object stored in this view as a tag, or {@code null} if not
20991     *         set
20992     *
20993     * @see #setTag(int, Object)
20994     * @see #getTag()
20995     */
20996    public Object getTag(int key) {
20997        if (mKeyedTags != null) return mKeyedTags.get(key);
20998        return null;
20999    }
21000
21001    /**
21002     * Sets a tag associated with this view and a key. A tag can be used
21003     * to mark a view in its hierarchy and does not have to be unique within
21004     * the hierarchy. Tags can also be used to store data within a view
21005     * without resorting to another data structure.
21006     *
21007     * The specified key should be an id declared in the resources of the
21008     * application to ensure it is unique (see the <a
21009     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21010     * Keys identified as belonging to
21011     * the Android framework or not associated with any package will cause
21012     * an {@link IllegalArgumentException} to be thrown.
21013     *
21014     * @param key The key identifying the tag
21015     * @param tag An Object to tag the view with
21016     *
21017     * @throws IllegalArgumentException If they specified key is not valid
21018     *
21019     * @see #setTag(Object)
21020     * @see #getTag(int)
21021     */
21022    public void setTag(int key, final Object tag) {
21023        // If the package id is 0x00 or 0x01, it's either an undefined package
21024        // or a framework id
21025        if ((key >>> 24) < 2) {
21026            throw new IllegalArgumentException("The key must be an application-specific "
21027                    + "resource id.");
21028        }
21029
21030        setKeyedTag(key, tag);
21031    }
21032
21033    /**
21034     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21035     * framework id.
21036     *
21037     * @hide
21038     */
21039    public void setTagInternal(int key, Object tag) {
21040        if ((key >>> 24) != 0x1) {
21041            throw new IllegalArgumentException("The key must be a framework-specific "
21042                    + "resource id.");
21043        }
21044
21045        setKeyedTag(key, tag);
21046    }
21047
21048    private void setKeyedTag(int key, Object tag) {
21049        if (mKeyedTags == null) {
21050            mKeyedTags = new SparseArray<Object>(2);
21051        }
21052
21053        mKeyedTags.put(key, tag);
21054    }
21055
21056    /**
21057     * Prints information about this view in the log output, with the tag
21058     * {@link #VIEW_LOG_TAG}.
21059     *
21060     * @hide
21061     */
21062    public void debug() {
21063        debug(0);
21064    }
21065
21066    /**
21067     * Prints information about this view in the log output, with the tag
21068     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21069     * indentation defined by the <code>depth</code>.
21070     *
21071     * @param depth the indentation level
21072     *
21073     * @hide
21074     */
21075    protected void debug(int depth) {
21076        String output = debugIndent(depth - 1);
21077
21078        output += "+ " + this;
21079        int id = getId();
21080        if (id != -1) {
21081            output += " (id=" + id + ")";
21082        }
21083        Object tag = getTag();
21084        if (tag != null) {
21085            output += " (tag=" + tag + ")";
21086        }
21087        Log.d(VIEW_LOG_TAG, output);
21088
21089        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21090            output = debugIndent(depth) + " FOCUSED";
21091            Log.d(VIEW_LOG_TAG, output);
21092        }
21093
21094        output = debugIndent(depth);
21095        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21096                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21097                + "} ";
21098        Log.d(VIEW_LOG_TAG, output);
21099
21100        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21101                || mPaddingBottom != 0) {
21102            output = debugIndent(depth);
21103            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21104                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21105            Log.d(VIEW_LOG_TAG, output);
21106        }
21107
21108        output = debugIndent(depth);
21109        output += "mMeasureWidth=" + mMeasuredWidth +
21110                " mMeasureHeight=" + mMeasuredHeight;
21111        Log.d(VIEW_LOG_TAG, output);
21112
21113        output = debugIndent(depth);
21114        if (mLayoutParams == null) {
21115            output += "BAD! no layout params";
21116        } else {
21117            output = mLayoutParams.debug(output);
21118        }
21119        Log.d(VIEW_LOG_TAG, output);
21120
21121        output = debugIndent(depth);
21122        output += "flags={";
21123        output += View.printFlags(mViewFlags);
21124        output += "}";
21125        Log.d(VIEW_LOG_TAG, output);
21126
21127        output = debugIndent(depth);
21128        output += "privateFlags={";
21129        output += View.printPrivateFlags(mPrivateFlags);
21130        output += "}";
21131        Log.d(VIEW_LOG_TAG, output);
21132    }
21133
21134    /**
21135     * Creates a string of whitespaces used for indentation.
21136     *
21137     * @param depth the indentation level
21138     * @return a String containing (depth * 2 + 3) * 2 white spaces
21139     *
21140     * @hide
21141     */
21142    protected static String debugIndent(int depth) {
21143        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21144        for (int i = 0; i < (depth * 2) + 3; i++) {
21145            spaces.append(' ').append(' ');
21146        }
21147        return spaces.toString();
21148    }
21149
21150    /**
21151     * <p>Return the offset of the widget's text baseline from the widget's top
21152     * boundary. If this widget does not support baseline alignment, this
21153     * method returns -1. </p>
21154     *
21155     * @return the offset of the baseline within the widget's bounds or -1
21156     *         if baseline alignment is not supported
21157     */
21158    @ViewDebug.ExportedProperty(category = "layout")
21159    public int getBaseline() {
21160        return -1;
21161    }
21162
21163    /**
21164     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21165     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21166     * a layout pass.
21167     *
21168     * @return whether the view hierarchy is currently undergoing a layout pass
21169     */
21170    public boolean isInLayout() {
21171        ViewRootImpl viewRoot = getViewRootImpl();
21172        return (viewRoot != null && viewRoot.isInLayout());
21173    }
21174
21175    /**
21176     * Call this when something has changed which has invalidated the
21177     * layout of this view. This will schedule a layout pass of the view
21178     * tree. This should not be called while the view hierarchy is currently in a layout
21179     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21180     * end of the current layout pass (and then layout will run again) or after the current
21181     * frame is drawn and the next layout occurs.
21182     *
21183     * <p>Subclasses which override this method should call the superclass method to
21184     * handle possible request-during-layout errors correctly.</p>
21185     */
21186    @CallSuper
21187    public void requestLayout() {
21188        if (mMeasureCache != null) mMeasureCache.clear();
21189
21190        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21191            // Only trigger request-during-layout logic if this is the view requesting it,
21192            // not the views in its parent hierarchy
21193            ViewRootImpl viewRoot = getViewRootImpl();
21194            if (viewRoot != null && viewRoot.isInLayout()) {
21195                if (!viewRoot.requestLayoutDuringLayout(this)) {
21196                    return;
21197                }
21198            }
21199            mAttachInfo.mViewRequestingLayout = this;
21200        }
21201
21202        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21203        mPrivateFlags |= PFLAG_INVALIDATED;
21204
21205        if (mParent != null && !mParent.isLayoutRequested()) {
21206            mParent.requestLayout();
21207        }
21208        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21209            mAttachInfo.mViewRequestingLayout = null;
21210        }
21211    }
21212
21213    /**
21214     * Forces this view to be laid out during the next layout pass.
21215     * This method does not call requestLayout() or forceLayout()
21216     * on the parent.
21217     */
21218    public void forceLayout() {
21219        if (mMeasureCache != null) mMeasureCache.clear();
21220
21221        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21222        mPrivateFlags |= PFLAG_INVALIDATED;
21223    }
21224
21225    /**
21226     * <p>
21227     * This is called to find out how big a view should be. The parent
21228     * supplies constraint information in the width and height parameters.
21229     * </p>
21230     *
21231     * <p>
21232     * The actual measurement work of a view is performed in
21233     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21234     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21235     * </p>
21236     *
21237     *
21238     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21239     *        parent
21240     * @param heightMeasureSpec Vertical space requirements as imposed by the
21241     *        parent
21242     *
21243     * @see #onMeasure(int, int)
21244     */
21245    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21246        boolean optical = isLayoutModeOptical(this);
21247        if (optical != isLayoutModeOptical(mParent)) {
21248            Insets insets = getOpticalInsets();
21249            int oWidth  = insets.left + insets.right;
21250            int oHeight = insets.top  + insets.bottom;
21251            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21252            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21253        }
21254
21255        // Suppress sign extension for the low bytes
21256        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21257        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21258
21259        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21260
21261        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21262        // already measured as the correct size. In API 23 and below, this
21263        // extra pass is required to make LinearLayout re-distribute weight.
21264        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21265                || heightMeasureSpec != mOldHeightMeasureSpec;
21266        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21267                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21268        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21269                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21270        final boolean needsLayout = specChanged
21271                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21272
21273        if (forceLayout || needsLayout) {
21274            // first clears the measured dimension flag
21275            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21276
21277            resolveRtlPropertiesIfNeeded();
21278
21279            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21280            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21281                // measure ourselves, this should set the measured dimension flag back
21282                onMeasure(widthMeasureSpec, heightMeasureSpec);
21283                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21284            } else {
21285                long value = mMeasureCache.valueAt(cacheIndex);
21286                // Casting a long to int drops the high 32 bits, no mask needed
21287                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21288                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21289            }
21290
21291            // flag not set, setMeasuredDimension() was not invoked, we raise
21292            // an exception to warn the developer
21293            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21294                throw new IllegalStateException("View with id " + getId() + ": "
21295                        + getClass().getName() + "#onMeasure() did not set the"
21296                        + " measured dimension by calling"
21297                        + " setMeasuredDimension()");
21298            }
21299
21300            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21301        }
21302
21303        mOldWidthMeasureSpec = widthMeasureSpec;
21304        mOldHeightMeasureSpec = heightMeasureSpec;
21305
21306        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21307                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21308    }
21309
21310    /**
21311     * <p>
21312     * Measure the view and its content to determine the measured width and the
21313     * measured height. This method is invoked by {@link #measure(int, int)} and
21314     * should be overridden by subclasses to provide accurate and efficient
21315     * measurement of their contents.
21316     * </p>
21317     *
21318     * <p>
21319     * <strong>CONTRACT:</strong> When overriding this method, you
21320     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21321     * measured width and height of this view. Failure to do so will trigger an
21322     * <code>IllegalStateException</code>, thrown by
21323     * {@link #measure(int, int)}. Calling the superclass'
21324     * {@link #onMeasure(int, int)} is a valid use.
21325     * </p>
21326     *
21327     * <p>
21328     * The base class implementation of measure defaults to the background size,
21329     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21330     * override {@link #onMeasure(int, int)} to provide better measurements of
21331     * their content.
21332     * </p>
21333     *
21334     * <p>
21335     * If this method is overridden, it is the subclass's responsibility to make
21336     * sure the measured height and width are at least the view's minimum height
21337     * and width ({@link #getSuggestedMinimumHeight()} and
21338     * {@link #getSuggestedMinimumWidth()}).
21339     * </p>
21340     *
21341     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21342     *                         The requirements are encoded with
21343     *                         {@link android.view.View.MeasureSpec}.
21344     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21345     *                         The requirements are encoded with
21346     *                         {@link android.view.View.MeasureSpec}.
21347     *
21348     * @see #getMeasuredWidth()
21349     * @see #getMeasuredHeight()
21350     * @see #setMeasuredDimension(int, int)
21351     * @see #getSuggestedMinimumHeight()
21352     * @see #getSuggestedMinimumWidth()
21353     * @see android.view.View.MeasureSpec#getMode(int)
21354     * @see android.view.View.MeasureSpec#getSize(int)
21355     */
21356    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21357        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21358                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21359    }
21360
21361    /**
21362     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21363     * measured width and measured height. Failing to do so will trigger an
21364     * exception at measurement time.</p>
21365     *
21366     * @param measuredWidth The measured width of this view.  May be a complex
21367     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21368     * {@link #MEASURED_STATE_TOO_SMALL}.
21369     * @param measuredHeight The measured height of this view.  May be a complex
21370     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21371     * {@link #MEASURED_STATE_TOO_SMALL}.
21372     */
21373    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21374        boolean optical = isLayoutModeOptical(this);
21375        if (optical != isLayoutModeOptical(mParent)) {
21376            Insets insets = getOpticalInsets();
21377            int opticalWidth  = insets.left + insets.right;
21378            int opticalHeight = insets.top  + insets.bottom;
21379
21380            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21381            measuredHeight += optical ? opticalHeight : -opticalHeight;
21382        }
21383        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21384    }
21385
21386    /**
21387     * Sets the measured dimension without extra processing for things like optical bounds.
21388     * Useful for reapplying consistent values that have already been cooked with adjustments
21389     * for optical bounds, etc. such as those from the measurement cache.
21390     *
21391     * @param measuredWidth The measured width of this view.  May be a complex
21392     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21393     * {@link #MEASURED_STATE_TOO_SMALL}.
21394     * @param measuredHeight The measured height of this view.  May be a complex
21395     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21396     * {@link #MEASURED_STATE_TOO_SMALL}.
21397     */
21398    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21399        mMeasuredWidth = measuredWidth;
21400        mMeasuredHeight = measuredHeight;
21401
21402        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21403    }
21404
21405    /**
21406     * Merge two states as returned by {@link #getMeasuredState()}.
21407     * @param curState The current state as returned from a view or the result
21408     * of combining multiple views.
21409     * @param newState The new view state to combine.
21410     * @return Returns a new integer reflecting the combination of the two
21411     * states.
21412     */
21413    public static int combineMeasuredStates(int curState, int newState) {
21414        return curState | newState;
21415    }
21416
21417    /**
21418     * Version of {@link #resolveSizeAndState(int, int, int)}
21419     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21420     */
21421    public static int resolveSize(int size, int measureSpec) {
21422        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21423    }
21424
21425    /**
21426     * Utility to reconcile a desired size and state, with constraints imposed
21427     * by a MeasureSpec. Will take the desired size, unless a different size
21428     * is imposed by the constraints. The returned value is a compound integer,
21429     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21430     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21431     * resulting size is smaller than the size the view wants to be.
21432     *
21433     * @param size How big the view wants to be.
21434     * @param measureSpec Constraints imposed by the parent.
21435     * @param childMeasuredState Size information bit mask for the view's
21436     *                           children.
21437     * @return Size information bit mask as defined by
21438     *         {@link #MEASURED_SIZE_MASK} and
21439     *         {@link #MEASURED_STATE_TOO_SMALL}.
21440     */
21441    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21442        final int specMode = MeasureSpec.getMode(measureSpec);
21443        final int specSize = MeasureSpec.getSize(measureSpec);
21444        final int result;
21445        switch (specMode) {
21446            case MeasureSpec.AT_MOST:
21447                if (specSize < size) {
21448                    result = specSize | MEASURED_STATE_TOO_SMALL;
21449                } else {
21450                    result = size;
21451                }
21452                break;
21453            case MeasureSpec.EXACTLY:
21454                result = specSize;
21455                break;
21456            case MeasureSpec.UNSPECIFIED:
21457            default:
21458                result = size;
21459        }
21460        return result | (childMeasuredState & MEASURED_STATE_MASK);
21461    }
21462
21463    /**
21464     * Utility to return a default size. Uses the supplied size if the
21465     * MeasureSpec imposed no constraints. Will get larger if allowed
21466     * by the MeasureSpec.
21467     *
21468     * @param size Default size for this view
21469     * @param measureSpec Constraints imposed by the parent
21470     * @return The size this view should be.
21471     */
21472    public static int getDefaultSize(int size, int measureSpec) {
21473        int result = size;
21474        int specMode = MeasureSpec.getMode(measureSpec);
21475        int specSize = MeasureSpec.getSize(measureSpec);
21476
21477        switch (specMode) {
21478        case MeasureSpec.UNSPECIFIED:
21479            result = size;
21480            break;
21481        case MeasureSpec.AT_MOST:
21482        case MeasureSpec.EXACTLY:
21483            result = specSize;
21484            break;
21485        }
21486        return result;
21487    }
21488
21489    /**
21490     * Returns the suggested minimum height that the view should use. This
21491     * returns the maximum of the view's minimum height
21492     * and the background's minimum height
21493     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21494     * <p>
21495     * When being used in {@link #onMeasure(int, int)}, the caller should still
21496     * ensure the returned height is within the requirements of the parent.
21497     *
21498     * @return The suggested minimum height of the view.
21499     */
21500    protected int getSuggestedMinimumHeight() {
21501        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21502
21503    }
21504
21505    /**
21506     * Returns the suggested minimum width that the view should use. This
21507     * returns the maximum of the view's minimum width
21508     * and the background's minimum width
21509     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21510     * <p>
21511     * When being used in {@link #onMeasure(int, int)}, the caller should still
21512     * ensure the returned width is within the requirements of the parent.
21513     *
21514     * @return The suggested minimum width of the view.
21515     */
21516    protected int getSuggestedMinimumWidth() {
21517        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21518    }
21519
21520    /**
21521     * Returns the minimum height of the view.
21522     *
21523     * @return the minimum height the view will try to be, in pixels
21524     *
21525     * @see #setMinimumHeight(int)
21526     *
21527     * @attr ref android.R.styleable#View_minHeight
21528     */
21529    public int getMinimumHeight() {
21530        return mMinHeight;
21531    }
21532
21533    /**
21534     * Sets the minimum height of the view. It is not guaranteed the view will
21535     * be able to achieve this minimum height (for example, if its parent layout
21536     * constrains it with less available height).
21537     *
21538     * @param minHeight The minimum height the view will try to be, in pixels
21539     *
21540     * @see #getMinimumHeight()
21541     *
21542     * @attr ref android.R.styleable#View_minHeight
21543     */
21544    @RemotableViewMethod
21545    public void setMinimumHeight(int minHeight) {
21546        mMinHeight = minHeight;
21547        requestLayout();
21548    }
21549
21550    /**
21551     * Returns the minimum width of the view.
21552     *
21553     * @return the minimum width the view will try to be, in pixels
21554     *
21555     * @see #setMinimumWidth(int)
21556     *
21557     * @attr ref android.R.styleable#View_minWidth
21558     */
21559    public int getMinimumWidth() {
21560        return mMinWidth;
21561    }
21562
21563    /**
21564     * Sets the minimum width of the view. It is not guaranteed the view will
21565     * be able to achieve this minimum width (for example, if its parent layout
21566     * constrains it with less available width).
21567     *
21568     * @param minWidth The minimum width the view will try to be, in pixels
21569     *
21570     * @see #getMinimumWidth()
21571     *
21572     * @attr ref android.R.styleable#View_minWidth
21573     */
21574    public void setMinimumWidth(int minWidth) {
21575        mMinWidth = minWidth;
21576        requestLayout();
21577
21578    }
21579
21580    /**
21581     * Get the animation currently associated with this view.
21582     *
21583     * @return The animation that is currently playing or
21584     *         scheduled to play for this view.
21585     */
21586    public Animation getAnimation() {
21587        return mCurrentAnimation;
21588    }
21589
21590    /**
21591     * Start the specified animation now.
21592     *
21593     * @param animation the animation to start now
21594     */
21595    public void startAnimation(Animation animation) {
21596        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21597        setAnimation(animation);
21598        invalidateParentCaches();
21599        invalidate(true);
21600    }
21601
21602    /**
21603     * Cancels any animations for this view.
21604     */
21605    public void clearAnimation() {
21606        if (mCurrentAnimation != null) {
21607            mCurrentAnimation.detach();
21608        }
21609        mCurrentAnimation = null;
21610        invalidateParentIfNeeded();
21611    }
21612
21613    /**
21614     * Sets the next animation to play for this view.
21615     * If you want the animation to play immediately, use
21616     * {@link #startAnimation(android.view.animation.Animation)} instead.
21617     * This method provides allows fine-grained
21618     * control over the start time and invalidation, but you
21619     * must make sure that 1) the animation has a start time set, and
21620     * 2) the view's parent (which controls animations on its children)
21621     * will be invalidated when the animation is supposed to
21622     * start.
21623     *
21624     * @param animation The next animation, or null.
21625     */
21626    public void setAnimation(Animation animation) {
21627        mCurrentAnimation = animation;
21628
21629        if (animation != null) {
21630            // If the screen is off assume the animation start time is now instead of
21631            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21632            // would cause the animation to start when the screen turns back on
21633            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21634                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21635                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21636            }
21637            animation.reset();
21638        }
21639    }
21640
21641    /**
21642     * Invoked by a parent ViewGroup to notify the start of the animation
21643     * currently associated with this view. If you override this method,
21644     * always call super.onAnimationStart();
21645     *
21646     * @see #setAnimation(android.view.animation.Animation)
21647     * @see #getAnimation()
21648     */
21649    @CallSuper
21650    protected void onAnimationStart() {
21651        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21652    }
21653
21654    /**
21655     * Invoked by a parent ViewGroup to notify the end of the animation
21656     * currently associated with this view. If you override this method,
21657     * always call super.onAnimationEnd();
21658     *
21659     * @see #setAnimation(android.view.animation.Animation)
21660     * @see #getAnimation()
21661     */
21662    @CallSuper
21663    protected void onAnimationEnd() {
21664        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21665    }
21666
21667    /**
21668     * Invoked if there is a Transform that involves alpha. Subclass that can
21669     * draw themselves with the specified alpha should return true, and then
21670     * respect that alpha when their onDraw() is called. If this returns false
21671     * then the view may be redirected to draw into an offscreen buffer to
21672     * fulfill the request, which will look fine, but may be slower than if the
21673     * subclass handles it internally. The default implementation returns false.
21674     *
21675     * @param alpha The alpha (0..255) to apply to the view's drawing
21676     * @return true if the view can draw with the specified alpha.
21677     */
21678    protected boolean onSetAlpha(int alpha) {
21679        return false;
21680    }
21681
21682    /**
21683     * This is used by the RootView to perform an optimization when
21684     * the view hierarchy contains one or several SurfaceView.
21685     * SurfaceView is always considered transparent, but its children are not,
21686     * therefore all View objects remove themselves from the global transparent
21687     * region (passed as a parameter to this function).
21688     *
21689     * @param region The transparent region for this ViewAncestor (window).
21690     *
21691     * @return Returns true if the effective visibility of the view at this
21692     * point is opaque, regardless of the transparent region; returns false
21693     * if it is possible for underlying windows to be seen behind the view.
21694     *
21695     * {@hide}
21696     */
21697    public boolean gatherTransparentRegion(Region region) {
21698        final AttachInfo attachInfo = mAttachInfo;
21699        if (region != null && attachInfo != null) {
21700            final int pflags = mPrivateFlags;
21701            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
21702                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
21703                // remove it from the transparent region.
21704                final int[] location = attachInfo.mTransparentLocation;
21705                getLocationInWindow(location);
21706                // When a view has Z value, then it will be better to leave some area below the view
21707                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
21708                // the bottom part needs more offset than the left, top and right parts due to the
21709                // spot light effects.
21710                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
21711                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
21712                        location[0] + mRight - mLeft + shadowOffset,
21713                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
21714            } else {
21715                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
21716                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
21717                    // the background drawable's non-transparent parts from this transparent region.
21718                    applyDrawableToTransparentRegion(mBackground, region);
21719                }
21720                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
21721                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
21722                    // Similarly, we remove the foreground drawable's non-transparent parts.
21723                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
21724                }
21725            }
21726        }
21727        return true;
21728    }
21729
21730    /**
21731     * Play a sound effect for this view.
21732     *
21733     * <p>The framework will play sound effects for some built in actions, such as
21734     * clicking, but you may wish to play these effects in your widget,
21735     * for instance, for internal navigation.
21736     *
21737     * <p>The sound effect will only be played if sound effects are enabled by the user, and
21738     * {@link #isSoundEffectsEnabled()} is true.
21739     *
21740     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
21741     */
21742    public void playSoundEffect(int soundConstant) {
21743        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
21744            return;
21745        }
21746        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
21747    }
21748
21749    /**
21750     * BZZZTT!!1!
21751     *
21752     * <p>Provide haptic feedback to the user for this view.
21753     *
21754     * <p>The framework will provide haptic feedback for some built in actions,
21755     * such as long presses, but you may wish to provide feedback for your
21756     * own widget.
21757     *
21758     * <p>The feedback will only be performed if
21759     * {@link #isHapticFeedbackEnabled()} is true.
21760     *
21761     * @param feedbackConstant One of the constants defined in
21762     * {@link HapticFeedbackConstants}
21763     */
21764    public boolean performHapticFeedback(int feedbackConstant) {
21765        return performHapticFeedback(feedbackConstant, 0);
21766    }
21767
21768    /**
21769     * BZZZTT!!1!
21770     *
21771     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
21772     *
21773     * @param feedbackConstant One of the constants defined in
21774     * {@link HapticFeedbackConstants}
21775     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
21776     */
21777    public boolean performHapticFeedback(int feedbackConstant, int flags) {
21778        if (mAttachInfo == null) {
21779            return false;
21780        }
21781        //noinspection SimplifiableIfStatement
21782        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
21783                && !isHapticFeedbackEnabled()) {
21784            return false;
21785        }
21786        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
21787                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
21788    }
21789
21790    /**
21791     * Request that the visibility of the status bar or other screen/window
21792     * decorations be changed.
21793     *
21794     * <p>This method is used to put the over device UI into temporary modes
21795     * where the user's attention is focused more on the application content,
21796     * by dimming or hiding surrounding system affordances.  This is typically
21797     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
21798     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
21799     * to be placed behind the action bar (and with these flags other system
21800     * affordances) so that smooth transitions between hiding and showing them
21801     * can be done.
21802     *
21803     * <p>Two representative examples of the use of system UI visibility is
21804     * implementing a content browsing application (like a magazine reader)
21805     * and a video playing application.
21806     *
21807     * <p>The first code shows a typical implementation of a View in a content
21808     * browsing application.  In this implementation, the application goes
21809     * into a content-oriented mode by hiding the status bar and action bar,
21810     * and putting the navigation elements into lights out mode.  The user can
21811     * then interact with content while in this mode.  Such an application should
21812     * provide an easy way for the user to toggle out of the mode (such as to
21813     * check information in the status bar or access notifications).  In the
21814     * implementation here, this is done simply by tapping on the content.
21815     *
21816     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
21817     *      content}
21818     *
21819     * <p>This second code sample shows a typical implementation of a View
21820     * in a video playing application.  In this situation, while the video is
21821     * playing the application would like to go into a complete full-screen mode,
21822     * to use as much of the display as possible for the video.  When in this state
21823     * the user can not interact with the application; the system intercepts
21824     * touching on the screen to pop the UI out of full screen mode.  See
21825     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
21826     *
21827     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
21828     *      content}
21829     *
21830     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21831     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21832     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21833     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21834     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21835     */
21836    public void setSystemUiVisibility(int visibility) {
21837        if (visibility != mSystemUiVisibility) {
21838            mSystemUiVisibility = visibility;
21839            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21840                mParent.recomputeViewAttributes(this);
21841            }
21842        }
21843    }
21844
21845    /**
21846     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
21847     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21848     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21849     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21850     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21851     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21852     */
21853    public int getSystemUiVisibility() {
21854        return mSystemUiVisibility;
21855    }
21856
21857    /**
21858     * Returns the current system UI visibility that is currently set for
21859     * the entire window.  This is the combination of the
21860     * {@link #setSystemUiVisibility(int)} values supplied by all of the
21861     * views in the window.
21862     */
21863    public int getWindowSystemUiVisibility() {
21864        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
21865    }
21866
21867    /**
21868     * Override to find out when the window's requested system UI visibility
21869     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
21870     * This is different from the callbacks received through
21871     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
21872     * in that this is only telling you about the local request of the window,
21873     * not the actual values applied by the system.
21874     */
21875    public void onWindowSystemUiVisibilityChanged(int visible) {
21876    }
21877
21878    /**
21879     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
21880     * the view hierarchy.
21881     */
21882    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
21883        onWindowSystemUiVisibilityChanged(visible);
21884    }
21885
21886    /**
21887     * Set a listener to receive callbacks when the visibility of the system bar changes.
21888     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
21889     */
21890    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
21891        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
21892        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21893            mParent.recomputeViewAttributes(this);
21894        }
21895    }
21896
21897    /**
21898     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
21899     * the view hierarchy.
21900     */
21901    public void dispatchSystemUiVisibilityChanged(int visibility) {
21902        ListenerInfo li = mListenerInfo;
21903        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
21904            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
21905                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
21906        }
21907    }
21908
21909    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
21910        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
21911        if (val != mSystemUiVisibility) {
21912            setSystemUiVisibility(val);
21913            return true;
21914        }
21915        return false;
21916    }
21917
21918    /** @hide */
21919    public void setDisabledSystemUiVisibility(int flags) {
21920        if (mAttachInfo != null) {
21921            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
21922                mAttachInfo.mDisabledSystemUiVisibility = flags;
21923                if (mParent != null) {
21924                    mParent.recomputeViewAttributes(this);
21925                }
21926            }
21927        }
21928    }
21929
21930    /**
21931     * Creates an image that the system displays during the drag and drop
21932     * operation. This is called a &quot;drag shadow&quot;. The default implementation
21933     * for a DragShadowBuilder based on a View returns an image that has exactly the same
21934     * appearance as the given View. The default also positions the center of the drag shadow
21935     * directly under the touch point. If no View is provided (the constructor with no parameters
21936     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
21937     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
21938     * default is an invisible drag shadow.
21939     * <p>
21940     * You are not required to use the View you provide to the constructor as the basis of the
21941     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
21942     * anything you want as the drag shadow.
21943     * </p>
21944     * <p>
21945     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
21946     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
21947     *  size and position of the drag shadow. It uses this data to construct a
21948     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
21949     *  so that your application can draw the shadow image in the Canvas.
21950     * </p>
21951     *
21952     * <div class="special reference">
21953     * <h3>Developer Guides</h3>
21954     * <p>For a guide to implementing drag and drop features, read the
21955     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21956     * </div>
21957     */
21958    public static class DragShadowBuilder {
21959        private final WeakReference<View> mView;
21960
21961        /**
21962         * Constructs a shadow image builder based on a View. By default, the resulting drag
21963         * shadow will have the same appearance and dimensions as the View, with the touch point
21964         * over the center of the View.
21965         * @param view A View. Any View in scope can be used.
21966         */
21967        public DragShadowBuilder(View view) {
21968            mView = new WeakReference<View>(view);
21969        }
21970
21971        /**
21972         * Construct a shadow builder object with no associated View.  This
21973         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
21974         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
21975         * to supply the drag shadow's dimensions and appearance without
21976         * reference to any View object. If they are not overridden, then the result is an
21977         * invisible drag shadow.
21978         */
21979        public DragShadowBuilder() {
21980            mView = new WeakReference<View>(null);
21981        }
21982
21983        /**
21984         * Returns the View object that had been passed to the
21985         * {@link #View.DragShadowBuilder(View)}
21986         * constructor.  If that View parameter was {@code null} or if the
21987         * {@link #View.DragShadowBuilder()}
21988         * constructor was used to instantiate the builder object, this method will return
21989         * null.
21990         *
21991         * @return The View object associate with this builder object.
21992         */
21993        @SuppressWarnings({"JavadocReference"})
21994        final public View getView() {
21995            return mView.get();
21996        }
21997
21998        /**
21999         * Provides the metrics for the shadow image. These include the dimensions of
22000         * the shadow image, and the point within that shadow that should
22001         * be centered under the touch location while dragging.
22002         * <p>
22003         * The default implementation sets the dimensions of the shadow to be the
22004         * same as the dimensions of the View itself and centers the shadow under
22005         * the touch point.
22006         * </p>
22007         *
22008         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22009         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22010         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22011         * image.
22012         *
22013         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22014         * shadow image that should be underneath the touch point during the drag and drop
22015         * operation. Your application must set {@link android.graphics.Point#x} to the
22016         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22017         */
22018        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22019            final View view = mView.get();
22020            if (view != null) {
22021                outShadowSize.set(view.getWidth(), view.getHeight());
22022                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22023            } else {
22024                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22025            }
22026        }
22027
22028        /**
22029         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22030         * based on the dimensions it received from the
22031         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22032         *
22033         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22034         */
22035        public void onDrawShadow(Canvas canvas) {
22036            final View view = mView.get();
22037            if (view != null) {
22038                view.draw(canvas);
22039            } else {
22040                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22041            }
22042        }
22043    }
22044
22045    /**
22046     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22047     * startDragAndDrop()} for newer platform versions.
22048     */
22049    @Deprecated
22050    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22051                                   Object myLocalState, int flags) {
22052        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22053    }
22054
22055    /**
22056     * Starts a drag and drop operation. When your application calls this method, it passes a
22057     * {@link android.view.View.DragShadowBuilder} object to the system. The
22058     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22059     * to get metrics for the drag shadow, and then calls the object's
22060     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22061     * <p>
22062     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22063     *  drag events to all the View objects in your application that are currently visible. It does
22064     *  this either by calling the View object's drag listener (an implementation of
22065     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22066     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22067     *  Both are passed a {@link android.view.DragEvent} object that has a
22068     *  {@link android.view.DragEvent#getAction()} value of
22069     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22070     * </p>
22071     * <p>
22072     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22073     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22074     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22075     * to the View the user selected for dragging.
22076     * </p>
22077     * @param data A {@link android.content.ClipData} object pointing to the data to be
22078     * transferred by the drag and drop operation.
22079     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22080     * drag shadow.
22081     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22082     * drop operation. When dispatching drag events to views in the same activity this object
22083     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22084     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22085     * will return null).
22086     * <p>
22087     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22088     * to the target Views. For example, it can contain flags that differentiate between a
22089     * a copy operation and a move operation.
22090     * </p>
22091     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22092     * flags, or any combination of the following:
22093     *     <ul>
22094     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22095     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22096     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22097     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22098     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22099     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22100     *     </ul>
22101     * @return {@code true} if the method completes successfully, or
22102     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22103     * do a drag, and so no drag operation is in progress.
22104     */
22105    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22106            Object myLocalState, int flags) {
22107        if (ViewDebug.DEBUG_DRAG) {
22108            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22109        }
22110        if (mAttachInfo == null) {
22111            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22112            return false;
22113        }
22114
22115        if (data != null) {
22116            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22117        }
22118
22119        boolean okay = false;
22120
22121        Point shadowSize = new Point();
22122        Point shadowTouchPoint = new Point();
22123        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22124
22125        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22126                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22127            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22128        }
22129
22130        if (ViewDebug.DEBUG_DRAG) {
22131            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22132                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22133        }
22134        if (mAttachInfo.mDragSurface != null) {
22135            mAttachInfo.mDragSurface.release();
22136        }
22137        mAttachInfo.mDragSurface = new Surface();
22138        try {
22139            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22140                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22141            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22142                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22143            if (mAttachInfo.mDragToken != null) {
22144                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22145                try {
22146                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22147                    shadowBuilder.onDrawShadow(canvas);
22148                } finally {
22149                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22150                }
22151
22152                final ViewRootImpl root = getViewRootImpl();
22153
22154                // Cache the local state object for delivery with DragEvents
22155                root.setLocalDragState(myLocalState);
22156
22157                // repurpose 'shadowSize' for the last touch point
22158                root.getLastTouchPoint(shadowSize);
22159
22160                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22161                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22162                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22163                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22164            }
22165        } catch (Exception e) {
22166            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22167            mAttachInfo.mDragSurface.destroy();
22168            mAttachInfo.mDragSurface = null;
22169        }
22170
22171        return okay;
22172    }
22173
22174    /**
22175     * Cancels an ongoing drag and drop operation.
22176     * <p>
22177     * A {@link android.view.DragEvent} object with
22178     * {@link android.view.DragEvent#getAction()} value of
22179     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22180     * {@link android.view.DragEvent#getResult()} value of {@code false}
22181     * will be sent to every
22182     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22183     * even if they are not currently visible.
22184     * </p>
22185     * <p>
22186     * This method can be called on any View in the same window as the View on which
22187     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22188     * was called.
22189     * </p>
22190     */
22191    public final void cancelDragAndDrop() {
22192        if (ViewDebug.DEBUG_DRAG) {
22193            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22194        }
22195        if (mAttachInfo == null) {
22196            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22197            return;
22198        }
22199        if (mAttachInfo.mDragToken != null) {
22200            try {
22201                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22202            } catch (Exception e) {
22203                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22204            }
22205            mAttachInfo.mDragToken = null;
22206        } else {
22207            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22208        }
22209    }
22210
22211    /**
22212     * Updates the drag shadow for the ongoing drag and drop operation.
22213     *
22214     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22215     * new drag shadow.
22216     */
22217    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22218        if (ViewDebug.DEBUG_DRAG) {
22219            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22220        }
22221        if (mAttachInfo == null) {
22222            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22223            return;
22224        }
22225        if (mAttachInfo.mDragToken != null) {
22226            try {
22227                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22228                try {
22229                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22230                    shadowBuilder.onDrawShadow(canvas);
22231                } finally {
22232                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22233                }
22234            } catch (Exception e) {
22235                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22236            }
22237        } else {
22238            Log.e(VIEW_LOG_TAG, "No active drag");
22239        }
22240    }
22241
22242    /**
22243     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22244     * between {startX, startY} and the new cursor positon.
22245     * @param startX horizontal coordinate where the move started.
22246     * @param startY vertical coordinate where the move started.
22247     * @return whether moving was started successfully.
22248     * @hide
22249     */
22250    public final boolean startMovingTask(float startX, float startY) {
22251        if (ViewDebug.DEBUG_POSITIONING) {
22252            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22253        }
22254        try {
22255            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22256        } catch (RemoteException e) {
22257            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22258        }
22259        return false;
22260    }
22261
22262    /**
22263     * Handles drag events sent by the system following a call to
22264     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22265     * startDragAndDrop()}.
22266     *<p>
22267     * When the system calls this method, it passes a
22268     * {@link android.view.DragEvent} object. A call to
22269     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22270     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22271     * operation.
22272     * @param event The {@link android.view.DragEvent} sent by the system.
22273     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22274     * in DragEvent, indicating the type of drag event represented by this object.
22275     * @return {@code true} if the method was successful, otherwise {@code false}.
22276     * <p>
22277     *  The method should return {@code true} in response to an action type of
22278     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22279     *  operation.
22280     * </p>
22281     * <p>
22282     *  The method should also return {@code true} in response to an action type of
22283     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22284     *  {@code false} if it didn't.
22285     * </p>
22286     * <p>
22287     *  For all other events, the return value is ignored.
22288     * </p>
22289     */
22290    public boolean onDragEvent(DragEvent event) {
22291        return false;
22292    }
22293
22294    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22295    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22296        return callDragEventHandler(event);
22297    }
22298
22299    /**
22300     * Detects if this View is enabled and has a drag event listener.
22301     * If both are true, then it calls the drag event listener with the
22302     * {@link android.view.DragEvent} it received. If the drag event listener returns
22303     * {@code true}, then dispatchDragEvent() returns {@code true}.
22304     * <p>
22305     * For all other cases, the method calls the
22306     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22307     * method and returns its result.
22308     * </p>
22309     * <p>
22310     * This ensures that a drag event is always consumed, even if the View does not have a drag
22311     * event listener. However, if the View has a listener and the listener returns true, then
22312     * onDragEvent() is not called.
22313     * </p>
22314     */
22315    public boolean dispatchDragEvent(DragEvent event) {
22316        event.mEventHandlerWasCalled = true;
22317        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22318            event.mAction == DragEvent.ACTION_DROP) {
22319            // About to deliver an event with coordinates to this view. Notify that now this view
22320            // has drag focus. This will send exit/enter events as needed.
22321            getViewRootImpl().setDragFocus(this, event);
22322        }
22323        return callDragEventHandler(event);
22324    }
22325
22326    final boolean callDragEventHandler(DragEvent event) {
22327        final boolean result;
22328
22329        ListenerInfo li = mListenerInfo;
22330        //noinspection SimplifiableIfStatement
22331        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22332                && li.mOnDragListener.onDrag(this, event)) {
22333            result = true;
22334        } else {
22335            result = onDragEvent(event);
22336        }
22337
22338        switch (event.mAction) {
22339            case DragEvent.ACTION_DRAG_ENTERED: {
22340                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22341                refreshDrawableState();
22342            } break;
22343            case DragEvent.ACTION_DRAG_EXITED: {
22344                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22345                refreshDrawableState();
22346            } break;
22347            case DragEvent.ACTION_DRAG_ENDED: {
22348                mPrivateFlags2 &= ~View.DRAG_MASK;
22349                refreshDrawableState();
22350            } break;
22351        }
22352
22353        return result;
22354    }
22355
22356    boolean canAcceptDrag() {
22357        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22358    }
22359
22360    /**
22361     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22362     * it is ever exposed at all.
22363     * @hide
22364     */
22365    public void onCloseSystemDialogs(String reason) {
22366    }
22367
22368    /**
22369     * Given a Drawable whose bounds have been set to draw into this view,
22370     * update a Region being computed for
22371     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22372     * that any non-transparent parts of the Drawable are removed from the
22373     * given transparent region.
22374     *
22375     * @param dr The Drawable whose transparency is to be applied to the region.
22376     * @param region A Region holding the current transparency information,
22377     * where any parts of the region that are set are considered to be
22378     * transparent.  On return, this region will be modified to have the
22379     * transparency information reduced by the corresponding parts of the
22380     * Drawable that are not transparent.
22381     * {@hide}
22382     */
22383    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22384        if (DBG) {
22385            Log.i("View", "Getting transparent region for: " + this);
22386        }
22387        final Region r = dr.getTransparentRegion();
22388        final Rect db = dr.getBounds();
22389        final AttachInfo attachInfo = mAttachInfo;
22390        if (r != null && attachInfo != null) {
22391            final int w = getRight()-getLeft();
22392            final int h = getBottom()-getTop();
22393            if (db.left > 0) {
22394                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22395                r.op(0, 0, db.left, h, Region.Op.UNION);
22396            }
22397            if (db.right < w) {
22398                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22399                r.op(db.right, 0, w, h, Region.Op.UNION);
22400            }
22401            if (db.top > 0) {
22402                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22403                r.op(0, 0, w, db.top, Region.Op.UNION);
22404            }
22405            if (db.bottom < h) {
22406                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22407                r.op(0, db.bottom, w, h, Region.Op.UNION);
22408            }
22409            final int[] location = attachInfo.mTransparentLocation;
22410            getLocationInWindow(location);
22411            r.translate(location[0], location[1]);
22412            region.op(r, Region.Op.INTERSECT);
22413        } else {
22414            region.op(db, Region.Op.DIFFERENCE);
22415        }
22416    }
22417
22418    private void checkForLongClick(int delayOffset, float x, float y) {
22419        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22420            mHasPerformedLongPress = false;
22421
22422            if (mPendingCheckForLongPress == null) {
22423                mPendingCheckForLongPress = new CheckForLongPress();
22424            }
22425            mPendingCheckForLongPress.setAnchor(x, y);
22426            mPendingCheckForLongPress.rememberWindowAttachCount();
22427            mPendingCheckForLongPress.rememberPressedState();
22428            postDelayed(mPendingCheckForLongPress,
22429                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22430        }
22431    }
22432
22433    /**
22434     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22435     * LayoutInflater} class, which provides a full range of options for view inflation.
22436     *
22437     * @param context The Context object for your activity or application.
22438     * @param resource The resource ID to inflate
22439     * @param root A view group that will be the parent.  Used to properly inflate the
22440     * layout_* parameters.
22441     * @see LayoutInflater
22442     */
22443    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22444        LayoutInflater factory = LayoutInflater.from(context);
22445        return factory.inflate(resource, root);
22446    }
22447
22448    /**
22449     * Scroll the view with standard behavior for scrolling beyond the normal
22450     * content boundaries. Views that call this method should override
22451     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22452     * results of an over-scroll operation.
22453     *
22454     * Views can use this method to handle any touch or fling-based scrolling.
22455     *
22456     * @param deltaX Change in X in pixels
22457     * @param deltaY Change in Y in pixels
22458     * @param scrollX Current X scroll value in pixels before applying deltaX
22459     * @param scrollY Current Y scroll value in pixels before applying deltaY
22460     * @param scrollRangeX Maximum content scroll range along the X axis
22461     * @param scrollRangeY Maximum content scroll range along the Y axis
22462     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22463     *          along the X axis.
22464     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22465     *          along the Y axis.
22466     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22467     * @return true if scrolling was clamped to an over-scroll boundary along either
22468     *          axis, false otherwise.
22469     */
22470    @SuppressWarnings({"UnusedParameters"})
22471    protected boolean overScrollBy(int deltaX, int deltaY,
22472            int scrollX, int scrollY,
22473            int scrollRangeX, int scrollRangeY,
22474            int maxOverScrollX, int maxOverScrollY,
22475            boolean isTouchEvent) {
22476        final int overScrollMode = mOverScrollMode;
22477        final boolean canScrollHorizontal =
22478                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22479        final boolean canScrollVertical =
22480                computeVerticalScrollRange() > computeVerticalScrollExtent();
22481        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22482                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22483        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22484                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22485
22486        int newScrollX = scrollX + deltaX;
22487        if (!overScrollHorizontal) {
22488            maxOverScrollX = 0;
22489        }
22490
22491        int newScrollY = scrollY + deltaY;
22492        if (!overScrollVertical) {
22493            maxOverScrollY = 0;
22494        }
22495
22496        // Clamp values if at the limits and record
22497        final int left = -maxOverScrollX;
22498        final int right = maxOverScrollX + scrollRangeX;
22499        final int top = -maxOverScrollY;
22500        final int bottom = maxOverScrollY + scrollRangeY;
22501
22502        boolean clampedX = false;
22503        if (newScrollX > right) {
22504            newScrollX = right;
22505            clampedX = true;
22506        } else if (newScrollX < left) {
22507            newScrollX = left;
22508            clampedX = true;
22509        }
22510
22511        boolean clampedY = false;
22512        if (newScrollY > bottom) {
22513            newScrollY = bottom;
22514            clampedY = true;
22515        } else if (newScrollY < top) {
22516            newScrollY = top;
22517            clampedY = true;
22518        }
22519
22520        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22521
22522        return clampedX || clampedY;
22523    }
22524
22525    /**
22526     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22527     * respond to the results of an over-scroll operation.
22528     *
22529     * @param scrollX New X scroll value in pixels
22530     * @param scrollY New Y scroll value in pixels
22531     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22532     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22533     */
22534    protected void onOverScrolled(int scrollX, int scrollY,
22535            boolean clampedX, boolean clampedY) {
22536        // Intentionally empty.
22537    }
22538
22539    /**
22540     * Returns the over-scroll mode for this view. The result will be
22541     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22542     * (allow over-scrolling only if the view content is larger than the container),
22543     * or {@link #OVER_SCROLL_NEVER}.
22544     *
22545     * @return This view's over-scroll mode.
22546     */
22547    public int getOverScrollMode() {
22548        return mOverScrollMode;
22549    }
22550
22551    /**
22552     * Set the over-scroll mode for this view. Valid over-scroll modes are
22553     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22554     * (allow over-scrolling only if the view content is larger than the container),
22555     * or {@link #OVER_SCROLL_NEVER}.
22556     *
22557     * Setting the over-scroll mode of a view will have an effect only if the
22558     * view is capable of scrolling.
22559     *
22560     * @param overScrollMode The new over-scroll mode for this view.
22561     */
22562    public void setOverScrollMode(int overScrollMode) {
22563        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22564                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22565                overScrollMode != OVER_SCROLL_NEVER) {
22566            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22567        }
22568        mOverScrollMode = overScrollMode;
22569    }
22570
22571    /**
22572     * Enable or disable nested scrolling for this view.
22573     *
22574     * <p>If this property is set to true the view will be permitted to initiate nested
22575     * scrolling operations with a compatible parent view in the current hierarchy. If this
22576     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22577     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22578     * the nested scroll.</p>
22579     *
22580     * @param enabled true to enable nested scrolling, false to disable
22581     *
22582     * @see #isNestedScrollingEnabled()
22583     */
22584    public void setNestedScrollingEnabled(boolean enabled) {
22585        if (enabled) {
22586            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22587        } else {
22588            stopNestedScroll();
22589            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22590        }
22591    }
22592
22593    /**
22594     * Returns true if nested scrolling is enabled for this view.
22595     *
22596     * <p>If nested scrolling is enabled and this View class implementation supports it,
22597     * this view will act as a nested scrolling child view when applicable, forwarding data
22598     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22599     * parent.</p>
22600     *
22601     * @return true if nested scrolling is enabled
22602     *
22603     * @see #setNestedScrollingEnabled(boolean)
22604     */
22605    public boolean isNestedScrollingEnabled() {
22606        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22607                PFLAG3_NESTED_SCROLLING_ENABLED;
22608    }
22609
22610    /**
22611     * Begin a nestable scroll operation along the given axes.
22612     *
22613     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22614     *
22615     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22616     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22617     * In the case of touch scrolling the nested scroll will be terminated automatically in
22618     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22619     * In the event of programmatic scrolling the caller must explicitly call
22620     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22621     *
22622     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22623     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22624     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22625     *
22626     * <p>At each incremental step of the scroll the caller should invoke
22627     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22628     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22629     * parent at least partially consumed the scroll and the caller should adjust the amount it
22630     * scrolls by.</p>
22631     *
22632     * <p>After applying the remainder of the scroll delta the caller should invoke
22633     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22634     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22635     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22636     * </p>
22637     *
22638     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22639     *             {@link #SCROLL_AXIS_VERTICAL}.
22640     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22641     *         the current gesture.
22642     *
22643     * @see #stopNestedScroll()
22644     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22645     * @see #dispatchNestedScroll(int, int, int, int, int[])
22646     */
22647    public boolean startNestedScroll(int axes) {
22648        if (hasNestedScrollingParent()) {
22649            // Already in progress
22650            return true;
22651        }
22652        if (isNestedScrollingEnabled()) {
22653            ViewParent p = getParent();
22654            View child = this;
22655            while (p != null) {
22656                try {
22657                    if (p.onStartNestedScroll(child, this, axes)) {
22658                        mNestedScrollingParent = p;
22659                        p.onNestedScrollAccepted(child, this, axes);
22660                        return true;
22661                    }
22662                } catch (AbstractMethodError e) {
22663                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22664                            "method onStartNestedScroll", e);
22665                    // Allow the search upward to continue
22666                }
22667                if (p instanceof View) {
22668                    child = (View) p;
22669                }
22670                p = p.getParent();
22671            }
22672        }
22673        return false;
22674    }
22675
22676    /**
22677     * Stop a nested scroll in progress.
22678     *
22679     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22680     *
22681     * @see #startNestedScroll(int)
22682     */
22683    public void stopNestedScroll() {
22684        if (mNestedScrollingParent != null) {
22685            mNestedScrollingParent.onStopNestedScroll(this);
22686            mNestedScrollingParent = null;
22687        }
22688    }
22689
22690    /**
22691     * Returns true if this view has a nested scrolling parent.
22692     *
22693     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22694     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22695     *
22696     * @return whether this view has a nested scrolling parent
22697     */
22698    public boolean hasNestedScrollingParent() {
22699        return mNestedScrollingParent != null;
22700    }
22701
22702    /**
22703     * Dispatch one step of a nested scroll in progress.
22704     *
22705     * <p>Implementations of views that support nested scrolling should call this to report
22706     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
22707     * is not currently in progress or nested scrolling is not
22708     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
22709     *
22710     * <p>Compatible View implementations should also call
22711     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
22712     * consuming a component of the scroll event themselves.</p>
22713     *
22714     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
22715     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
22716     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
22717     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
22718     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22719     *                       in local view coordinates of this view from before this operation
22720     *                       to after it completes. View implementations may use this to adjust
22721     *                       expected input coordinate tracking.
22722     * @return true if the event was dispatched, false if it could not be dispatched.
22723     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22724     */
22725    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
22726            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
22727        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22728            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
22729                int startX = 0;
22730                int startY = 0;
22731                if (offsetInWindow != null) {
22732                    getLocationInWindow(offsetInWindow);
22733                    startX = offsetInWindow[0];
22734                    startY = offsetInWindow[1];
22735                }
22736
22737                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
22738                        dxUnconsumed, dyUnconsumed);
22739
22740                if (offsetInWindow != null) {
22741                    getLocationInWindow(offsetInWindow);
22742                    offsetInWindow[0] -= startX;
22743                    offsetInWindow[1] -= startY;
22744                }
22745                return true;
22746            } else if (offsetInWindow != null) {
22747                // No motion, no dispatch. Keep offsetInWindow up to date.
22748                offsetInWindow[0] = 0;
22749                offsetInWindow[1] = 0;
22750            }
22751        }
22752        return false;
22753    }
22754
22755    /**
22756     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
22757     *
22758     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
22759     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
22760     * scrolling operation to consume some or all of the scroll operation before the child view
22761     * consumes it.</p>
22762     *
22763     * @param dx Horizontal scroll distance in pixels
22764     * @param dy Vertical scroll distance in pixels
22765     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
22766     *                 and consumed[1] the consumed dy.
22767     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22768     *                       in local view coordinates of this view from before this operation
22769     *                       to after it completes. View implementations may use this to adjust
22770     *                       expected input coordinate tracking.
22771     * @return true if the parent consumed some or all of the scroll delta
22772     * @see #dispatchNestedScroll(int, int, int, int, int[])
22773     */
22774    public boolean dispatchNestedPreScroll(int dx, int dy,
22775            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
22776        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22777            if (dx != 0 || dy != 0) {
22778                int startX = 0;
22779                int startY = 0;
22780                if (offsetInWindow != null) {
22781                    getLocationInWindow(offsetInWindow);
22782                    startX = offsetInWindow[0];
22783                    startY = offsetInWindow[1];
22784                }
22785
22786                if (consumed == null) {
22787                    if (mTempNestedScrollConsumed == null) {
22788                        mTempNestedScrollConsumed = new int[2];
22789                    }
22790                    consumed = mTempNestedScrollConsumed;
22791                }
22792                consumed[0] = 0;
22793                consumed[1] = 0;
22794                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
22795
22796                if (offsetInWindow != null) {
22797                    getLocationInWindow(offsetInWindow);
22798                    offsetInWindow[0] -= startX;
22799                    offsetInWindow[1] -= startY;
22800                }
22801                return consumed[0] != 0 || consumed[1] != 0;
22802            } else if (offsetInWindow != null) {
22803                offsetInWindow[0] = 0;
22804                offsetInWindow[1] = 0;
22805            }
22806        }
22807        return false;
22808    }
22809
22810    /**
22811     * Dispatch a fling to a nested scrolling parent.
22812     *
22813     * <p>This method should be used to indicate that a nested scrolling child has detected
22814     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
22815     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
22816     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
22817     * along a scrollable axis.</p>
22818     *
22819     * <p>If a nested scrolling child view would normally fling but it is at the edge of
22820     * its own content, it can use this method to delegate the fling to its nested scrolling
22821     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
22822     *
22823     * @param velocityX Horizontal fling velocity in pixels per second
22824     * @param velocityY Vertical fling velocity in pixels per second
22825     * @param consumed true if the child consumed the fling, false otherwise
22826     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
22827     */
22828    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
22829        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22830            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
22831        }
22832        return false;
22833    }
22834
22835    /**
22836     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
22837     *
22838     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
22839     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
22840     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
22841     * before the child view consumes it. If this method returns <code>true</code>, a nested
22842     * parent view consumed the fling and this view should not scroll as a result.</p>
22843     *
22844     * <p>For a better user experience, only one view in a nested scrolling chain should consume
22845     * the fling at a time. If a parent view consumed the fling this method will return false.
22846     * Custom view implementations should account for this in two ways:</p>
22847     *
22848     * <ul>
22849     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
22850     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
22851     *     position regardless.</li>
22852     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
22853     *     even to settle back to a valid idle position.</li>
22854     * </ul>
22855     *
22856     * <p>Views should also not offer fling velocities to nested parent views along an axis
22857     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
22858     * should not offer a horizontal fling velocity to its parents since scrolling along that
22859     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
22860     *
22861     * @param velocityX Horizontal fling velocity in pixels per second
22862     * @param velocityY Vertical fling velocity in pixels per second
22863     * @return true if a nested scrolling parent consumed the fling
22864     */
22865    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
22866        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22867            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
22868        }
22869        return false;
22870    }
22871
22872    /**
22873     * Gets a scale factor that determines the distance the view should scroll
22874     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
22875     * @return The vertical scroll scale factor.
22876     * @hide
22877     */
22878    protected float getVerticalScrollFactor() {
22879        if (mVerticalScrollFactor == 0) {
22880            TypedValue outValue = new TypedValue();
22881            if (!mContext.getTheme().resolveAttribute(
22882                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
22883                throw new IllegalStateException(
22884                        "Expected theme to define listPreferredItemHeight.");
22885            }
22886            mVerticalScrollFactor = outValue.getDimension(
22887                    mContext.getResources().getDisplayMetrics());
22888        }
22889        return mVerticalScrollFactor;
22890    }
22891
22892    /**
22893     * Gets a scale factor that determines the distance the view should scroll
22894     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
22895     * @return The horizontal scroll scale factor.
22896     * @hide
22897     */
22898    protected float getHorizontalScrollFactor() {
22899        // TODO: Should use something else.
22900        return getVerticalScrollFactor();
22901    }
22902
22903    /**
22904     * Return the value specifying the text direction or policy that was set with
22905     * {@link #setTextDirection(int)}.
22906     *
22907     * @return the defined text direction. It can be one of:
22908     *
22909     * {@link #TEXT_DIRECTION_INHERIT},
22910     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22911     * {@link #TEXT_DIRECTION_ANY_RTL},
22912     * {@link #TEXT_DIRECTION_LTR},
22913     * {@link #TEXT_DIRECTION_RTL},
22914     * {@link #TEXT_DIRECTION_LOCALE},
22915     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22916     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22917     *
22918     * @attr ref android.R.styleable#View_textDirection
22919     *
22920     * @hide
22921     */
22922    @ViewDebug.ExportedProperty(category = "text", mapping = {
22923            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22924            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22925            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22926            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22927            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22928            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22929            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22930            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22931    })
22932    public int getRawTextDirection() {
22933        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
22934    }
22935
22936    /**
22937     * Set the text direction.
22938     *
22939     * @param textDirection the direction to set. Should be one of:
22940     *
22941     * {@link #TEXT_DIRECTION_INHERIT},
22942     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22943     * {@link #TEXT_DIRECTION_ANY_RTL},
22944     * {@link #TEXT_DIRECTION_LTR},
22945     * {@link #TEXT_DIRECTION_RTL},
22946     * {@link #TEXT_DIRECTION_LOCALE}
22947     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22948     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
22949     *
22950     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
22951     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
22952     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
22953     *
22954     * @attr ref android.R.styleable#View_textDirection
22955     */
22956    public void setTextDirection(int textDirection) {
22957        if (getRawTextDirection() != textDirection) {
22958            // Reset the current text direction and the resolved one
22959            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
22960            resetResolvedTextDirection();
22961            // Set the new text direction
22962            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
22963            // Do resolution
22964            resolveTextDirection();
22965            // Notify change
22966            onRtlPropertiesChanged(getLayoutDirection());
22967            // Refresh
22968            requestLayout();
22969            invalidate(true);
22970        }
22971    }
22972
22973    /**
22974     * Return the resolved text direction.
22975     *
22976     * @return the resolved text direction. Returns one of:
22977     *
22978     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22979     * {@link #TEXT_DIRECTION_ANY_RTL},
22980     * {@link #TEXT_DIRECTION_LTR},
22981     * {@link #TEXT_DIRECTION_RTL},
22982     * {@link #TEXT_DIRECTION_LOCALE},
22983     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22984     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22985     *
22986     * @attr ref android.R.styleable#View_textDirection
22987     */
22988    @ViewDebug.ExportedProperty(category = "text", mapping = {
22989            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22990            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22991            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22992            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22993            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22994            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22995            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22996            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22997    })
22998    public int getTextDirection() {
22999        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23000    }
23001
23002    /**
23003     * Resolve the text direction.
23004     *
23005     * @return true if resolution has been done, false otherwise.
23006     *
23007     * @hide
23008     */
23009    public boolean resolveTextDirection() {
23010        // Reset any previous text direction resolution
23011        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23012
23013        if (hasRtlSupport()) {
23014            // Set resolved text direction flag depending on text direction flag
23015            final int textDirection = getRawTextDirection();
23016            switch(textDirection) {
23017                case TEXT_DIRECTION_INHERIT:
23018                    if (!canResolveTextDirection()) {
23019                        // We cannot do the resolution if there is no parent, so use the default one
23020                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23021                        // Resolution will need to happen again later
23022                        return false;
23023                    }
23024
23025                    // Parent has not yet resolved, so we still return the default
23026                    try {
23027                        if (!mParent.isTextDirectionResolved()) {
23028                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23029                            // Resolution will need to happen again later
23030                            return false;
23031                        }
23032                    } catch (AbstractMethodError e) {
23033                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23034                                " does not fully implement ViewParent", e);
23035                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23036                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23037                        return true;
23038                    }
23039
23040                    // Set current resolved direction to the same value as the parent's one
23041                    int parentResolvedDirection;
23042                    try {
23043                        parentResolvedDirection = mParent.getTextDirection();
23044                    } catch (AbstractMethodError e) {
23045                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23046                                " does not fully implement ViewParent", e);
23047                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23048                    }
23049                    switch (parentResolvedDirection) {
23050                        case TEXT_DIRECTION_FIRST_STRONG:
23051                        case TEXT_DIRECTION_ANY_RTL:
23052                        case TEXT_DIRECTION_LTR:
23053                        case TEXT_DIRECTION_RTL:
23054                        case TEXT_DIRECTION_LOCALE:
23055                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23056                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23057                            mPrivateFlags2 |=
23058                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23059                            break;
23060                        default:
23061                            // Default resolved direction is "first strong" heuristic
23062                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23063                    }
23064                    break;
23065                case TEXT_DIRECTION_FIRST_STRONG:
23066                case TEXT_DIRECTION_ANY_RTL:
23067                case TEXT_DIRECTION_LTR:
23068                case TEXT_DIRECTION_RTL:
23069                case TEXT_DIRECTION_LOCALE:
23070                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23071                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23072                    // Resolved direction is the same as text direction
23073                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23074                    break;
23075                default:
23076                    // Default resolved direction is "first strong" heuristic
23077                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23078            }
23079        } else {
23080            // Default resolved direction is "first strong" heuristic
23081            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23082        }
23083
23084        // Set to resolved
23085        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23086        return true;
23087    }
23088
23089    /**
23090     * Check if text direction resolution can be done.
23091     *
23092     * @return true if text direction resolution can be done otherwise return false.
23093     */
23094    public boolean canResolveTextDirection() {
23095        switch (getRawTextDirection()) {
23096            case TEXT_DIRECTION_INHERIT:
23097                if (mParent != null) {
23098                    try {
23099                        return mParent.canResolveTextDirection();
23100                    } catch (AbstractMethodError e) {
23101                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23102                                " does not fully implement ViewParent", e);
23103                    }
23104                }
23105                return false;
23106
23107            default:
23108                return true;
23109        }
23110    }
23111
23112    /**
23113     * Reset resolved text direction. Text direction will be resolved during a call to
23114     * {@link #onMeasure(int, int)}.
23115     *
23116     * @hide
23117     */
23118    public void resetResolvedTextDirection() {
23119        // Reset any previous text direction resolution
23120        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23121        // Set to default value
23122        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23123    }
23124
23125    /**
23126     * @return true if text direction is inherited.
23127     *
23128     * @hide
23129     */
23130    public boolean isTextDirectionInherited() {
23131        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23132    }
23133
23134    /**
23135     * @return true if text direction is resolved.
23136     */
23137    public boolean isTextDirectionResolved() {
23138        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23139    }
23140
23141    /**
23142     * Return the value specifying the text alignment or policy that was set with
23143     * {@link #setTextAlignment(int)}.
23144     *
23145     * @return the defined text alignment. It can be one of:
23146     *
23147     * {@link #TEXT_ALIGNMENT_INHERIT},
23148     * {@link #TEXT_ALIGNMENT_GRAVITY},
23149     * {@link #TEXT_ALIGNMENT_CENTER},
23150     * {@link #TEXT_ALIGNMENT_TEXT_START},
23151     * {@link #TEXT_ALIGNMENT_TEXT_END},
23152     * {@link #TEXT_ALIGNMENT_VIEW_START},
23153     * {@link #TEXT_ALIGNMENT_VIEW_END}
23154     *
23155     * @attr ref android.R.styleable#View_textAlignment
23156     *
23157     * @hide
23158     */
23159    @ViewDebug.ExportedProperty(category = "text", mapping = {
23160            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23161            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23162            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23163            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23164            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23165            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23166            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23167    })
23168    @TextAlignment
23169    public int getRawTextAlignment() {
23170        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23171    }
23172
23173    /**
23174     * Set the text alignment.
23175     *
23176     * @param textAlignment The text alignment to set. Should be one of
23177     *
23178     * {@link #TEXT_ALIGNMENT_INHERIT},
23179     * {@link #TEXT_ALIGNMENT_GRAVITY},
23180     * {@link #TEXT_ALIGNMENT_CENTER},
23181     * {@link #TEXT_ALIGNMENT_TEXT_START},
23182     * {@link #TEXT_ALIGNMENT_TEXT_END},
23183     * {@link #TEXT_ALIGNMENT_VIEW_START},
23184     * {@link #TEXT_ALIGNMENT_VIEW_END}
23185     *
23186     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23187     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23188     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23189     *
23190     * @attr ref android.R.styleable#View_textAlignment
23191     */
23192    public void setTextAlignment(@TextAlignment int textAlignment) {
23193        if (textAlignment != getRawTextAlignment()) {
23194            // Reset the current and resolved text alignment
23195            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23196            resetResolvedTextAlignment();
23197            // Set the new text alignment
23198            mPrivateFlags2 |=
23199                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23200            // Do resolution
23201            resolveTextAlignment();
23202            // Notify change
23203            onRtlPropertiesChanged(getLayoutDirection());
23204            // Refresh
23205            requestLayout();
23206            invalidate(true);
23207        }
23208    }
23209
23210    /**
23211     * Return the resolved text alignment.
23212     *
23213     * @return the resolved text alignment. Returns one of:
23214     *
23215     * {@link #TEXT_ALIGNMENT_GRAVITY},
23216     * {@link #TEXT_ALIGNMENT_CENTER},
23217     * {@link #TEXT_ALIGNMENT_TEXT_START},
23218     * {@link #TEXT_ALIGNMENT_TEXT_END},
23219     * {@link #TEXT_ALIGNMENT_VIEW_START},
23220     * {@link #TEXT_ALIGNMENT_VIEW_END}
23221     *
23222     * @attr ref android.R.styleable#View_textAlignment
23223     */
23224    @ViewDebug.ExportedProperty(category = "text", mapping = {
23225            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23226            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23227            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23228            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23229            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23230            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23231            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23232    })
23233    @TextAlignment
23234    public int getTextAlignment() {
23235        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23236                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23237    }
23238
23239    /**
23240     * Resolve the text alignment.
23241     *
23242     * @return true if resolution has been done, false otherwise.
23243     *
23244     * @hide
23245     */
23246    public boolean resolveTextAlignment() {
23247        // Reset any previous text alignment resolution
23248        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23249
23250        if (hasRtlSupport()) {
23251            // Set resolved text alignment flag depending on text alignment flag
23252            final int textAlignment = getRawTextAlignment();
23253            switch (textAlignment) {
23254                case TEXT_ALIGNMENT_INHERIT:
23255                    // Check if we can resolve the text alignment
23256                    if (!canResolveTextAlignment()) {
23257                        // We cannot do the resolution if there is no parent so use the default
23258                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23259                        // Resolution will need to happen again later
23260                        return false;
23261                    }
23262
23263                    // Parent has not yet resolved, so we still return the default
23264                    try {
23265                        if (!mParent.isTextAlignmentResolved()) {
23266                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23267                            // Resolution will need to happen again later
23268                            return false;
23269                        }
23270                    } catch (AbstractMethodError e) {
23271                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23272                                " does not fully implement ViewParent", e);
23273                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23274                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23275                        return true;
23276                    }
23277
23278                    int parentResolvedTextAlignment;
23279                    try {
23280                        parentResolvedTextAlignment = mParent.getTextAlignment();
23281                    } catch (AbstractMethodError e) {
23282                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23283                                " does not fully implement ViewParent", e);
23284                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23285                    }
23286                    switch (parentResolvedTextAlignment) {
23287                        case TEXT_ALIGNMENT_GRAVITY:
23288                        case TEXT_ALIGNMENT_TEXT_START:
23289                        case TEXT_ALIGNMENT_TEXT_END:
23290                        case TEXT_ALIGNMENT_CENTER:
23291                        case TEXT_ALIGNMENT_VIEW_START:
23292                        case TEXT_ALIGNMENT_VIEW_END:
23293                            // Resolved text alignment is the same as the parent resolved
23294                            // text alignment
23295                            mPrivateFlags2 |=
23296                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23297                            break;
23298                        default:
23299                            // Use default resolved text alignment
23300                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23301                    }
23302                    break;
23303                case TEXT_ALIGNMENT_GRAVITY:
23304                case TEXT_ALIGNMENT_TEXT_START:
23305                case TEXT_ALIGNMENT_TEXT_END:
23306                case TEXT_ALIGNMENT_CENTER:
23307                case TEXT_ALIGNMENT_VIEW_START:
23308                case TEXT_ALIGNMENT_VIEW_END:
23309                    // Resolved text alignment is the same as text alignment
23310                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23311                    break;
23312                default:
23313                    // Use default resolved text alignment
23314                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23315            }
23316        } else {
23317            // Use default resolved text alignment
23318            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23319        }
23320
23321        // Set the resolved
23322        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23323        return true;
23324    }
23325
23326    /**
23327     * Check if text alignment resolution can be done.
23328     *
23329     * @return true if text alignment resolution can be done otherwise return false.
23330     */
23331    public boolean canResolveTextAlignment() {
23332        switch (getRawTextAlignment()) {
23333            case TEXT_DIRECTION_INHERIT:
23334                if (mParent != null) {
23335                    try {
23336                        return mParent.canResolveTextAlignment();
23337                    } catch (AbstractMethodError e) {
23338                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23339                                " does not fully implement ViewParent", e);
23340                    }
23341                }
23342                return false;
23343
23344            default:
23345                return true;
23346        }
23347    }
23348
23349    /**
23350     * Reset resolved text alignment. Text alignment will be resolved during a call to
23351     * {@link #onMeasure(int, int)}.
23352     *
23353     * @hide
23354     */
23355    public void resetResolvedTextAlignment() {
23356        // Reset any previous text alignment resolution
23357        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23358        // Set to default
23359        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23360    }
23361
23362    /**
23363     * @return true if text alignment is inherited.
23364     *
23365     * @hide
23366     */
23367    public boolean isTextAlignmentInherited() {
23368        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23369    }
23370
23371    /**
23372     * @return true if text alignment is resolved.
23373     */
23374    public boolean isTextAlignmentResolved() {
23375        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23376    }
23377
23378    /**
23379     * Generate a value suitable for use in {@link #setId(int)}.
23380     * This value will not collide with ID values generated at build time by aapt for R.id.
23381     *
23382     * @return a generated ID value
23383     */
23384    public static int generateViewId() {
23385        for (;;) {
23386            final int result = sNextGeneratedId.get();
23387            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23388            int newValue = result + 1;
23389            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23390            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23391                return result;
23392            }
23393        }
23394    }
23395
23396    private static boolean isViewIdGenerated(int id) {
23397        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23398    }
23399
23400    /**
23401     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23402     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23403     *                           a normal View or a ViewGroup with
23404     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23405     * @hide
23406     */
23407    public void captureTransitioningViews(List<View> transitioningViews) {
23408        if (getVisibility() == View.VISIBLE) {
23409            transitioningViews.add(this);
23410        }
23411    }
23412
23413    /**
23414     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23415     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23416     * @hide
23417     */
23418    public void findNamedViews(Map<String, View> namedElements) {
23419        if (getVisibility() == VISIBLE || mGhostView != null) {
23420            String transitionName = getTransitionName();
23421            if (transitionName != null) {
23422                namedElements.put(transitionName, this);
23423            }
23424        }
23425    }
23426
23427    /**
23428     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23429     * The default implementation does not care the location or event types, but some subclasses
23430     * may use it (such as WebViews).
23431     * @param event The MotionEvent from a mouse
23432     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23433     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23434     * @see PointerIcon
23435     */
23436    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23437        final float x = event.getX(pointerIndex);
23438        final float y = event.getY(pointerIndex);
23439        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23440            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23441        }
23442        return mPointerIcon;
23443    }
23444
23445    /**
23446     * Set the pointer icon for the current view.
23447     * Passing {@code null} will restore the pointer icon to its default value.
23448     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23449     */
23450    public void setPointerIcon(PointerIcon pointerIcon) {
23451        mPointerIcon = pointerIcon;
23452        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23453            return;
23454        }
23455        try {
23456            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23457        } catch (RemoteException e) {
23458        }
23459    }
23460
23461    /**
23462     * Gets the pointer icon for the current view.
23463     */
23464    public PointerIcon getPointerIcon() {
23465        return mPointerIcon;
23466    }
23467
23468    /**
23469     * Checks pointer capture status.
23470     *
23471     * @return true if the view has pointer capture.
23472     * @see #requestPointerCapture()
23473     * @see #hasPointerCapture()
23474     */
23475    public boolean hasPointerCapture() {
23476        final ViewRootImpl viewRootImpl = getViewRootImpl();
23477        if (viewRootImpl == null) {
23478            return false;
23479        }
23480        return viewRootImpl.hasPointerCapture();
23481    }
23482
23483    /**
23484     * Requests pointer capture mode.
23485     * <p>
23486     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23487     * change its position. Further mouse will be dispatched with the source
23488     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23489     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23490     * (touchscreens, or stylus) will not be affected.
23491     * <p>
23492     * If the window already has pointer capture, this call does nothing.
23493     * <p>
23494     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23495     * automatically when the window loses focus.
23496     *
23497     * @see #releasePointerCapture()
23498     * @see #hasPointerCapture()
23499     */
23500    public void requestPointerCapture() {
23501        final ViewRootImpl viewRootImpl = getViewRootImpl();
23502        if (viewRootImpl != null) {
23503            viewRootImpl.requestPointerCapture(true);
23504        }
23505    }
23506
23507
23508    /**
23509     * Releases the pointer capture.
23510     * <p>
23511     * If the window does not have pointer capture, this call will do nothing.
23512     * @see #requestPointerCapture()
23513     * @see #hasPointerCapture()
23514     */
23515    public void releasePointerCapture() {
23516        final ViewRootImpl viewRootImpl = getViewRootImpl();
23517        if (viewRootImpl != null) {
23518            viewRootImpl.requestPointerCapture(false);
23519        }
23520    }
23521
23522    /**
23523     * Called when the window has just acquired or lost pointer capture.
23524     *
23525     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23526     */
23527    @CallSuper
23528    public void onPointerCaptureChange(boolean hasCapture) {
23529    }
23530
23531    /**
23532     * @see #onPointerCaptureChange
23533     */
23534    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23535        onPointerCaptureChange(hasCapture);
23536    }
23537
23538    /**
23539     * Implement this method to handle captured pointer events
23540     *
23541     * @param event The captured pointer event.
23542     * @return True if the event was handled, false otherwise.
23543     * @see #requestPointerCapture()
23544     */
23545    public boolean onCapturedPointerEvent(MotionEvent event) {
23546        return false;
23547    }
23548
23549    /**
23550     * Interface definition for a callback to be invoked when a captured pointer event
23551     * is being dispatched this view. The callback will be invoked before the event is
23552     * given to the view.
23553     */
23554    public interface OnCapturedPointerListener {
23555        /**
23556         * Called when a captured pointer event is dispatched to a view.
23557         * @param view The view this event has been dispatched to.
23558         * @param event The captured event.
23559         * @return True if the listener has consumed the event, false otherwise.
23560         */
23561        boolean onCapturedPointer(View view, MotionEvent event);
23562    }
23563
23564    /**
23565     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23566     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23567     */
23568    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23569        getListenerInfo().mOnCapturedPointerListener = l;
23570    }
23571
23572    // Properties
23573    //
23574    /**
23575     * A Property wrapper around the <code>alpha</code> functionality handled by the
23576     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23577     */
23578    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23579        @Override
23580        public void setValue(View object, float value) {
23581            object.setAlpha(value);
23582        }
23583
23584        @Override
23585        public Float get(View object) {
23586            return object.getAlpha();
23587        }
23588    };
23589
23590    /**
23591     * A Property wrapper around the <code>translationX</code> functionality handled by the
23592     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23593     */
23594    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23595        @Override
23596        public void setValue(View object, float value) {
23597            object.setTranslationX(value);
23598        }
23599
23600                @Override
23601        public Float get(View object) {
23602            return object.getTranslationX();
23603        }
23604    };
23605
23606    /**
23607     * A Property wrapper around the <code>translationY</code> functionality handled by the
23608     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23609     */
23610    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23611        @Override
23612        public void setValue(View object, float value) {
23613            object.setTranslationY(value);
23614        }
23615
23616        @Override
23617        public Float get(View object) {
23618            return object.getTranslationY();
23619        }
23620    };
23621
23622    /**
23623     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23624     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23625     */
23626    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23627        @Override
23628        public void setValue(View object, float value) {
23629            object.setTranslationZ(value);
23630        }
23631
23632        @Override
23633        public Float get(View object) {
23634            return object.getTranslationZ();
23635        }
23636    };
23637
23638    /**
23639     * A Property wrapper around the <code>x</code> functionality handled by the
23640     * {@link View#setX(float)} and {@link View#getX()} methods.
23641     */
23642    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23643        @Override
23644        public void setValue(View object, float value) {
23645            object.setX(value);
23646        }
23647
23648        @Override
23649        public Float get(View object) {
23650            return object.getX();
23651        }
23652    };
23653
23654    /**
23655     * A Property wrapper around the <code>y</code> functionality handled by the
23656     * {@link View#setY(float)} and {@link View#getY()} methods.
23657     */
23658    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23659        @Override
23660        public void setValue(View object, float value) {
23661            object.setY(value);
23662        }
23663
23664        @Override
23665        public Float get(View object) {
23666            return object.getY();
23667        }
23668    };
23669
23670    /**
23671     * A Property wrapper around the <code>z</code> functionality handled by the
23672     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23673     */
23674    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23675        @Override
23676        public void setValue(View object, float value) {
23677            object.setZ(value);
23678        }
23679
23680        @Override
23681        public Float get(View object) {
23682            return object.getZ();
23683        }
23684    };
23685
23686    /**
23687     * A Property wrapper around the <code>rotation</code> functionality handled by the
23688     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23689     */
23690    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23691        @Override
23692        public void setValue(View object, float value) {
23693            object.setRotation(value);
23694        }
23695
23696        @Override
23697        public Float get(View object) {
23698            return object.getRotation();
23699        }
23700    };
23701
23702    /**
23703     * A Property wrapper around the <code>rotationX</code> functionality handled by the
23704     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
23705     */
23706    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
23707        @Override
23708        public void setValue(View object, float value) {
23709            object.setRotationX(value);
23710        }
23711
23712        @Override
23713        public Float get(View object) {
23714            return object.getRotationX();
23715        }
23716    };
23717
23718    /**
23719     * A Property wrapper around the <code>rotationY</code> functionality handled by the
23720     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
23721     */
23722    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
23723        @Override
23724        public void setValue(View object, float value) {
23725            object.setRotationY(value);
23726        }
23727
23728        @Override
23729        public Float get(View object) {
23730            return object.getRotationY();
23731        }
23732    };
23733
23734    /**
23735     * A Property wrapper around the <code>scaleX</code> functionality handled by the
23736     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
23737     */
23738    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
23739        @Override
23740        public void setValue(View object, float value) {
23741            object.setScaleX(value);
23742        }
23743
23744        @Override
23745        public Float get(View object) {
23746            return object.getScaleX();
23747        }
23748    };
23749
23750    /**
23751     * A Property wrapper around the <code>scaleY</code> functionality handled by the
23752     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
23753     */
23754    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
23755        @Override
23756        public void setValue(View object, float value) {
23757            object.setScaleY(value);
23758        }
23759
23760        @Override
23761        public Float get(View object) {
23762            return object.getScaleY();
23763        }
23764    };
23765
23766    /**
23767     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
23768     * Each MeasureSpec represents a requirement for either the width or the height.
23769     * A MeasureSpec is comprised of a size and a mode. There are three possible
23770     * modes:
23771     * <dl>
23772     * <dt>UNSPECIFIED</dt>
23773     * <dd>
23774     * The parent has not imposed any constraint on the child. It can be whatever size
23775     * it wants.
23776     * </dd>
23777     *
23778     * <dt>EXACTLY</dt>
23779     * <dd>
23780     * The parent has determined an exact size for the child. The child is going to be
23781     * given those bounds regardless of how big it wants to be.
23782     * </dd>
23783     *
23784     * <dt>AT_MOST</dt>
23785     * <dd>
23786     * The child can be as large as it wants up to the specified size.
23787     * </dd>
23788     * </dl>
23789     *
23790     * MeasureSpecs are implemented as ints to reduce object allocation. This class
23791     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
23792     */
23793    public static class MeasureSpec {
23794        private static final int MODE_SHIFT = 30;
23795        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
23796
23797        /** @hide */
23798        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
23799        @Retention(RetentionPolicy.SOURCE)
23800        public @interface MeasureSpecMode {}
23801
23802        /**
23803         * Measure specification mode: The parent has not imposed any constraint
23804         * on the child. It can be whatever size it wants.
23805         */
23806        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
23807
23808        /**
23809         * Measure specification mode: The parent has determined an exact size
23810         * for the child. The child is going to be given those bounds regardless
23811         * of how big it wants to be.
23812         */
23813        public static final int EXACTLY     = 1 << MODE_SHIFT;
23814
23815        /**
23816         * Measure specification mode: The child can be as large as it wants up
23817         * to the specified size.
23818         */
23819        public static final int AT_MOST     = 2 << MODE_SHIFT;
23820
23821        /**
23822         * Creates a measure specification based on the supplied size and mode.
23823         *
23824         * The mode must always be one of the following:
23825         * <ul>
23826         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
23827         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
23828         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
23829         * </ul>
23830         *
23831         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
23832         * implementation was such that the order of arguments did not matter
23833         * and overflow in either value could impact the resulting MeasureSpec.
23834         * {@link android.widget.RelativeLayout} was affected by this bug.
23835         * Apps targeting API levels greater than 17 will get the fixed, more strict
23836         * behavior.</p>
23837         *
23838         * @param size the size of the measure specification
23839         * @param mode the mode of the measure specification
23840         * @return the measure specification based on size and mode
23841         */
23842        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
23843                                          @MeasureSpecMode int mode) {
23844            if (sUseBrokenMakeMeasureSpec) {
23845                return size + mode;
23846            } else {
23847                return (size & ~MODE_MASK) | (mode & MODE_MASK);
23848            }
23849        }
23850
23851        /**
23852         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
23853         * will automatically get a size of 0. Older apps expect this.
23854         *
23855         * @hide internal use only for compatibility with system widgets and older apps
23856         */
23857        public static int makeSafeMeasureSpec(int size, int mode) {
23858            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
23859                return 0;
23860            }
23861            return makeMeasureSpec(size, mode);
23862        }
23863
23864        /**
23865         * Extracts the mode from the supplied measure specification.
23866         *
23867         * @param measureSpec the measure specification to extract the mode from
23868         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
23869         *         {@link android.view.View.MeasureSpec#AT_MOST} or
23870         *         {@link android.view.View.MeasureSpec#EXACTLY}
23871         */
23872        @MeasureSpecMode
23873        public static int getMode(int measureSpec) {
23874            //noinspection ResourceType
23875            return (measureSpec & MODE_MASK);
23876        }
23877
23878        /**
23879         * Extracts the size from the supplied measure specification.
23880         *
23881         * @param measureSpec the measure specification to extract the size from
23882         * @return the size in pixels defined in the supplied measure specification
23883         */
23884        public static int getSize(int measureSpec) {
23885            return (measureSpec & ~MODE_MASK);
23886        }
23887
23888        static int adjust(int measureSpec, int delta) {
23889            final int mode = getMode(measureSpec);
23890            int size = getSize(measureSpec);
23891            if (mode == UNSPECIFIED) {
23892                // No need to adjust size for UNSPECIFIED mode.
23893                return makeMeasureSpec(size, UNSPECIFIED);
23894            }
23895            size += delta;
23896            if (size < 0) {
23897                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
23898                        ") spec: " + toString(measureSpec) + " delta: " + delta);
23899                size = 0;
23900            }
23901            return makeMeasureSpec(size, mode);
23902        }
23903
23904        /**
23905         * Returns a String representation of the specified measure
23906         * specification.
23907         *
23908         * @param measureSpec the measure specification to convert to a String
23909         * @return a String with the following format: "MeasureSpec: MODE SIZE"
23910         */
23911        public static String toString(int measureSpec) {
23912            int mode = getMode(measureSpec);
23913            int size = getSize(measureSpec);
23914
23915            StringBuilder sb = new StringBuilder("MeasureSpec: ");
23916
23917            if (mode == UNSPECIFIED)
23918                sb.append("UNSPECIFIED ");
23919            else if (mode == EXACTLY)
23920                sb.append("EXACTLY ");
23921            else if (mode == AT_MOST)
23922                sb.append("AT_MOST ");
23923            else
23924                sb.append(mode).append(" ");
23925
23926            sb.append(size);
23927            return sb.toString();
23928        }
23929    }
23930
23931    private final class CheckForLongPress implements Runnable {
23932        private int mOriginalWindowAttachCount;
23933        private float mX;
23934        private float mY;
23935        private boolean mOriginalPressedState;
23936
23937        @Override
23938        public void run() {
23939            if ((mOriginalPressedState == isPressed()) && (mParent != null)
23940                    && mOriginalWindowAttachCount == mWindowAttachCount) {
23941                if (performLongClick(mX, mY)) {
23942                    mHasPerformedLongPress = true;
23943                }
23944            }
23945        }
23946
23947        public void setAnchor(float x, float y) {
23948            mX = x;
23949            mY = y;
23950        }
23951
23952        public void rememberWindowAttachCount() {
23953            mOriginalWindowAttachCount = mWindowAttachCount;
23954        }
23955
23956        public void rememberPressedState() {
23957            mOriginalPressedState = isPressed();
23958        }
23959    }
23960
23961    private final class CheckForTap implements Runnable {
23962        public float x;
23963        public float y;
23964
23965        @Override
23966        public void run() {
23967            mPrivateFlags &= ~PFLAG_PREPRESSED;
23968            setPressed(true, x, y);
23969            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
23970        }
23971    }
23972
23973    private final class PerformClick implements Runnable {
23974        @Override
23975        public void run() {
23976            performClick();
23977        }
23978    }
23979
23980    /**
23981     * This method returns a ViewPropertyAnimator object, which can be used to animate
23982     * specific properties on this View.
23983     *
23984     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
23985     */
23986    public ViewPropertyAnimator animate() {
23987        if (mAnimator == null) {
23988            mAnimator = new ViewPropertyAnimator(this);
23989        }
23990        return mAnimator;
23991    }
23992
23993    /**
23994     * Sets the name of the View to be used to identify Views in Transitions.
23995     * Names should be unique in the View hierarchy.
23996     *
23997     * @param transitionName The name of the View to uniquely identify it for Transitions.
23998     */
23999    public final void setTransitionName(String transitionName) {
24000        mTransitionName = transitionName;
24001    }
24002
24003    /**
24004     * Returns the name of the View to be used to identify Views in Transitions.
24005     * Names should be unique in the View hierarchy.
24006     *
24007     * <p>This returns null if the View has not been given a name.</p>
24008     *
24009     * @return The name used of the View to be used to identify Views in Transitions or null
24010     * if no name has been given.
24011     */
24012    @ViewDebug.ExportedProperty
24013    public String getTransitionName() {
24014        return mTransitionName;
24015    }
24016
24017    /**
24018     * @hide
24019     */
24020    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24021        // Do nothing.
24022    }
24023
24024    /**
24025     * Interface definition for a callback to be invoked when a hardware key event is
24026     * dispatched to this view. The callback will be invoked before the key event is
24027     * given to the view. This is only useful for hardware keyboards; a software input
24028     * method has no obligation to trigger this listener.
24029     */
24030    public interface OnKeyListener {
24031        /**
24032         * Called when a hardware key is dispatched to a view. This allows listeners to
24033         * get a chance to respond before the target view.
24034         * <p>Key presses in software keyboards will generally NOT trigger this method,
24035         * although some may elect to do so in some situations. Do not assume a
24036         * software input method has to be key-based; even if it is, it may use key presses
24037         * in a different way than you expect, so there is no way to reliably catch soft
24038         * input key presses.
24039         *
24040         * @param v The view the key has been dispatched to.
24041         * @param keyCode The code for the physical key that was pressed
24042         * @param event The KeyEvent object containing full information about
24043         *        the event.
24044         * @return True if the listener has consumed the event, false otherwise.
24045         */
24046        boolean onKey(View v, int keyCode, KeyEvent event);
24047    }
24048
24049    /**
24050     * Interface definition for a callback to be invoked when a touch event is
24051     * dispatched to this view. The callback will be invoked before the touch
24052     * event is given to the view.
24053     */
24054    public interface OnTouchListener {
24055        /**
24056         * Called when a touch event is dispatched to a view. This allows listeners to
24057         * get a chance to respond before the target view.
24058         *
24059         * @param v The view the touch event has been dispatched to.
24060         * @param event The MotionEvent object containing full information about
24061         *        the event.
24062         * @return True if the listener has consumed the event, false otherwise.
24063         */
24064        boolean onTouch(View v, MotionEvent event);
24065    }
24066
24067    /**
24068     * Interface definition for a callback to be invoked when a hover event is
24069     * dispatched to this view. The callback will be invoked before the hover
24070     * event is given to the view.
24071     */
24072    public interface OnHoverListener {
24073        /**
24074         * Called when a hover event is dispatched to a view. This allows listeners to
24075         * get a chance to respond before the target view.
24076         *
24077         * @param v The view the hover event has been dispatched to.
24078         * @param event The MotionEvent object containing full information about
24079         *        the event.
24080         * @return True if the listener has consumed the event, false otherwise.
24081         */
24082        boolean onHover(View v, MotionEvent event);
24083    }
24084
24085    /**
24086     * Interface definition for a callback to be invoked when a generic motion event is
24087     * dispatched to this view. The callback will be invoked before the generic motion
24088     * event is given to the view.
24089     */
24090    public interface OnGenericMotionListener {
24091        /**
24092         * Called when a generic motion event is dispatched to a view. This allows listeners to
24093         * get a chance to respond before the target view.
24094         *
24095         * @param v The view the generic motion event has been dispatched to.
24096         * @param event The MotionEvent object containing full information about
24097         *        the event.
24098         * @return True if the listener has consumed the event, false otherwise.
24099         */
24100        boolean onGenericMotion(View v, MotionEvent event);
24101    }
24102
24103    /**
24104     * Interface definition for a callback to be invoked when a view has been clicked and held.
24105     */
24106    public interface OnLongClickListener {
24107        /**
24108         * Called when a view has been clicked and held.
24109         *
24110         * @param v The view that was clicked and held.
24111         *
24112         * @return true if the callback consumed the long click, false otherwise.
24113         */
24114        boolean onLongClick(View v);
24115    }
24116
24117    /**
24118     * Interface definition for a callback to be invoked when a drag is being dispatched
24119     * to this view.  The callback will be invoked before the hosting view's own
24120     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24121     * onDrag(event) behavior, it should return 'false' from this callback.
24122     *
24123     * <div class="special reference">
24124     * <h3>Developer Guides</h3>
24125     * <p>For a guide to implementing drag and drop features, read the
24126     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24127     * </div>
24128     */
24129    public interface OnDragListener {
24130        /**
24131         * Called when a drag event is dispatched to a view. This allows listeners
24132         * to get a chance to override base View behavior.
24133         *
24134         * @param v The View that received the drag event.
24135         * @param event The {@link android.view.DragEvent} object for the drag event.
24136         * @return {@code true} if the drag event was handled successfully, or {@code false}
24137         * if the drag event was not handled. Note that {@code false} will trigger the View
24138         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24139         */
24140        boolean onDrag(View v, DragEvent event);
24141    }
24142
24143    /**
24144     * Interface definition for a callback to be invoked when the focus state of
24145     * a view changed.
24146     */
24147    public interface OnFocusChangeListener {
24148        /**
24149         * Called when the focus state of a view has changed.
24150         *
24151         * @param v The view whose state has changed.
24152         * @param hasFocus The new focus state of v.
24153         */
24154        void onFocusChange(View v, boolean hasFocus);
24155    }
24156
24157    /**
24158     * Interface definition for a callback to be invoked when a view is clicked.
24159     */
24160    public interface OnClickListener {
24161        /**
24162         * Called when a view has been clicked.
24163         *
24164         * @param v The view that was clicked.
24165         */
24166        void onClick(View v);
24167    }
24168
24169    /**
24170     * Interface definition for a callback to be invoked when a view is context clicked.
24171     */
24172    public interface OnContextClickListener {
24173        /**
24174         * Called when a view is context clicked.
24175         *
24176         * @param v The view that has been context clicked.
24177         * @return true if the callback consumed the context click, false otherwise.
24178         */
24179        boolean onContextClick(View v);
24180    }
24181
24182    /**
24183     * Interface definition for a callback to be invoked when the context menu
24184     * for this view is being built.
24185     */
24186    public interface OnCreateContextMenuListener {
24187        /**
24188         * Called when the context menu for this view is being built. It is not
24189         * safe to hold onto the menu after this method returns.
24190         *
24191         * @param menu The context menu that is being built
24192         * @param v The view for which the context menu is being built
24193         * @param menuInfo Extra information about the item for which the
24194         *            context menu should be shown. This information will vary
24195         *            depending on the class of v.
24196         */
24197        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24198    }
24199
24200    /**
24201     * Interface definition for a callback to be invoked when the status bar changes
24202     * visibility.  This reports <strong>global</strong> changes to the system UI
24203     * state, not what the application is requesting.
24204     *
24205     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24206     */
24207    public interface OnSystemUiVisibilityChangeListener {
24208        /**
24209         * Called when the status bar changes visibility because of a call to
24210         * {@link View#setSystemUiVisibility(int)}.
24211         *
24212         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24213         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24214         * This tells you the <strong>global</strong> state of these UI visibility
24215         * flags, not what your app is currently applying.
24216         */
24217        public void onSystemUiVisibilityChange(int visibility);
24218    }
24219
24220    /**
24221     * Interface definition for a callback to be invoked when this view is attached
24222     * or detached from its window.
24223     */
24224    public interface OnAttachStateChangeListener {
24225        /**
24226         * Called when the view is attached to a window.
24227         * @param v The view that was attached
24228         */
24229        public void onViewAttachedToWindow(View v);
24230        /**
24231         * Called when the view is detached from a window.
24232         * @param v The view that was detached
24233         */
24234        public void onViewDetachedFromWindow(View v);
24235    }
24236
24237    /**
24238     * Listener for applying window insets on a view in a custom way.
24239     *
24240     * <p>Apps may choose to implement this interface if they want to apply custom policy
24241     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24242     * is set, its
24243     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24244     * method will be called instead of the View's own
24245     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24246     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24247     * the View's normal behavior as part of its own.</p>
24248     */
24249    public interface OnApplyWindowInsetsListener {
24250        /**
24251         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24252         * on a View, this listener method will be called instead of the view's own
24253         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24254         *
24255         * @param v The view applying window insets
24256         * @param insets The insets to apply
24257         * @return The insets supplied, minus any insets that were consumed
24258         */
24259        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24260    }
24261
24262    private final class UnsetPressedState implements Runnable {
24263        @Override
24264        public void run() {
24265            setPressed(false);
24266        }
24267    }
24268
24269    /**
24270     * Base class for derived classes that want to save and restore their own
24271     * state in {@link android.view.View#onSaveInstanceState()}.
24272     */
24273    public static class BaseSavedState extends AbsSavedState {
24274        String mStartActivityRequestWhoSaved;
24275
24276        /**
24277         * Constructor used when reading from a parcel. Reads the state of the superclass.
24278         *
24279         * @param source parcel to read from
24280         */
24281        public BaseSavedState(Parcel source) {
24282            this(source, null);
24283        }
24284
24285        /**
24286         * Constructor used when reading from a parcel using a given class loader.
24287         * Reads the state of the superclass.
24288         *
24289         * @param source parcel to read from
24290         * @param loader ClassLoader to use for reading
24291         */
24292        public BaseSavedState(Parcel source, ClassLoader loader) {
24293            super(source, loader);
24294            mStartActivityRequestWhoSaved = source.readString();
24295        }
24296
24297        /**
24298         * Constructor called by derived classes when creating their SavedState objects
24299         *
24300         * @param superState The state of the superclass of this view
24301         */
24302        public BaseSavedState(Parcelable superState) {
24303            super(superState);
24304        }
24305
24306        @Override
24307        public void writeToParcel(Parcel out, int flags) {
24308            super.writeToParcel(out, flags);
24309            out.writeString(mStartActivityRequestWhoSaved);
24310        }
24311
24312        public static final Parcelable.Creator<BaseSavedState> CREATOR
24313                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24314            @Override
24315            public BaseSavedState createFromParcel(Parcel in) {
24316                return new BaseSavedState(in);
24317            }
24318
24319            @Override
24320            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24321                return new BaseSavedState(in, loader);
24322            }
24323
24324            @Override
24325            public BaseSavedState[] newArray(int size) {
24326                return new BaseSavedState[size];
24327            }
24328        };
24329    }
24330
24331    /**
24332     * A set of information given to a view when it is attached to its parent
24333     * window.
24334     */
24335    final static class AttachInfo {
24336        interface Callbacks {
24337            void playSoundEffect(int effectId);
24338            boolean performHapticFeedback(int effectId, boolean always);
24339        }
24340
24341        /**
24342         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24343         * to a Handler. This class contains the target (View) to invalidate and
24344         * the coordinates of the dirty rectangle.
24345         *
24346         * For performance purposes, this class also implements a pool of up to
24347         * POOL_LIMIT objects that get reused. This reduces memory allocations
24348         * whenever possible.
24349         */
24350        static class InvalidateInfo {
24351            private static final int POOL_LIMIT = 10;
24352
24353            private static final SynchronizedPool<InvalidateInfo> sPool =
24354                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24355
24356            View target;
24357
24358            int left;
24359            int top;
24360            int right;
24361            int bottom;
24362
24363            public static InvalidateInfo obtain() {
24364                InvalidateInfo instance = sPool.acquire();
24365                return (instance != null) ? instance : new InvalidateInfo();
24366            }
24367
24368            public void recycle() {
24369                target = null;
24370                sPool.release(this);
24371            }
24372        }
24373
24374        final IWindowSession mSession;
24375
24376        final IWindow mWindow;
24377
24378        final IBinder mWindowToken;
24379
24380        Display mDisplay;
24381
24382        final Callbacks mRootCallbacks;
24383
24384        IWindowId mIWindowId;
24385        WindowId mWindowId;
24386
24387        /**
24388         * The top view of the hierarchy.
24389         */
24390        View mRootView;
24391
24392        IBinder mPanelParentWindowToken;
24393
24394        boolean mHardwareAccelerated;
24395        boolean mHardwareAccelerationRequested;
24396        ThreadedRenderer mThreadedRenderer;
24397        List<RenderNode> mPendingAnimatingRenderNodes;
24398
24399        /**
24400         * The state of the display to which the window is attached, as reported
24401         * by {@link Display#getState()}.  Note that the display state constants
24402         * declared by {@link Display} do not exactly line up with the screen state
24403         * constants declared by {@link View} (there are more display states than
24404         * screen states).
24405         */
24406        int mDisplayState = Display.STATE_UNKNOWN;
24407
24408        /**
24409         * Scale factor used by the compatibility mode
24410         */
24411        float mApplicationScale;
24412
24413        /**
24414         * Indicates whether the application is in compatibility mode
24415         */
24416        boolean mScalingRequired;
24417
24418        /**
24419         * Left position of this view's window
24420         */
24421        int mWindowLeft;
24422
24423        /**
24424         * Top position of this view's window
24425         */
24426        int mWindowTop;
24427
24428        /**
24429         * Indicates whether views need to use 32-bit drawing caches
24430         */
24431        boolean mUse32BitDrawingCache;
24432
24433        /**
24434         * For windows that are full-screen but using insets to layout inside
24435         * of the screen areas, these are the current insets to appear inside
24436         * the overscan area of the display.
24437         */
24438        final Rect mOverscanInsets = new Rect();
24439
24440        /**
24441         * For windows that are full-screen but using insets to layout inside
24442         * of the screen decorations, these are the current insets for the
24443         * content of the window.
24444         */
24445        final Rect mContentInsets = new Rect();
24446
24447        /**
24448         * For windows that are full-screen but using insets to layout inside
24449         * of the screen decorations, these are the current insets for the
24450         * actual visible parts of the window.
24451         */
24452        final Rect mVisibleInsets = new Rect();
24453
24454        /**
24455         * For windows that are full-screen but using insets to layout inside
24456         * of the screen decorations, these are the current insets for the
24457         * stable system windows.
24458         */
24459        final Rect mStableInsets = new Rect();
24460
24461        /**
24462         * For windows that include areas that are not covered by real surface these are the outsets
24463         * for real surface.
24464         */
24465        final Rect mOutsets = new Rect();
24466
24467        /**
24468         * In multi-window we force show the navigation bar. Because we don't want that the surface
24469         * size changes in this mode, we instead have a flag whether the navigation bar size should
24470         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24471         */
24472        boolean mAlwaysConsumeNavBar;
24473
24474        /**
24475         * The internal insets given by this window.  This value is
24476         * supplied by the client (through
24477         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24478         * be given to the window manager when changed to be used in laying
24479         * out windows behind it.
24480         */
24481        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24482                = new ViewTreeObserver.InternalInsetsInfo();
24483
24484        /**
24485         * Set to true when mGivenInternalInsets is non-empty.
24486         */
24487        boolean mHasNonEmptyGivenInternalInsets;
24488
24489        /**
24490         * All views in the window's hierarchy that serve as scroll containers,
24491         * used to determine if the window can be resized or must be panned
24492         * to adjust for a soft input area.
24493         */
24494        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24495
24496        final KeyEvent.DispatcherState mKeyDispatchState
24497                = new KeyEvent.DispatcherState();
24498
24499        /**
24500         * Indicates whether the view's window currently has the focus.
24501         */
24502        boolean mHasWindowFocus;
24503
24504        /**
24505         * The current visibility of the window.
24506         */
24507        int mWindowVisibility;
24508
24509        /**
24510         * Indicates the time at which drawing started to occur.
24511         */
24512        long mDrawingTime;
24513
24514        /**
24515         * Indicates whether or not ignoring the DIRTY_MASK flags.
24516         */
24517        boolean mIgnoreDirtyState;
24518
24519        /**
24520         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24521         * to avoid clearing that flag prematurely.
24522         */
24523        boolean mSetIgnoreDirtyState = false;
24524
24525        /**
24526         * Indicates whether the view's window is currently in touch mode.
24527         */
24528        boolean mInTouchMode;
24529
24530        /**
24531         * Indicates whether the view has requested unbuffered input dispatching for the current
24532         * event stream.
24533         */
24534        boolean mUnbufferedDispatchRequested;
24535
24536        /**
24537         * Indicates that ViewAncestor should trigger a global layout change
24538         * the next time it performs a traversal
24539         */
24540        boolean mRecomputeGlobalAttributes;
24541
24542        /**
24543         * Always report new attributes at next traversal.
24544         */
24545        boolean mForceReportNewAttributes;
24546
24547        /**
24548         * Set during a traveral if any views want to keep the screen on.
24549         */
24550        boolean mKeepScreenOn;
24551
24552        /**
24553         * Set during a traveral if the light center needs to be updated.
24554         */
24555        boolean mNeedsUpdateLightCenter;
24556
24557        /**
24558         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24559         */
24560        int mSystemUiVisibility;
24561
24562        /**
24563         * Hack to force certain system UI visibility flags to be cleared.
24564         */
24565        int mDisabledSystemUiVisibility;
24566
24567        /**
24568         * Last global system UI visibility reported by the window manager.
24569         */
24570        int mGlobalSystemUiVisibility = -1;
24571
24572        /**
24573         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24574         * attached.
24575         */
24576        boolean mHasSystemUiListeners;
24577
24578        /**
24579         * Set if the window has requested to extend into the overscan region
24580         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24581         */
24582        boolean mOverscanRequested;
24583
24584        /**
24585         * Set if the visibility of any views has changed.
24586         */
24587        boolean mViewVisibilityChanged;
24588
24589        /**
24590         * Set to true if a view has been scrolled.
24591         */
24592        boolean mViewScrollChanged;
24593
24594        /**
24595         * Set to true if high contrast mode enabled
24596         */
24597        boolean mHighContrastText;
24598
24599        /**
24600         * Set to true if a pointer event is currently being handled.
24601         */
24602        boolean mHandlingPointerEvent;
24603
24604        /**
24605         * Global to the view hierarchy used as a temporary for dealing with
24606         * x/y points in the transparent region computations.
24607         */
24608        final int[] mTransparentLocation = new int[2];
24609
24610        /**
24611         * Global to the view hierarchy used as a temporary for dealing with
24612         * x/y points in the ViewGroup.invalidateChild implementation.
24613         */
24614        final int[] mInvalidateChildLocation = new int[2];
24615
24616        /**
24617         * Global to the view hierarchy used as a temporary for dealing with
24618         * computing absolute on-screen location.
24619         */
24620        final int[] mTmpLocation = new int[2];
24621
24622        /**
24623         * Global to the view hierarchy used as a temporary for dealing with
24624         * x/y location when view is transformed.
24625         */
24626        final float[] mTmpTransformLocation = new float[2];
24627
24628        /**
24629         * The view tree observer used to dispatch global events like
24630         * layout, pre-draw, touch mode change, etc.
24631         */
24632        final ViewTreeObserver mTreeObserver;
24633
24634        /**
24635         * A Canvas used by the view hierarchy to perform bitmap caching.
24636         */
24637        Canvas mCanvas;
24638
24639        /**
24640         * The view root impl.
24641         */
24642        final ViewRootImpl mViewRootImpl;
24643
24644        /**
24645         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24646         * handler can be used to pump events in the UI events queue.
24647         */
24648        final Handler mHandler;
24649
24650        /**
24651         * Temporary for use in computing invalidate rectangles while
24652         * calling up the hierarchy.
24653         */
24654        final Rect mTmpInvalRect = new Rect();
24655
24656        /**
24657         * Temporary for use in computing hit areas with transformed views
24658         */
24659        final RectF mTmpTransformRect = new RectF();
24660
24661        /**
24662         * Temporary for use in computing hit areas with transformed views
24663         */
24664        final RectF mTmpTransformRect1 = new RectF();
24665
24666        /**
24667         * Temporary list of rectanges.
24668         */
24669        final List<RectF> mTmpRectList = new ArrayList<>();
24670
24671        /**
24672         * Temporary for use in transforming invalidation rect
24673         */
24674        final Matrix mTmpMatrix = new Matrix();
24675
24676        /**
24677         * Temporary for use in transforming invalidation rect
24678         */
24679        final Transformation mTmpTransformation = new Transformation();
24680
24681        /**
24682         * Temporary for use in querying outlines from OutlineProviders
24683         */
24684        final Outline mTmpOutline = new Outline();
24685
24686        /**
24687         * Temporary list for use in collecting focusable descendents of a view.
24688         */
24689        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
24690
24691        /**
24692         * The id of the window for accessibility purposes.
24693         */
24694        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
24695
24696        /**
24697         * Flags related to accessibility processing.
24698         *
24699         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
24700         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
24701         */
24702        int mAccessibilityFetchFlags;
24703
24704        /**
24705         * The drawable for highlighting accessibility focus.
24706         */
24707        Drawable mAccessibilityFocusDrawable;
24708
24709        /**
24710         * Show where the margins, bounds and layout bounds are for each view.
24711         */
24712        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
24713
24714        /**
24715         * Point used to compute visible regions.
24716         */
24717        final Point mPoint = new Point();
24718
24719        /**
24720         * Used to track which View originated a requestLayout() call, used when
24721         * requestLayout() is called during layout.
24722         */
24723        View mViewRequestingLayout;
24724
24725        /**
24726         * Used to track views that need (at least) a partial relayout at their current size
24727         * during the next traversal.
24728         */
24729        List<View> mPartialLayoutViews = new ArrayList<>();
24730
24731        /**
24732         * Swapped with mPartialLayoutViews during layout to avoid concurrent
24733         * modification. Lazily assigned during ViewRootImpl layout.
24734         */
24735        List<View> mEmptyPartialLayoutViews;
24736
24737        /**
24738         * Used to track the identity of the current drag operation.
24739         */
24740        IBinder mDragToken;
24741
24742        /**
24743         * The drag shadow surface for the current drag operation.
24744         */
24745        public Surface mDragSurface;
24746
24747
24748        /**
24749         * The view that currently has a tooltip displayed.
24750         */
24751        View mTooltipHost;
24752
24753        /**
24754         * Creates a new set of attachment information with the specified
24755         * events handler and thread.
24756         *
24757         * @param handler the events handler the view must use
24758         */
24759        AttachInfo(IWindowSession session, IWindow window, Display display,
24760                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
24761                Context context) {
24762            mSession = session;
24763            mWindow = window;
24764            mWindowToken = window.asBinder();
24765            mDisplay = display;
24766            mViewRootImpl = viewRootImpl;
24767            mHandler = handler;
24768            mRootCallbacks = effectPlayer;
24769            mTreeObserver = new ViewTreeObserver(context);
24770        }
24771    }
24772
24773    /**
24774     * <p>ScrollabilityCache holds various fields used by a View when scrolling
24775     * is supported. This avoids keeping too many unused fields in most
24776     * instances of View.</p>
24777     */
24778    private static class ScrollabilityCache implements Runnable {
24779
24780        /**
24781         * Scrollbars are not visible
24782         */
24783        public static final int OFF = 0;
24784
24785        /**
24786         * Scrollbars are visible
24787         */
24788        public static final int ON = 1;
24789
24790        /**
24791         * Scrollbars are fading away
24792         */
24793        public static final int FADING = 2;
24794
24795        public boolean fadeScrollBars;
24796
24797        public int fadingEdgeLength;
24798        public int scrollBarDefaultDelayBeforeFade;
24799        public int scrollBarFadeDuration;
24800
24801        public int scrollBarSize;
24802        public int scrollBarMinTouchTarget;
24803        public ScrollBarDrawable scrollBar;
24804        public float[] interpolatorValues;
24805        public View host;
24806
24807        public final Paint paint;
24808        public final Matrix matrix;
24809        public Shader shader;
24810
24811        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
24812
24813        private static final float[] OPAQUE = { 255 };
24814        private static final float[] TRANSPARENT = { 0.0f };
24815
24816        /**
24817         * When fading should start. This time moves into the future every time
24818         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
24819         */
24820        public long fadeStartTime;
24821
24822
24823        /**
24824         * The current state of the scrollbars: ON, OFF, or FADING
24825         */
24826        public int state = OFF;
24827
24828        private int mLastColor;
24829
24830        public final Rect mScrollBarBounds = new Rect();
24831        public final Rect mScrollBarTouchBounds = new Rect();
24832
24833        public static final int NOT_DRAGGING = 0;
24834        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
24835        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
24836        public int mScrollBarDraggingState = NOT_DRAGGING;
24837
24838        public float mScrollBarDraggingPos = 0;
24839
24840        public ScrollabilityCache(ViewConfiguration configuration, View host) {
24841            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
24842            scrollBarSize = configuration.getScaledScrollBarSize();
24843            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
24844            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
24845            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
24846
24847            paint = new Paint();
24848            matrix = new Matrix();
24849            // use use a height of 1, and then wack the matrix each time we
24850            // actually use it.
24851            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
24852            paint.setShader(shader);
24853            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
24854
24855            this.host = host;
24856        }
24857
24858        public void setFadeColor(int color) {
24859            if (color != mLastColor) {
24860                mLastColor = color;
24861
24862                if (color != 0) {
24863                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
24864                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
24865                    paint.setShader(shader);
24866                    // Restore the default transfer mode (src_over)
24867                    paint.setXfermode(null);
24868                } else {
24869                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
24870                    paint.setShader(shader);
24871                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
24872                }
24873            }
24874        }
24875
24876        public void run() {
24877            long now = AnimationUtils.currentAnimationTimeMillis();
24878            if (now >= fadeStartTime) {
24879
24880                // the animation fades the scrollbars out by changing
24881                // the opacity (alpha) from fully opaque to fully
24882                // transparent
24883                int nextFrame = (int) now;
24884                int framesCount = 0;
24885
24886                Interpolator interpolator = scrollBarInterpolator;
24887
24888                // Start opaque
24889                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
24890
24891                // End transparent
24892                nextFrame += scrollBarFadeDuration;
24893                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
24894
24895                state = FADING;
24896
24897                // Kick off the fade animation
24898                host.invalidate(true);
24899            }
24900        }
24901    }
24902
24903    /**
24904     * Resuable callback for sending
24905     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
24906     */
24907    private class SendViewScrolledAccessibilityEvent implements Runnable {
24908        public volatile boolean mIsPending;
24909
24910        public void run() {
24911            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
24912            mIsPending = false;
24913        }
24914    }
24915
24916    /**
24917     * <p>
24918     * This class represents a delegate that can be registered in a {@link View}
24919     * to enhance accessibility support via composition rather via inheritance.
24920     * It is specifically targeted to widget developers that extend basic View
24921     * classes i.e. classes in package android.view, that would like their
24922     * applications to be backwards compatible.
24923     * </p>
24924     * <div class="special reference">
24925     * <h3>Developer Guides</h3>
24926     * <p>For more information about making applications accessible, read the
24927     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
24928     * developer guide.</p>
24929     * </div>
24930     * <p>
24931     * A scenario in which a developer would like to use an accessibility delegate
24932     * is overriding a method introduced in a later API version than the minimal API
24933     * version supported by the application. For example, the method
24934     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
24935     * in API version 4 when the accessibility APIs were first introduced. If a
24936     * developer would like his application to run on API version 4 devices (assuming
24937     * all other APIs used by the application are version 4 or lower) and take advantage
24938     * of this method, instead of overriding the method which would break the application's
24939     * backwards compatibility, he can override the corresponding method in this
24940     * delegate and register the delegate in the target View if the API version of
24941     * the system is high enough, i.e. the API version is the same as or higher than the API
24942     * version that introduced
24943     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
24944     * </p>
24945     * <p>
24946     * Here is an example implementation:
24947     * </p>
24948     * <code><pre><p>
24949     * if (Build.VERSION.SDK_INT >= 14) {
24950     *     // If the API version is equal of higher than the version in
24951     *     // which onInitializeAccessibilityNodeInfo was introduced we
24952     *     // register a delegate with a customized implementation.
24953     *     View view = findViewById(R.id.view_id);
24954     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
24955     *         public void onInitializeAccessibilityNodeInfo(View host,
24956     *                 AccessibilityNodeInfo info) {
24957     *             // Let the default implementation populate the info.
24958     *             super.onInitializeAccessibilityNodeInfo(host, info);
24959     *             // Set some other information.
24960     *             info.setEnabled(host.isEnabled());
24961     *         }
24962     *     });
24963     * }
24964     * </code></pre></p>
24965     * <p>
24966     * This delegate contains methods that correspond to the accessibility methods
24967     * in View. If a delegate has been specified the implementation in View hands
24968     * off handling to the corresponding method in this delegate. The default
24969     * implementation the delegate methods behaves exactly as the corresponding
24970     * method in View for the case of no accessibility delegate been set. Hence,
24971     * to customize the behavior of a View method, clients can override only the
24972     * corresponding delegate method without altering the behavior of the rest
24973     * accessibility related methods of the host view.
24974     * </p>
24975     * <p>
24976     * <strong>Note:</strong> On platform versions prior to
24977     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
24978     * views in the {@code android.widget.*} package are called <i>before</i>
24979     * host methods. This prevents certain properties such as class name from
24980     * being modified by overriding
24981     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
24982     * as any changes will be overwritten by the host class.
24983     * <p>
24984     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
24985     * methods are called <i>after</i> host methods, which all properties to be
24986     * modified without being overwritten by the host class.
24987     */
24988    public static class AccessibilityDelegate {
24989
24990        /**
24991         * Sends an accessibility event of the given type. If accessibility is not
24992         * enabled this method has no effect.
24993         * <p>
24994         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
24995         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
24996         * been set.
24997         * </p>
24998         *
24999         * @param host The View hosting the delegate.
25000         * @param eventType The type of the event to send.
25001         *
25002         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25003         */
25004        public void sendAccessibilityEvent(View host, int eventType) {
25005            host.sendAccessibilityEventInternal(eventType);
25006        }
25007
25008        /**
25009         * Performs the specified accessibility action on the view. For
25010         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25011         * <p>
25012         * The default implementation behaves as
25013         * {@link View#performAccessibilityAction(int, Bundle)
25014         *  View#performAccessibilityAction(int, Bundle)} for the case of
25015         *  no accessibility delegate been set.
25016         * </p>
25017         *
25018         * @param action The action to perform.
25019         * @return Whether the action was performed.
25020         *
25021         * @see View#performAccessibilityAction(int, Bundle)
25022         *      View#performAccessibilityAction(int, Bundle)
25023         */
25024        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25025            return host.performAccessibilityActionInternal(action, args);
25026        }
25027
25028        /**
25029         * Sends an accessibility event. This method behaves exactly as
25030         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25031         * empty {@link AccessibilityEvent} and does not perform a check whether
25032         * accessibility is enabled.
25033         * <p>
25034         * The default implementation behaves as
25035         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25036         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25037         * the case of no accessibility delegate been set.
25038         * </p>
25039         *
25040         * @param host The View hosting the delegate.
25041         * @param event The event to send.
25042         *
25043         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25044         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25045         */
25046        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25047            host.sendAccessibilityEventUncheckedInternal(event);
25048        }
25049
25050        /**
25051         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25052         * to its children for adding their text content to the event.
25053         * <p>
25054         * The default implementation behaves as
25055         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25056         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25057         * the case of no accessibility delegate been set.
25058         * </p>
25059         *
25060         * @param host The View hosting the delegate.
25061         * @param event The event.
25062         * @return True if the event population was completed.
25063         *
25064         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25065         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25066         */
25067        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25068            return host.dispatchPopulateAccessibilityEventInternal(event);
25069        }
25070
25071        /**
25072         * Gives a chance to the host View to populate the accessibility event with its
25073         * text content.
25074         * <p>
25075         * The default implementation behaves as
25076         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25077         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25078         * the case of no accessibility delegate been set.
25079         * </p>
25080         *
25081         * @param host The View hosting the delegate.
25082         * @param event The accessibility event which to populate.
25083         *
25084         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25085         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25086         */
25087        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25088            host.onPopulateAccessibilityEventInternal(event);
25089        }
25090
25091        /**
25092         * Initializes an {@link AccessibilityEvent} with information about the
25093         * the host View which is the event source.
25094         * <p>
25095         * The default implementation behaves as
25096         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25097         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25098         * the case of no accessibility delegate been set.
25099         * </p>
25100         *
25101         * @param host The View hosting the delegate.
25102         * @param event The event to initialize.
25103         *
25104         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25105         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25106         */
25107        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25108            host.onInitializeAccessibilityEventInternal(event);
25109        }
25110
25111        /**
25112         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25113         * <p>
25114         * The default implementation behaves as
25115         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25116         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25117         * the case of no accessibility delegate been set.
25118         * </p>
25119         *
25120         * @param host The View hosting the delegate.
25121         * @param info The instance to initialize.
25122         *
25123         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25124         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25125         */
25126        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25127            host.onInitializeAccessibilityNodeInfoInternal(info);
25128        }
25129
25130        /**
25131         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25132         * additional data.
25133         * <p>
25134         * This method only needs to be implemented if the View offers to provide additional data.
25135         * </p>
25136         * <p>
25137         * The default implementation behaves as
25138         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
25139         * for the case where no accessibility delegate is set.
25140         * </p>
25141         *
25142         * @param host The View hosting the delegate. Never {@code null}.
25143         * @param info The info to which to add the extra data. Never {@code null}.
25144         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25145         *                     extra data should be added to the {@link Bundle} returned by
25146         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25147         *                     {@code null}.
25148         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25149         *                  May be {@code null} if the if the service provided no arguments.
25150         *
25151         * @see AccessibilityNodeInfo#setExtraAvailableData
25152         */
25153        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25154                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25155                @Nullable Bundle arguments) {
25156            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25157        }
25158
25159        /**
25160         * Called when a child of the host View has requested sending an
25161         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25162         * to augment the event.
25163         * <p>
25164         * The default implementation behaves as
25165         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25166         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25167         * the case of no accessibility delegate been set.
25168         * </p>
25169         *
25170         * @param host The View hosting the delegate.
25171         * @param child The child which requests sending the event.
25172         * @param event The event to be sent.
25173         * @return True if the event should be sent
25174         *
25175         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25176         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25177         */
25178        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25179                AccessibilityEvent event) {
25180            return host.onRequestSendAccessibilityEventInternal(child, event);
25181        }
25182
25183        /**
25184         * Gets the provider for managing a virtual view hierarchy rooted at this View
25185         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25186         * that explore the window content.
25187         * <p>
25188         * The default implementation behaves as
25189         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25190         * the case of no accessibility delegate been set.
25191         * </p>
25192         *
25193         * @return The provider.
25194         *
25195         * @see AccessibilityNodeProvider
25196         */
25197        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25198            return null;
25199        }
25200
25201        /**
25202         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25203         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25204         * This method is responsible for obtaining an accessibility node info from a
25205         * pool of reusable instances and calling
25206         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25207         * view to initialize the former.
25208         * <p>
25209         * <strong>Note:</strong> The client is responsible for recycling the obtained
25210         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25211         * creation.
25212         * </p>
25213         * <p>
25214         * The default implementation behaves as
25215         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25216         * the case of no accessibility delegate been set.
25217         * </p>
25218         * @return A populated {@link AccessibilityNodeInfo}.
25219         *
25220         * @see AccessibilityNodeInfo
25221         *
25222         * @hide
25223         */
25224        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25225            return host.createAccessibilityNodeInfoInternal();
25226        }
25227    }
25228
25229    private static class MatchIdPredicate implements Predicate<View> {
25230        public int mId;
25231
25232        @Override
25233        public boolean test(View view) {
25234            return (view.mID == mId);
25235        }
25236    }
25237
25238    private static class MatchLabelForPredicate implements Predicate<View> {
25239        private int mLabeledId;
25240
25241        @Override
25242        public boolean test(View view) {
25243            return (view.mLabelForId == mLabeledId);
25244        }
25245    }
25246
25247    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25248        private int mChangeTypes = 0;
25249        private boolean mPosted;
25250        private boolean mPostedWithDelay;
25251        private long mLastEventTimeMillis;
25252
25253        @Override
25254        public void run() {
25255            mPosted = false;
25256            mPostedWithDelay = false;
25257            mLastEventTimeMillis = SystemClock.uptimeMillis();
25258            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25259                final AccessibilityEvent event = AccessibilityEvent.obtain();
25260                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25261                event.setContentChangeTypes(mChangeTypes);
25262                sendAccessibilityEventUnchecked(event);
25263            }
25264            mChangeTypes = 0;
25265        }
25266
25267        public void runOrPost(int changeType) {
25268            mChangeTypes |= changeType;
25269
25270            // If this is a live region or the child of a live region, collect
25271            // all events from this frame and send them on the next frame.
25272            if (inLiveRegion()) {
25273                // If we're already posted with a delay, remove that.
25274                if (mPostedWithDelay) {
25275                    removeCallbacks(this);
25276                    mPostedWithDelay = false;
25277                }
25278                // Only post if we're not already posted.
25279                if (!mPosted) {
25280                    post(this);
25281                    mPosted = true;
25282                }
25283                return;
25284            }
25285
25286            if (mPosted) {
25287                return;
25288            }
25289
25290            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25291            final long minEventIntevalMillis =
25292                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25293            if (timeSinceLastMillis >= minEventIntevalMillis) {
25294                removeCallbacks(this);
25295                run();
25296            } else {
25297                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25298                mPostedWithDelay = true;
25299            }
25300        }
25301    }
25302
25303    private boolean inLiveRegion() {
25304        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25305            return true;
25306        }
25307
25308        ViewParent parent = getParent();
25309        while (parent instanceof View) {
25310            if (((View) parent).getAccessibilityLiveRegion()
25311                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25312                return true;
25313            }
25314            parent = parent.getParent();
25315        }
25316
25317        return false;
25318    }
25319
25320    /**
25321     * Dump all private flags in readable format, useful for documentation and
25322     * sanity checking.
25323     */
25324    private static void dumpFlags() {
25325        final HashMap<String, String> found = Maps.newHashMap();
25326        try {
25327            for (Field field : View.class.getDeclaredFields()) {
25328                final int modifiers = field.getModifiers();
25329                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25330                    if (field.getType().equals(int.class)) {
25331                        final int value = field.getInt(null);
25332                        dumpFlag(found, field.getName(), value);
25333                    } else if (field.getType().equals(int[].class)) {
25334                        final int[] values = (int[]) field.get(null);
25335                        for (int i = 0; i < values.length; i++) {
25336                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25337                        }
25338                    }
25339                }
25340            }
25341        } catch (IllegalAccessException e) {
25342            throw new RuntimeException(e);
25343        }
25344
25345        final ArrayList<String> keys = Lists.newArrayList();
25346        keys.addAll(found.keySet());
25347        Collections.sort(keys);
25348        for (String key : keys) {
25349            Log.d(VIEW_LOG_TAG, found.get(key));
25350        }
25351    }
25352
25353    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25354        // Sort flags by prefix, then by bits, always keeping unique keys
25355        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25356        final int prefix = name.indexOf('_');
25357        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25358        final String output = bits + " " + name;
25359        found.put(key, output);
25360    }
25361
25362    /** {@hide} */
25363    public void encode(@NonNull ViewHierarchyEncoder stream) {
25364        stream.beginObject(this);
25365        encodeProperties(stream);
25366        stream.endObject();
25367    }
25368
25369    /** {@hide} */
25370    @CallSuper
25371    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25372        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25373        if (resolveId instanceof String) {
25374            stream.addProperty("id", (String) resolveId);
25375        } else {
25376            stream.addProperty("id", mID);
25377        }
25378
25379        stream.addProperty("misc:transformation.alpha",
25380                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25381        stream.addProperty("misc:transitionName", getTransitionName());
25382
25383        // layout
25384        stream.addProperty("layout:left", mLeft);
25385        stream.addProperty("layout:right", mRight);
25386        stream.addProperty("layout:top", mTop);
25387        stream.addProperty("layout:bottom", mBottom);
25388        stream.addProperty("layout:width", getWidth());
25389        stream.addProperty("layout:height", getHeight());
25390        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25391        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25392        stream.addProperty("layout:hasTransientState", hasTransientState());
25393        stream.addProperty("layout:baseline", getBaseline());
25394
25395        // layout params
25396        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25397        if (layoutParams != null) {
25398            stream.addPropertyKey("layoutParams");
25399            layoutParams.encode(stream);
25400        }
25401
25402        // scrolling
25403        stream.addProperty("scrolling:scrollX", mScrollX);
25404        stream.addProperty("scrolling:scrollY", mScrollY);
25405
25406        // padding
25407        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25408        stream.addProperty("padding:paddingRight", mPaddingRight);
25409        stream.addProperty("padding:paddingTop", mPaddingTop);
25410        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25411        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25412        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25413        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25414        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25415        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25416
25417        // measurement
25418        stream.addProperty("measurement:minHeight", mMinHeight);
25419        stream.addProperty("measurement:minWidth", mMinWidth);
25420        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25421        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25422
25423        // drawing
25424        stream.addProperty("drawing:elevation", getElevation());
25425        stream.addProperty("drawing:translationX", getTranslationX());
25426        stream.addProperty("drawing:translationY", getTranslationY());
25427        stream.addProperty("drawing:translationZ", getTranslationZ());
25428        stream.addProperty("drawing:rotation", getRotation());
25429        stream.addProperty("drawing:rotationX", getRotationX());
25430        stream.addProperty("drawing:rotationY", getRotationY());
25431        stream.addProperty("drawing:scaleX", getScaleX());
25432        stream.addProperty("drawing:scaleY", getScaleY());
25433        stream.addProperty("drawing:pivotX", getPivotX());
25434        stream.addProperty("drawing:pivotY", getPivotY());
25435        stream.addProperty("drawing:opaque", isOpaque());
25436        stream.addProperty("drawing:alpha", getAlpha());
25437        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25438        stream.addProperty("drawing:shadow", hasShadow());
25439        stream.addProperty("drawing:solidColor", getSolidColor());
25440        stream.addProperty("drawing:layerType", mLayerType);
25441        stream.addProperty("drawing:willNotDraw", willNotDraw());
25442        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25443        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25444        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25445        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25446
25447        // focus
25448        stream.addProperty("focus:hasFocus", hasFocus());
25449        stream.addProperty("focus:isFocused", isFocused());
25450        stream.addProperty("focus:isFocusable", isFocusable());
25451        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25452
25453        stream.addProperty("misc:clickable", isClickable());
25454        stream.addProperty("misc:pressed", isPressed());
25455        stream.addProperty("misc:selected", isSelected());
25456        stream.addProperty("misc:touchMode", isInTouchMode());
25457        stream.addProperty("misc:hovered", isHovered());
25458        stream.addProperty("misc:activated", isActivated());
25459
25460        stream.addProperty("misc:visibility", getVisibility());
25461        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25462        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25463
25464        stream.addProperty("misc:enabled", isEnabled());
25465        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25466        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25467
25468        // theme attributes
25469        Resources.Theme theme = getContext().getTheme();
25470        if (theme != null) {
25471            stream.addPropertyKey("theme");
25472            theme.encode(stream);
25473        }
25474
25475        // view attribute information
25476        int n = mAttributes != null ? mAttributes.length : 0;
25477        stream.addProperty("meta:__attrCount__", n/2);
25478        for (int i = 0; i < n; i += 2) {
25479            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25480        }
25481
25482        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25483
25484        // text
25485        stream.addProperty("text:textDirection", getTextDirection());
25486        stream.addProperty("text:textAlignment", getTextAlignment());
25487
25488        // accessibility
25489        CharSequence contentDescription = getContentDescription();
25490        stream.addProperty("accessibility:contentDescription",
25491                contentDescription == null ? "" : contentDescription.toString());
25492        stream.addProperty("accessibility:labelFor", getLabelFor());
25493        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25494    }
25495
25496    /**
25497     * Determine if this view is rendered on a round wearable device and is the main view
25498     * on the screen.
25499     */
25500    boolean shouldDrawRoundScrollbar() {
25501        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25502            return false;
25503        }
25504
25505        final View rootView = getRootView();
25506        final WindowInsets insets = getRootWindowInsets();
25507
25508        int height = getHeight();
25509        int width = getWidth();
25510        int displayHeight = rootView.getHeight();
25511        int displayWidth = rootView.getWidth();
25512
25513        if (height != displayHeight || width != displayWidth) {
25514            return false;
25515        }
25516
25517        getLocationInWindow(mAttachInfo.mTmpLocation);
25518        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25519                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25520    }
25521
25522    /**
25523     * Sets the tooltip text which will be displayed in a small popup next to the view.
25524     * <p>
25525     * The tooltip will be displayed:
25526     * <ul>
25527     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
25528     * menu). </li>
25529     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25530     * </ul>
25531     * <p>
25532     * <strong>Note:</strong> Do not override this method, as it will have no
25533     * effect on the text displayed in the tooltip.
25534     *
25535     * @param tooltipText the tooltip text, or null if no tooltip is required
25536     * @see #getTooltipText()
25537     * @attr ref android.R.styleable#View_tooltipText
25538     */
25539    public void setTooltipText(@Nullable CharSequence tooltipText) {
25540        if (TextUtils.isEmpty(tooltipText)) {
25541            setFlags(0, TOOLTIP);
25542            hideTooltip();
25543            mTooltipInfo = null;
25544        } else {
25545            setFlags(TOOLTIP, TOOLTIP);
25546            if (mTooltipInfo == null) {
25547                mTooltipInfo = new TooltipInfo();
25548                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25549                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25550            }
25551            mTooltipInfo.mTooltipText = tooltipText;
25552            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25553                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25554            }
25555        }
25556    }
25557
25558    /**
25559     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25560     */
25561    public void setTooltip(@Nullable CharSequence tooltipText) {
25562        setTooltipText(tooltipText);
25563    }
25564
25565    /**
25566     * Returns the view's tooltip text.
25567     *
25568     * <strong>Note:</strong> Do not override this method, as it will have no
25569     * effect on the text displayed in the tooltip. You must call
25570     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25571     *
25572     * @return the tooltip text
25573     * @see #setTooltipText(CharSequence)
25574     * @attr ref android.R.styleable#View_tooltipText
25575     */
25576    @Nullable
25577    public CharSequence getTooltipText() {
25578        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25579    }
25580
25581    /**
25582     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25583     */
25584    @Nullable
25585    public CharSequence getTooltip() {
25586        return getTooltipText();
25587    }
25588
25589    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25590        if (mAttachInfo == null || mTooltipInfo == null) {
25591            return false;
25592        }
25593        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25594            return false;
25595        }
25596        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25597            return false;
25598        }
25599        hideTooltip();
25600        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25601        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25602        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25603        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25604        mAttachInfo.mTooltipHost = this;
25605        return true;
25606    }
25607
25608    void hideTooltip() {
25609        if (mTooltipInfo == null) {
25610            return;
25611        }
25612        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25613        if (mTooltipInfo.mTooltipPopup == null) {
25614            return;
25615        }
25616        mTooltipInfo.mTooltipPopup.hide();
25617        mTooltipInfo.mTooltipPopup = null;
25618        mTooltipInfo.mTooltipFromLongClick = false;
25619        if (mAttachInfo != null) {
25620            mAttachInfo.mTooltipHost = null;
25621        }
25622    }
25623
25624    private boolean showLongClickTooltip(int x, int y) {
25625        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25626        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25627        return showTooltip(x, y, true);
25628    }
25629
25630    private void showHoverTooltip() {
25631        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25632    }
25633
25634    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25635        if (mTooltipInfo == null) {
25636            return false;
25637        }
25638        switch(event.getAction()) {
25639            case MotionEvent.ACTION_HOVER_MOVE:
25640                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25641                    break;
25642                }
25643                if (!mTooltipInfo.mTooltipFromLongClick) {
25644                    if (mTooltipInfo.mTooltipPopup == null) {
25645                        // Schedule showing the tooltip after a timeout.
25646                        mTooltipInfo.mAnchorX = (int) event.getX();
25647                        mTooltipInfo.mAnchorY = (int) event.getY();
25648                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25649                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25650                                ViewConfiguration.getHoverTooltipShowTimeout());
25651                    }
25652
25653                    // Hide hover-triggered tooltip after a period of inactivity.
25654                    // Match the timeout used by NativeInputManager to hide the mouse pointer
25655                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
25656                    final int timeout;
25657                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
25658                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
25659                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
25660                    } else {
25661                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
25662                    }
25663                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25664                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
25665                }
25666                return true;
25667
25668            case MotionEvent.ACTION_HOVER_EXIT:
25669                if (!mTooltipInfo.mTooltipFromLongClick) {
25670                    hideTooltip();
25671                }
25672                break;
25673        }
25674        return false;
25675    }
25676
25677    void handleTooltipKey(KeyEvent event) {
25678        switch (event.getAction()) {
25679            case KeyEvent.ACTION_DOWN:
25680                if (event.getRepeatCount() == 0) {
25681                    hideTooltip();
25682                }
25683                break;
25684
25685            case KeyEvent.ACTION_UP:
25686                handleTooltipUp();
25687                break;
25688        }
25689    }
25690
25691    private void handleTooltipUp() {
25692        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25693            return;
25694        }
25695        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25696        postDelayed(mTooltipInfo.mHideTooltipRunnable,
25697                ViewConfiguration.getLongPressTooltipHideTimeout());
25698    }
25699
25700    private int getFocusableAttribute(TypedArray attributes) {
25701        TypedValue val = new TypedValue();
25702        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
25703            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
25704                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
25705            } else {
25706                return val.data;
25707            }
25708        } else {
25709            return FOCUSABLE_AUTO;
25710        }
25711    }
25712
25713    /**
25714     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
25715     * is not showing.
25716     * @hide
25717     */
25718    @TestApi
25719    public View getTooltipView() {
25720        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25721            return null;
25722        }
25723        return mTooltipInfo.mTooltipPopup.getContentView();
25724    }
25725}
25726